github.com/DataDog/datadog-agent/pkg/security/secl@v0.55.0-devel.0.20240517055856-10c4965fea94/model/unmarshallers_linux.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the Apache License Version 2.0. 3 // This product includes software developed at Datadog (https://www.datadoghq.com/). 4 // Copyright 2016-present Datadog, Inc. 5 6 // Package model holds model related files 7 package model 8 9 import ( 10 "encoding/binary" 11 "fmt" 12 "math/bits" 13 "strings" 14 "time" 15 16 "github.com/DataDog/datadog-agent/pkg/security/secl/compiler/eval" 17 ) 18 19 func validateReadSize(size, read int) (int, error) { 20 if size != read { 21 return 0, fmt.Errorf("expected %d, read %d: %w", size, read, ErrIncorrectDataSize) 22 } 23 return read, nil 24 } 25 26 // BinaryUnmarshaler interface implemented by every event type 27 type BinaryUnmarshaler interface { 28 UnmarshalBinary(data []byte) (int, error) 29 } 30 31 // UnmarshalBinary unmarshalls a binary representation of itself 32 func (e *ContainerContext) UnmarshalBinary(data []byte) (int, error) { 33 id, err := UnmarshalString(data, ContainerIDLen) 34 if err != nil { 35 return 0, err 36 } 37 e.ID = id 38 39 return ContainerIDLen, nil 40 } 41 42 // UnmarshalBinary unmarshalls a binary representation of itself 43 func (e *ChmodEvent) UnmarshalBinary(data []byte) (int, error) { 44 n, err := UnmarshalBinary(data, &e.SyscallEvent, &e.File) 45 if err != nil { 46 return n, err 47 } 48 49 data = data[n:] 50 if len(data) < 4 { 51 return n, ErrNotEnoughData 52 } 53 54 e.Mode = binary.NativeEndian.Uint32(data[0:4]) 55 return n + 4, nil 56 } 57 58 // UnmarshalBinary unmarshalls a binary representation of itself 59 func (e *ChownEvent) UnmarshalBinary(data []byte) (int, error) { 60 n, err := UnmarshalBinary(data, &e.SyscallEvent, &e.File) 61 if err != nil { 62 return n, err 63 } 64 65 data = data[n:] 66 if len(data) < 8 { 67 return n, ErrNotEnoughData 68 } 69 70 // First convert to int32 to sign extend, then convert to int64 71 e.UID = int64(int32(binary.NativeEndian.Uint32(data[0:4]))) 72 e.GID = int64(int32(binary.NativeEndian.Uint32(data[4:8]))) 73 return n + 8, nil 74 } 75 76 // UnmarshalBinary unmarshalls a binary representation of itself 77 func (e *Event) UnmarshalBinary(data []byte) (int, error) { 78 if len(data) < 24 { 79 return 0, ErrNotEnoughData 80 } 81 82 e.TimestampRaw = binary.NativeEndian.Uint64(data[8:16]) 83 e.Type = binary.NativeEndian.Uint32(data[16:20]) 84 e.Flags = binary.NativeEndian.Uint32(data[20:24]) 85 86 return 24, nil 87 } 88 89 // UnmarshalBinary unmarshalls a binary representation of itself 90 func (e *SetuidEvent) UnmarshalBinary(data []byte) (int, error) { 91 if len(data) < 16 { 92 return 0, ErrNotEnoughData 93 } 94 e.UID = binary.NativeEndian.Uint32(data[0:4]) 95 e.EUID = binary.NativeEndian.Uint32(data[4:8]) 96 e.FSUID = binary.NativeEndian.Uint32(data[8:12]) 97 return 16, nil 98 } 99 100 // UnmarshalBinary unmarshalls a binary representation of itself 101 func (e *SetgidEvent) UnmarshalBinary(data []byte) (int, error) { 102 if len(data) < 16 { 103 return 0, ErrNotEnoughData 104 } 105 e.GID = binary.NativeEndian.Uint32(data[0:4]) 106 e.EGID = binary.NativeEndian.Uint32(data[4:8]) 107 e.FSGID = binary.NativeEndian.Uint32(data[8:12]) 108 return 16, nil 109 } 110 111 // UnmarshalBinary unmarshalls a binary representation of itself 112 func (e *CapsetEvent) UnmarshalBinary(data []byte) (int, error) { 113 if len(data) < 16 { 114 return 0, ErrNotEnoughData 115 } 116 e.CapEffective = binary.NativeEndian.Uint64(data[0:8]) 117 e.CapPermitted = binary.NativeEndian.Uint64(data[8:16]) 118 return 16, nil 119 } 120 121 // UnmarshalBinary unmarshalls a binary representation of itself 122 func (e *Credentials) UnmarshalBinary(data []byte) (int, error) { 123 if len(data) < 40 { 124 return 0, ErrNotEnoughData 125 } 126 127 e.UID = binary.NativeEndian.Uint32(data[0:4]) 128 e.GID = binary.NativeEndian.Uint32(data[4:8]) 129 e.EUID = binary.NativeEndian.Uint32(data[8:12]) 130 e.EGID = binary.NativeEndian.Uint32(data[12:16]) 131 e.FSUID = binary.NativeEndian.Uint32(data[16:20]) 132 e.FSGID = binary.NativeEndian.Uint32(data[20:24]) 133 e.CapEffective = binary.NativeEndian.Uint64(data[24:32]) 134 e.CapPermitted = binary.NativeEndian.Uint64(data[32:40]) 135 return 40, nil 136 } 137 138 func unmarshalTime(data []byte) time.Time { 139 if t := int64(binary.NativeEndian.Uint64(data)); t != 0 { 140 return time.Unix(0, t) 141 } 142 return time.Time{} 143 } 144 145 // isValidTTYName uses a naive assumption as other tty driver may create tty with other prefix 146 func isValidTTYName(ttyName string) bool { 147 return IsPrintableASCII(ttyName) && (strings.HasPrefix(ttyName, "tty") || strings.HasPrefix(ttyName, "pts")) 148 } 149 150 // UnmarshalProcEntryBinary unmarshalls process_entry_t from process.h 151 func (e *Process) UnmarshalProcEntryBinary(data []byte) (int, error) { 152 const size = 160 153 if len(data) < size { 154 return 0, ErrNotEnoughData 155 } 156 157 read, err := UnmarshalBinary(data, &e.FileEvent) 158 if err != nil { 159 return 0, err 160 } 161 162 e.ExecTime = unmarshalTime(data[read : read+8]) 163 read += 8 164 165 var ttyRaw [64]byte 166 SliceToArray(data[read:read+64], ttyRaw[:]) 167 ttyName, err := UnmarshalString(ttyRaw[:], 64) 168 if err != nil { 169 return 0, err 170 } 171 if isValidTTYName(ttyName) { 172 e.TTYName = ttyName 173 } 174 read += 64 175 176 var commRaw [16]byte 177 SliceToArray(data[read:read+16], commRaw[:]) 178 e.Comm, err = UnmarshalString(commRaw[:], 16) 179 if err != nil { 180 return 0, err 181 } 182 read += 16 183 184 return validateReadSize(size, read) 185 } 186 187 // UnmarshalPidCacheBinary unmarshalls Unmarshal pid_cache_t 188 func (e *Process) UnmarshalPidCacheBinary(data []byte) (int, error) { 189 const size = 80 190 if len(data) < size { 191 return 0, ErrNotEnoughData 192 } 193 194 var read int 195 196 // Unmarshal pid_cache_t 197 cookie := binary.NativeEndian.Uint64(data[0:SizeOfCookie]) 198 if cookie > 0 { 199 e.Cookie = cookie 200 } 201 e.PPid = binary.NativeEndian.Uint32(data[8:12]) 202 203 // padding 204 205 e.ForkTime = unmarshalTime(data[16:24]) 206 e.ExitTime = unmarshalTime(data[24:32]) 207 e.UserSession.ID = binary.NativeEndian.Uint64(data[32:40]) 208 209 // Unmarshal the credentials contained in pid_cache_t 210 read, err := UnmarshalBinary(data[40:], &e.Credentials) 211 if err != nil { 212 return 0, err 213 } 214 read += 40 215 216 return validateReadSize(size, read) 217 } 218 219 // UnmarshalBinary unmarshalls a binary representation of itself 220 func (e *Process) UnmarshalBinary(data []byte) (int, error) { 221 const size = 272 // size of struct exec_event_t starting from process_entry_t, inclusive 222 if len(data) < size { 223 return 0, ErrNotEnoughData 224 } 225 var read int 226 227 n, err := e.UnmarshalProcEntryBinary((data)) 228 if err != nil { 229 return 0, err 230 } 231 read += n 232 233 n, err = e.UnmarshalPidCacheBinary((data[read:])) 234 if err != nil { 235 return 0, err 236 } 237 read += n 238 239 // interpreter part 240 var pathKey PathKey 241 242 n, err = pathKey.UnmarshalBinary(data[read:]) 243 if err != nil { 244 return 0, err 245 } 246 read += n 247 248 // TODO: Is there a better way to determine if there's no interpreter? 249 if e.FileEvent.Inode != pathKey.Inode || e.FileEvent.MountID != pathKey.MountID { 250 e.LinuxBinprm.FileEvent.PathKey = pathKey 251 } 252 253 if len(data[read:]) < 16 { 254 return 0, ErrNotEnoughData 255 } 256 257 e.ArgsID = binary.NativeEndian.Uint32(data[read : read+4]) 258 e.ArgsTruncated = binary.NativeEndian.Uint32(data[read+4:read+8]) == 1 259 read += 8 260 261 e.EnvsID = binary.NativeEndian.Uint32(data[read : read+4]) 262 e.EnvsTruncated = binary.NativeEndian.Uint32(data[read+4:read+8]) == 1 263 read += 8 264 265 return validateReadSize(size, read) 266 } 267 268 // UnmarshalBinary unmarshalls a binary representation of itself 269 func (e *ExitEvent) UnmarshalBinary(data []byte) (int, error) { 270 // Unmarshal exit code 271 if len(data) < 4 { 272 return 0, ErrNotEnoughData 273 } 274 275 exitStatus := binary.NativeEndian.Uint32(data[0:4]) 276 if exitStatus&0x7F == 0x00 { // process terminated normally 277 e.Cause = uint32(ExitExited) 278 e.Code = (exitStatus >> 8) & 0xFF 279 } else if exitStatus&0x7F != 0x7F { // process terminated because of a signal 280 if exitStatus&0x80 == 0x80 { // coredump signal 281 e.Cause = uint32(ExitCoreDumped) 282 e.Code = exitStatus & 0x7F 283 } else { // other signals 284 e.Cause = uint32(ExitSignaled) 285 e.Code = exitStatus & 0x7F 286 } 287 } 288 289 return 4, nil 290 } 291 292 // UnmarshalBinary unmarshalls a binary representation of itself 293 func (e *InvalidateDentryEvent) UnmarshalBinary(data []byte) (int, error) { 294 if len(data) < 16 { 295 return 0, ErrNotEnoughData 296 } 297 298 e.Inode = binary.NativeEndian.Uint64(data[0:8]) 299 e.MountID = binary.NativeEndian.Uint32(data[8:12]) 300 // padding 301 302 return 16, nil 303 } 304 305 // UnmarshalBinary unmarshalls a binary representation of itself 306 func (e *ArgsEnvsEvent) UnmarshalBinary(data []byte) (int, error) { 307 if len(data) < MaxArgEnvSize+8 { 308 return 0, ErrNotEnoughData 309 } 310 311 e.ID = binary.NativeEndian.Uint32(data[0:4]) 312 e.Size = binary.NativeEndian.Uint32(data[4:8]) 313 if e.Size > MaxArgEnvSize { 314 e.Size = MaxArgEnvSize 315 } 316 SliceToArray(data[8:MaxArgEnvSize+8], e.ValuesRaw[:]) 317 318 return MaxArgEnvSize + 8, nil 319 } 320 321 // UnmarshalBinary unmarshals the given content 322 func (p *PathKey) UnmarshalBinary(data []byte) (int, error) { 323 if len(data) < 16 { 324 return 0, ErrNotEnoughData 325 } 326 p.Inode = binary.NativeEndian.Uint64(data[0:8]) 327 p.MountID = binary.NativeEndian.Uint32(data[8:12]) 328 p.PathID = binary.NativeEndian.Uint32(data[12:16]) 329 330 return 16, nil 331 } 332 333 // UnmarshalBinary unmarshalls a binary representation of itself 334 func (e *FileFields) UnmarshalBinary(data []byte) (int, error) { 335 if len(data) < 72 { 336 return 0, ErrNotEnoughData 337 } 338 339 n, err := e.PathKey.UnmarshalBinary(data) 340 if err != nil { 341 return n, err 342 } 343 data = data[n:] 344 345 e.Device = binary.NativeEndian.Uint32(data[0:4]) 346 347 e.Flags = int32(binary.NativeEndian.Uint32(data[4:8])) 348 349 e.UID = binary.NativeEndian.Uint32(data[8:12]) 350 e.GID = binary.NativeEndian.Uint32(data[12:16]) 351 e.NLink = binary.NativeEndian.Uint32(data[16:20]) 352 e.Mode = binary.NativeEndian.Uint16(data[20:22]) 353 354 timeSec := binary.NativeEndian.Uint64(data[24:32]) 355 timeNsec := binary.NativeEndian.Uint64(data[32:40]) 356 e.CTime = uint64(time.Unix(int64(timeSec), int64(timeNsec)).UnixNano()) 357 358 timeSec = binary.NativeEndian.Uint64(data[40:48]) 359 timeNsec = binary.NativeEndian.Uint64(data[48:56]) 360 e.MTime = uint64(time.Unix(int64(timeSec), int64(timeNsec)).UnixNano()) 361 362 return 72, nil 363 } 364 365 // UnmarshalBinary unmarshalls a binary representation of itself 366 func (e *FileEvent) UnmarshalBinary(data []byte) (int, error) { 367 return UnmarshalBinary(data, &e.FileFields) 368 } 369 370 // UnmarshalBinary unmarshalls a binary representation of itself 371 func (e *LinkEvent) UnmarshalBinary(data []byte) (int, error) { 372 return UnmarshalBinary(data, &e.SyscallEvent, &e.Source, &e.Target) 373 } 374 375 // UnmarshalBinary unmarshalls a binary representation of itself 376 func (e *MkdirEvent) UnmarshalBinary(data []byte) (int, error) { 377 n, err := UnmarshalBinary(data, &e.SyscallEvent, &e.File) 378 if err != nil { 379 return n, err 380 } 381 382 data = data[n:] 383 if len(data) < 4 { 384 return n, ErrNotEnoughData 385 } 386 387 e.Mode = binary.NativeEndian.Uint32(data[0:4]) 388 return n + 4, nil 389 } 390 391 // UnmarshalBinary unmarshalls a binary representation of itself 392 func (m *Mount) UnmarshalBinary(data []byte) (int, error) { 393 if len(data) < 56 { 394 return 0, ErrNotEnoughData 395 } 396 397 n, err := m.RootPathKey.UnmarshalBinary(data) 398 if err != nil { 399 return 0, err 400 } 401 data = data[n:] 402 403 n, err = m.ParentPathKey.UnmarshalBinary(data) 404 if err != nil { 405 return 0, err 406 } 407 data = data[n:] 408 409 m.Device = binary.NativeEndian.Uint32(data[0:4]) 410 m.BindSrcMountID = binary.NativeEndian.Uint32(data[4:8]) 411 m.FSType, err = UnmarshalString(data[8:], 16) 412 if err != nil { 413 return 0, err 414 } 415 416 m.MountID = m.RootPathKey.MountID 417 418 return 56, nil 419 } 420 421 // UnmarshalBinary unmarshalls a binary representation of itself 422 func (e *MountEvent) UnmarshalBinary(data []byte) (int, error) { 423 return UnmarshalBinary(data, &e.SyscallEvent, &e.Mount) 424 } 425 426 // UnmarshalBinary unmarshalls a binary representation of itself 427 func (e *UnshareMountNSEvent) UnmarshalBinary(data []byte) (int, error) { 428 return e.Mount.UnmarshalBinary(data) 429 } 430 431 // UnmarshalBinary unmarshalls a binary representation of itself 432 func (e *ChdirEvent) UnmarshalBinary(data []byte) (int, error) { 433 return UnmarshalBinary(data, &e.SyscallEvent, &e.File) 434 } 435 436 // UnmarshalBinary unmarshalls a binary representation of itself 437 func (e *OpenEvent) UnmarshalBinary(data []byte) (int, error) { 438 n, err := UnmarshalBinary(data, &e.SyscallEvent, &e.File) 439 if err != nil { 440 return n, err 441 } 442 443 data = data[n:] 444 if len(data) < 8 { 445 return n, ErrNotEnoughData 446 } 447 448 e.Flags = binary.NativeEndian.Uint32(data[0:4]) 449 e.Mode = binary.NativeEndian.Uint32(data[4:8]) 450 return n + 8, nil 451 } 452 453 // UnmarshalBinary unmarshalls a binary representation of itself 454 func (s *SpanContext) UnmarshalBinary(data []byte) (int, error) { 455 if len(data) < 16 { 456 return 0, ErrNotEnoughData 457 } 458 459 s.SpanID = binary.NativeEndian.Uint64(data[0:8]) 460 s.TraceID = binary.NativeEndian.Uint64(data[8:16]) 461 462 return 16, nil 463 } 464 465 // UnmarshalBinary unmarshalls a binary representation of itself 466 func (e *SELinuxEvent) UnmarshalBinary(data []byte) (int, error) { 467 n, err := UnmarshalBinary(data, &e.File) 468 if err != nil { 469 return n, err 470 } 471 472 data = data[n:] 473 if len(data) < 8 { 474 return n, ErrNotEnoughData 475 } 476 477 e.EventKind = SELinuxEventKind(binary.NativeEndian.Uint32(data[0:4])) 478 479 switch e.EventKind { 480 case SELinuxBoolChangeEventKind: 481 boolValue := binary.NativeEndian.Uint32(data[4:8]) 482 if boolValue == ^uint32(0) { 483 e.BoolChangeValue = "error" 484 } else if boolValue > 0 { 485 e.BoolChangeValue = "on" 486 } else { 487 e.BoolChangeValue = "off" 488 } 489 case SELinuxBoolCommitEventKind: 490 boolValue := binary.NativeEndian.Uint32(data[4:8]) 491 e.BoolCommitValue = boolValue != 0 492 case SELinuxStatusChangeEventKind: 493 disableValue := binary.NativeEndian.Uint16(data[4:6]) != 0 494 enforceValue := binary.NativeEndian.Uint16(data[6:8]) != 0 495 if disableValue { 496 e.EnforceStatus = "disabled" 497 } else if enforceValue { 498 e.EnforceStatus = "enforcing" 499 } else { 500 e.EnforceStatus = "permissive" 501 } 502 } 503 504 return n + 8, nil 505 } 506 507 // UnmarshalBinary unmarshalls a binary representation of itself, process_context_t kernel side 508 func (p *PIDContext) UnmarshalBinary(data []byte) (int, error) { 509 if len(data) < 24 { 510 return 0, ErrNotEnoughData 511 } 512 513 p.Pid = binary.NativeEndian.Uint32(data[0:4]) 514 p.Tid = binary.NativeEndian.Uint32(data[4:8]) 515 p.NetNS = binary.NativeEndian.Uint32(data[8:12]) 516 p.IsKworker = binary.NativeEndian.Uint32(data[12:16]) > 0 517 p.ExecInode = binary.NativeEndian.Uint64(data[16:24]) 518 519 return 24, nil 520 } 521 522 // UnmarshalBinary unmarshalls a binary representation of itself 523 func (e *RenameEvent) UnmarshalBinary(data []byte) (int, error) { 524 return UnmarshalBinary(data, &e.SyscallEvent, &e.Old, &e.New) 525 } 526 527 // UnmarshalBinary unmarshalls a binary representation of itself 528 func (e *RmdirEvent) UnmarshalBinary(data []byte) (int, error) { 529 return UnmarshalBinary(data, &e.SyscallEvent, &e.File) 530 } 531 532 // UnmarshalBinary unmarshalls a binary representation of itself 533 func (e *SetXAttrEvent) UnmarshalBinary(data []byte) (int, error) { 534 n, err := UnmarshalBinary(data, &e.SyscallEvent, &e.File) 535 if err != nil { 536 return n, err 537 } 538 539 data = data[n:] 540 if len(data) < 200 { 541 return n, ErrNotEnoughData 542 } 543 SliceToArray(data[0:200], e.NameRaw[:]) 544 545 return n + 200, nil 546 } 547 548 // UnmarshalBinary unmarshalls a binary representation of itself 549 func (e *SyscallEvent) UnmarshalBinary(data []byte) (int, error) { 550 if len(data) < 8 { 551 return 0, ErrNotEnoughData 552 } 553 e.Retval = int64(binary.NativeEndian.Uint64(data[0:8])) 554 return 8, nil 555 } 556 557 // UnmarshalBinary unmarshalls a binary representation of itself 558 func (e *UmountEvent) UnmarshalBinary(data []byte) (int, error) { 559 n, err := UnmarshalBinary(data, &e.SyscallEvent) 560 if err != nil { 561 return n, err 562 } 563 564 data = data[n:] 565 if len(data) < 4 { 566 return 0, ErrNotEnoughData 567 } 568 569 e.MountID = binary.NativeEndian.Uint32(data[0:4]) 570 571 return 8, nil 572 } 573 574 // UnmarshalBinary unmarshalls a binary representation of itself 575 func (e *UnlinkEvent) UnmarshalBinary(data []byte) (int, error) { 576 n, err := UnmarshalBinary(data, &e.SyscallEvent, &e.File) 577 if err != nil { 578 return n, err 579 } 580 581 data = data[n:] 582 if len(data) < 8 { 583 return 0, ErrNotEnoughData 584 } 585 586 e.Flags = binary.NativeEndian.Uint32(data[0:4]) 587 // padding 588 589 return n + 8, nil 590 } 591 592 // UnmarshalBinary unmarshalls a binary representation of itself 593 func (e *UtimesEvent) UnmarshalBinary(data []byte) (int, error) { 594 n, err := UnmarshalBinary(data, &e.SyscallEvent, &e.File) 595 if err != nil { 596 return n, err 597 } 598 599 data = data[n:] 600 if len(data) < 32 { 601 return 0, ErrNotEnoughData 602 } 603 604 timeSec := binary.NativeEndian.Uint64(data[0:8]) 605 timeNsec := binary.NativeEndian.Uint64(data[8:16]) 606 e.Atime = time.Unix(int64(timeSec), int64(timeNsec)) 607 608 timeSec = binary.NativeEndian.Uint64(data[16:24]) 609 timeNsec = binary.NativeEndian.Uint64(data[24:32]) 610 e.Mtime = time.Unix(int64(timeSec), int64(timeNsec)) 611 612 return n + 32, nil 613 } 614 615 // UnmarshalBinary calls a series of BinaryUnmarshaler 616 func UnmarshalBinary(data []byte, binaryUnmarshalers ...BinaryUnmarshaler) (int, error) { 617 read := 0 618 for _, marshaler := range binaryUnmarshalers { 619 n, err := marshaler.UnmarshalBinary(data[read:]) 620 read += n 621 if err != nil { 622 return read, err 623 } 624 } 625 return read, nil 626 } 627 628 // UnmarshalBinary unmarshalls a binary representation of itself 629 func (e *MountReleasedEvent) UnmarshalBinary(data []byte) (int, error) { 630 if len(data) < 4 { 631 return 0, ErrNotEnoughData 632 } 633 634 e.MountID = binary.NativeEndian.Uint32(data[0:4]) 635 636 return 8, nil 637 } 638 639 // UnmarshalBinary unmarshalls a binary representation of itself 640 func (e *BPFEvent) UnmarshalBinary(data []byte) (int, error) { 641 read, err := UnmarshalBinary(data, &e.SyscallEvent) 642 if err != nil { 643 return 0, err 644 } 645 cursor := read 646 647 read, err = e.Map.UnmarshalBinary(data[cursor:]) 648 if err != nil { 649 return 0, err 650 } 651 cursor += read 652 read, err = e.Program.UnmarshalBinary(data[cursor:]) 653 if err != nil { 654 return 0, err 655 } 656 cursor += read 657 if len(data) < cursor+4 { 658 return 0, ErrNotEnoughData 659 } 660 e.Cmd = binary.NativeEndian.Uint32(data[cursor : cursor+4]) 661 return cursor + 4, nil 662 } 663 664 // UnmarshalBinary unmarshalls a binary representation of itself 665 func (m *BPFMap) UnmarshalBinary(data []byte) (int, error) { 666 if len(data) < 24 { 667 return 0, ErrNotEnoughData 668 } 669 m.ID = binary.NativeEndian.Uint32(data[0:4]) 670 m.Type = binary.NativeEndian.Uint32(data[4:8]) 671 672 var err error 673 m.Name, err = UnmarshalString(data[8:24], 16) 674 if err != nil { 675 return 0, err 676 } 677 return 24, nil 678 } 679 680 // UnmarshalBinary unmarshalls a binary representation of itself 681 func (p *BPFProgram) UnmarshalBinary(data []byte) (int, error) { 682 if len(data) < 64 { 683 return 0, ErrNotEnoughData 684 } 685 p.ID = binary.NativeEndian.Uint32(data[0:4]) 686 p.Type = binary.NativeEndian.Uint32(data[4:8]) 687 p.AttachType = binary.NativeEndian.Uint32(data[8:12]) 688 // padding 689 helpers := []uint64{0, 0, 0} 690 helpers[0] = binary.NativeEndian.Uint64(data[16:24]) 691 helpers[1] = binary.NativeEndian.Uint64(data[24:32]) 692 helpers[2] = binary.NativeEndian.Uint64(data[32:40]) 693 p.Helpers = parseHelpers(helpers) 694 695 var err error 696 p.Name, err = UnmarshalString(data[40:56], 16) 697 if err != nil { 698 return 0, err 699 } 700 p.Tag = parseSHA1Tag(data[56:64]) 701 return 64, nil 702 } 703 704 // parseSHA1Tag parses the short sha1 digest from the kernel event 705 func parseSHA1Tag(data []byte) string { 706 if len(data) != 8 { 707 return "" 708 } 709 710 var builder strings.Builder 711 builder.Grow(16) 712 713 for _, b := range data { 714 if _, err := fmt.Fprintf(&builder, "%02x", b); err != nil { 715 // should really never happen when writing to a string.Builder 716 return "" 717 } 718 } 719 return builder.String() 720 } 721 722 func parseHelpers(helpers []uint64) []uint32 { 723 if len(helpers) < 3 { 724 return nil 725 } 726 727 var popcnt int 728 for _, h := range helpers { 729 popcnt += bits.OnesCount64(h) 730 } 731 rep := make([]uint32, 0, popcnt) 732 733 for i := 0; i < 192; i++ { 734 add := false 735 if i < 64 { 736 if helpers[0]&(1<<i) == (1 << i) { 737 add = true 738 } 739 } else if i < 128 { 740 if helpers[1]&(1<<(i-64)) == (1 << (i - 64)) { 741 add = true 742 } 743 } else if i < 192 { 744 if helpers[2]&(1<<(i-128)) == (1 << (i - 128)) { 745 add = true 746 } 747 } 748 749 if add { 750 rep = append(rep, uint32(i)) 751 } 752 } 753 return rep 754 } 755 756 // UnmarshalBinary unmarshalls a binary representation of itself 757 func (e *PTraceEvent) UnmarshalBinary(data []byte) (int, error) { 758 read, err := UnmarshalBinary(data, &e.SyscallEvent) 759 if err != nil { 760 return 0, err 761 } 762 763 if len(data)-read < 16 { 764 return 0, ErrNotEnoughData 765 } 766 767 e.Request = binary.NativeEndian.Uint32(data[read : read+4]) 768 e.PID = binary.NativeEndian.Uint32(data[read+4 : read+8]) 769 e.Address = binary.NativeEndian.Uint64(data[read+8 : read+16]) 770 return read + 16, nil 771 } 772 773 // UnmarshalBinary unmarshals a binary representation of itself 774 func (e *MMapEvent) UnmarshalBinary(data []byte) (int, error) { 775 read, err := UnmarshalBinary(data, &e.SyscallEvent, &e.File) 776 if err != nil { 777 return 0, err 778 } 779 780 if len(data)-read < 40 { 781 return 0, ErrNotEnoughData 782 } 783 784 e.Addr = binary.NativeEndian.Uint64(data[read : read+8]) 785 e.Offset = binary.NativeEndian.Uint64(data[read+8 : read+16]) 786 e.Len = binary.NativeEndian.Uint64(data[read+16 : read+24]) 787 e.Protection = binary.NativeEndian.Uint64(data[read+24 : read+32]) 788 e.Flags = binary.NativeEndian.Uint64(data[read+32 : read+40]) 789 return read + 40, nil 790 } 791 792 // UnmarshalBinary unmarshals a binary representation of itself 793 func (e *MProtectEvent) UnmarshalBinary(data []byte) (int, error) { 794 read, err := UnmarshalBinary(data, &e.SyscallEvent) 795 if err != nil { 796 return 0, err 797 } 798 799 if len(data)-read < 32 { 800 return 0, ErrNotEnoughData 801 } 802 803 e.VMStart = binary.NativeEndian.Uint64(data[read : read+8]) 804 e.VMEnd = binary.NativeEndian.Uint64(data[read+8 : read+16]) 805 e.VMProtection = int(binary.NativeEndian.Uint32(data[read+16 : read+24])) 806 e.ReqProtection = int(binary.NativeEndian.Uint32(data[read+24 : read+32])) 807 return read + 32, nil 808 } 809 810 // UnmarshalBinary unmarshals a binary representation of itself 811 func (e *LoadModuleEvent) UnmarshalBinary(data []byte) (int, error) { 812 read, err := UnmarshalBinary(data, &e.SyscallEvent, &e.File) 813 if err != nil { 814 return 0, err 815 } 816 817 if len(data)-read < 188 { 818 return 0, ErrNotEnoughData 819 } 820 821 e.Name, err = UnmarshalString(data[read:read+56], 56) 822 read += 56 823 824 if err != nil { 825 return 0, err 826 } 827 828 e.Args, err = UnmarshalString(data[read:read+128], 128) 829 read += 128 830 831 e.ArgsTruncated = binary.NativeEndian.Uint32(data[read:read+4]) == uint32(1) 832 read += 4 833 834 if err != nil { 835 return 0, err 836 } 837 e.LoadedFromMemory = binary.NativeEndian.Uint32(data[read:read+4]) == uint32(1) 838 read += 4 839 840 return read, nil 841 } 842 843 // UnmarshalBinary unmarshals a binary representation of itself 844 func (e *UnloadModuleEvent) UnmarshalBinary(data []byte) (int, error) { 845 read, err := UnmarshalBinary(data, &e.SyscallEvent) 846 if err != nil { 847 return 0, err 848 } 849 850 if len(data)-read < 56 { 851 return 0, ErrNotEnoughData 852 } 853 854 e.Name, err = UnmarshalString(data[read:read+56], 56) 855 if err != nil { 856 return 0, err 857 } 858 return read + 56, nil 859 } 860 861 // UnmarshalBinary unmarshals a binary representation of itself 862 func (e *SignalEvent) UnmarshalBinary(data []byte) (int, error) { 863 read, err := UnmarshalBinary(data, &e.SyscallEvent) 864 if err != nil { 865 return 0, err 866 } 867 868 if len(data)-read < 8 { 869 return 0, ErrNotEnoughData 870 } 871 872 e.PID = binary.NativeEndian.Uint32(data[read : read+4]) 873 e.Type = binary.NativeEndian.Uint32(data[read+4 : read+8]) 874 return read + 8, nil 875 } 876 877 // UnmarshalBinary unmarshals a binary representation of itself 878 func (e *SpliceEvent) UnmarshalBinary(data []byte) (int, error) { 879 read, err := UnmarshalBinary(data, &e.SyscallEvent, &e.File) 880 if err != nil { 881 return 0, err 882 } 883 884 if len(data)-read < 8 { 885 return 0, ErrNotEnoughData 886 } 887 888 e.PipeEntryFlag = binary.NativeEndian.Uint32(data[read : read+4]) 889 e.PipeExitFlag = binary.NativeEndian.Uint32(data[read+4 : read+8]) 890 return read + 4, nil 891 } 892 893 // UnmarshalBinary unmarshals a binary representation of itself 894 func (e *CgroupTracingEvent) UnmarshalBinary(data []byte) (int, error) { 895 read, err := UnmarshalBinary(data, &e.ContainerContext) 896 if err != nil { 897 return 0, err 898 } 899 cursor := read 900 901 read, err = e.Config.EventUnmarshalBinary(data[cursor:]) 902 if err != nil { 903 return 0, err 904 } 905 cursor += read 906 907 if len(data)-cursor < 4 { 908 return 0, ErrNotEnoughData 909 } 910 911 e.ConfigCookie = binary.NativeEndian.Uint64(data[cursor : cursor+8]) 912 return cursor + 8, nil 913 } 914 915 // EventUnmarshalBinary unmarshals a binary representation of itself 916 func (adlc *ActivityDumpLoadConfig) EventUnmarshalBinary(data []byte) (int, error) { 917 if len(data) < 48 { 918 return 0, ErrNotEnoughData 919 } 920 921 eventMask := binary.NativeEndian.Uint64(data[0:8]) 922 for i := uint64(0); i < 64; i++ { 923 if eventMask&(1<<i) == (1 << i) { 924 adlc.TracedEventTypes = append(adlc.TracedEventTypes, EventType(i)+FirstDiscarderEventType) 925 } 926 } 927 adlc.Timeout = time.Duration(binary.NativeEndian.Uint64(data[8:16])) 928 adlc.WaitListTimestampRaw = binary.NativeEndian.Uint64(data[16:24]) 929 adlc.StartTimestampRaw = binary.NativeEndian.Uint64(data[24:32]) 930 adlc.EndTimestampRaw = binary.NativeEndian.Uint64(data[32:40]) 931 adlc.Rate = binary.NativeEndian.Uint32(data[40:44]) 932 adlc.Paused = binary.NativeEndian.Uint32(data[44:48]) 933 return 48, nil 934 } 935 936 // UnmarshalBinary unmarshals a binary representation of itself 937 func (adlc *ActivityDumpLoadConfig) UnmarshalBinary(data []byte) error { 938 _, err := adlc.EventUnmarshalBinary(data) 939 return err 940 } 941 942 // UnmarshalBinary unmarshalls a binary representation of itself 943 func (e *NetworkDeviceContext) UnmarshalBinary(data []byte) (int, error) { 944 if len(data) < 8 { 945 return 0, ErrNotEnoughData 946 } 947 e.NetNS = binary.NativeEndian.Uint32(data[0:4]) 948 e.IfIndex = binary.NativeEndian.Uint32(data[4:8]) 949 return 8, nil 950 } 951 952 // UnmarshalBinary unmarshalls a binary representation of itself 953 func (e *NetworkContext) UnmarshalBinary(data []byte) (int, error) { 954 read, err := UnmarshalBinary(data, &e.Device) 955 if err != nil { 956 return 0, err 957 } 958 959 if len(data)-read < 44 { 960 return 0, ErrNotEnoughData 961 } 962 963 var srcIP, dstIP [16]byte 964 SliceToArray(data[read:read+16], srcIP[:]) 965 SliceToArray(data[read+16:read+32], dstIP[:]) 966 e.Source.Port = binary.BigEndian.Uint16(data[read+32 : read+34]) 967 e.Destination.Port = binary.BigEndian.Uint16(data[read+34 : read+36]) 968 // padding 4 bytes 969 970 e.Size = binary.NativeEndian.Uint32(data[read+40 : read+44]) 971 e.L3Protocol = binary.NativeEndian.Uint16(data[read+44 : read+46]) 972 e.L4Protocol = binary.NativeEndian.Uint16(data[read+46 : read+48]) 973 974 // readjust IP sizes depending on the protocol 975 switch e.L3Protocol { 976 case 0x800: // unix.ETH_P_IP 977 e.Source.IPNet = *eval.IPNetFromIP(srcIP[0:4]) 978 e.Destination.IPNet = *eval.IPNetFromIP(dstIP[0:4]) 979 default: 980 e.Source.IPNet = *eval.IPNetFromIP(srcIP[:]) 981 e.Destination.IPNet = *eval.IPNetFromIP(dstIP[:]) 982 } 983 return read + 48, nil 984 } 985 986 // UnmarshalBinary unmarshalls a binary representation of itself 987 func (e *DNSEvent) UnmarshalBinary(data []byte) (int, error) { 988 if len(data) < 10 { 989 return 0, ErrNotEnoughData 990 } 991 992 e.ID = binary.NativeEndian.Uint16(data[0:2]) 993 e.Count = binary.NativeEndian.Uint16(data[2:4]) 994 e.Type = binary.NativeEndian.Uint16(data[4:6]) 995 e.Class = binary.NativeEndian.Uint16(data[6:8]) 996 e.Size = binary.NativeEndian.Uint16(data[8:10]) 997 var err error 998 e.Name, err = decodeDNSName(data[10:]) 999 if err != nil { 1000 return 0, err 1001 } 1002 if err = validateDNSName(e.Name); err != nil { 1003 return 0, err 1004 } 1005 return len(data), nil 1006 } 1007 1008 // UnmarshalBinary unmarshalls a binary representation of itself 1009 func (d *NetDevice) UnmarshalBinary(data []byte) (int, error) { 1010 if len(data[:]) < 32 { 1011 return 0, ErrNotEnoughData 1012 } 1013 1014 var err error 1015 d.Name, err = UnmarshalString(data[0:16], 16) 1016 if err != nil { 1017 return 0, err 1018 } 1019 d.NetNS = binary.NativeEndian.Uint32(data[16:20]) 1020 d.IfIndex = binary.NativeEndian.Uint32(data[20:24]) 1021 d.PeerNetNS = binary.NativeEndian.Uint32(data[24:28]) 1022 d.PeerIfIndex = binary.NativeEndian.Uint32(data[28:32]) 1023 return 32, nil 1024 } 1025 1026 // UnmarshalBinary unmarshalls a binary representation of itself 1027 func (e *NetDeviceEvent) UnmarshalBinary(data []byte) (int, error) { 1028 read, err := UnmarshalBinary(data, &e.SyscallEvent) 1029 if err != nil { 1030 return 0, err 1031 } 1032 cursor := read 1033 1034 read, err = e.Device.UnmarshalBinary(data[cursor:]) 1035 if err != nil { 1036 return 0, err 1037 } 1038 cursor += read 1039 return cursor, nil 1040 } 1041 1042 // UnmarshalBinary unmarshalls a binary representation of itself 1043 func (e *VethPairEvent) UnmarshalBinary(data []byte) (int, error) { 1044 read, err := UnmarshalBinary(data, &e.SyscallEvent) 1045 if err != nil { 1046 return 0, err 1047 } 1048 cursor := read 1049 1050 read, err = e.HostDevice.UnmarshalBinary(data[cursor:]) 1051 if err != nil { 1052 return 0, err 1053 } 1054 cursor += read 1055 1056 read, err = e.PeerDevice.UnmarshalBinary(data[cursor:]) 1057 if err != nil { 1058 return 0, err 1059 } 1060 cursor += read 1061 1062 return cursor, nil 1063 } 1064 1065 // UnmarshalBinary unmarshalls a binary representation of itself 1066 func (e *BindEvent) UnmarshalBinary(data []byte) (int, error) { 1067 read, err := UnmarshalBinary(data, &e.SyscallEvent) 1068 if err != nil { 1069 return 0, err 1070 } 1071 1072 if len(data)-read < 20 { 1073 return 0, ErrNotEnoughData 1074 } 1075 1076 var ipRaw [16]byte 1077 SliceToArray(data[read:read+16], ipRaw[:]) 1078 e.AddrFamily = binary.NativeEndian.Uint16(data[read+16 : read+18]) 1079 e.Addr.Port = binary.BigEndian.Uint16(data[read+18 : read+20]) 1080 1081 // readjust IP size depending on the protocol 1082 switch e.AddrFamily { 1083 case 0x2: // unix.AF_INET 1084 e.Addr.IPNet = *eval.IPNetFromIP(ipRaw[0:4]) 1085 case 0xa: // unix.AF_INET6 1086 e.Addr.IPNet = *eval.IPNetFromIP(ipRaw[:]) 1087 } 1088 1089 return read + 20, nil 1090 } 1091 1092 // UnmarshalBinary unmarshalls a binary representation of itself 1093 func (e *SyscallsEvent) UnmarshalBinary(data []byte) (int, error) { 1094 if len(data) < 64 { 1095 return 0, ErrNotEnoughData 1096 } 1097 1098 for i, b := range data[:64] { 1099 // compute the ID of the syscall 1100 for j := 0; j < 8; j++ { 1101 if b&(1<<j) > 0 { 1102 e.Syscalls = append(e.Syscalls, Syscall(i*8+j)) 1103 } 1104 } 1105 } 1106 return 64, nil 1107 } 1108 1109 // UnmarshalBinary unmarshalls a binary representation of itself 1110 func (e *AnomalyDetectionSyscallEvent) UnmarshalBinary(data []byte) (int, error) { 1111 if len(data) < 8 { 1112 return 0, ErrNotEnoughData 1113 } 1114 1115 e.SyscallID = Syscall(binary.NativeEndian.Uint64(data[0:8])) 1116 return 8, nil 1117 }