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  }