From 04dfd82fd8820d6b3365659bab149eb97a7935b1 Mon Sep 17 00:00:00 2001 From: Sylvain Afchain Date: Wed, 18 Dec 2024 22:28:06 +0100 Subject: [PATCH] [CWS] fix inode on aws kernel >= 6.8 --- .../ebpf/c/include/constants/offsets/filesystem.h | 8 +++++++- pkg/security/probe/constantfetch/constant_names.go | 3 +++ pkg/security/probe/constantfetch/fallback.go | 6 ++++++ pkg/security/probe/probe_ebpf.go | 3 +++ pkg/security/resolvers/process/resolver_ebpf.go | 11 +++++++---- 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/pkg/security/ebpf/c/include/constants/offsets/filesystem.h b/pkg/security/ebpf/c/include/constants/offsets/filesystem.h index 24b2d5f769af16..6df2fcb3c0790f 100644 --- a/pkg/security/ebpf/c/include/constants/offsets/filesystem.h +++ b/pkg/security/ebpf/c/include/constants/offsets/filesystem.h @@ -8,9 +8,15 @@ struct mount; +int __attribute__((always_inline)) get_ino_offset() { + u64 ino_offset; + LOAD_CONSTANT("inode_ino_offset", ino_offset); + return ino_offset; +} + unsigned long __attribute__((always_inline)) get_inode_ino(struct inode *inode) { unsigned long ino; - bpf_probe_read(&ino, sizeof(inode), &inode->i_ino); + bpf_probe_read(&ino, sizeof(inode), (void *)inode + get_ino_offset()); return ino; } diff --git a/pkg/security/probe/constantfetch/constant_names.go b/pkg/security/probe/constantfetch/constant_names.go index 2feab9c5e0402c..ccc740712e91f7 100644 --- a/pkg/security/probe/constantfetch/constant_names.go +++ b/pkg/security/probe/constantfetch/constant_names.go @@ -31,6 +31,9 @@ const ( OffsetNameDentryDSb = "dentry_d_sb_offset" OffsetNameMountMntID = "mount_id_offset" + // ino + OffsetInodeIno = "inode_ino_offset" + // inode times OffsetNameInodeCtimeSec = "inode_ctime_sec_offset" OffsetNameInodeCtimeNsec = "inode_ctime_nsec_offset" diff --git a/pkg/security/probe/constantfetch/fallback.go b/pkg/security/probe/constantfetch/fallback.go index 531edb59c29d34..8cee35118d0b7d 100644 --- a/pkg/security/probe/constantfetch/fallback.go +++ b/pkg/security/probe/constantfetch/fallback.go @@ -147,6 +147,8 @@ func (f *FallbackConstantFetcher) appendRequest(id string) { value = getRenameStructOldDentryOffset(f.kernelVersion) case OffsetNameRenameStructNewDentry: value = getRenameStructNewDentryOffset(f.kernelVersion) + case OffsetInodeIno: + value = getInodeInoOffset(f.kernelVersion) } f.res[id] = value } @@ -236,6 +238,10 @@ func getSizeOfStructInode(kv *kernel.Version) uint64 { return sizeOf } +func getInodeInoOffset(_ *kernel.Version) uint64 { + return uint64(64) +} + func getSuperBlockFlagsOffset(_ *kernel.Version) uint64 { return uint64(80) } diff --git a/pkg/security/probe/probe_ebpf.go b/pkg/security/probe/probe_ebpf.go index f06cbe8fa45aea..5586ad0ae77925 100644 --- a/pkg/security/probe/probe_ebpf.go +++ b/pkg/security/probe/probe_ebpf.go @@ -2525,6 +2525,9 @@ func AppendProbeRequestsToFetcher(constantFetcher constantfetch.ConstantFetcher, if kv.Code != 0 && (kv.Code >= kernel.Kernel5_1) { constantFetcher.AppendOffsetofRequest(constantfetch.OffsetNameIoKiocbStructCtx, "struct io_kiocb", "ctx", "") } + + // inode + constantFetcher.AppendOffsetofRequest(constantfetch.OffsetInodeIno, "struct inode", "i_ino", "linux/fs.h") } // HandleActions handles the rule actions diff --git a/pkg/security/resolvers/process/resolver_ebpf.go b/pkg/security/resolvers/process/resolver_ebpf.go index 5bcccdb52c540c..cf614f2ad9a343 100644 --- a/pkg/security/resolvers/process/resolver_ebpf.go +++ b/pkg/security/resolvers/process/resolver_ebpf.go @@ -334,6 +334,9 @@ func (p *EBPFResolver) enrichEventFromProc(entry *model.ProcessCacheEntry, proc // Get the file fields of the process binary info, err := p.retrieveExecFileFields(procExecPath) if err != nil { + if !os.IsNotExist(err) { + seclog.Errorf("snapshot failed for %d: couldn't retrieve inode info: %s", proc.Pid, err) + } return fmt.Errorf("snapshot failed for %d: couldn't retrieve inode info: %w", proc.Pid, err) } @@ -465,11 +468,11 @@ func (p *EBPFResolver) enrichEventFromProc(entry *model.ProcessCacheEntry, proc func (p *EBPFResolver) retrieveExecFileFields(procExecPath string) (*model.FileFields, error) { fi, err := os.Stat(procExecPath) if err != nil { - return nil, fmt.Errorf("snapshot failed for `%s`: couldn't stat binary: %w", procExecPath, err) + return nil, err } stat, ok := fi.Sys().(*syscall.Stat_t) if !ok { - return nil, fmt.Errorf("snapshot failed for `%s`: couldn't stat binary", procExecPath) + return nil, errors.New("wrong type") } inode := stat.Ino @@ -483,11 +486,11 @@ func (p *EBPFResolver) retrieveExecFileFields(procExecPath string) (*model.FileF var fileFields model.FileFields if _, err := fileFields.UnmarshalBinary(data); err != nil { - return nil, fmt.Errorf("unable to unmarshal entry for inode `%d`", inode) + return nil, fmt.Errorf("unable to unmarshal entry for inode `%d`: %v", inode, err) } if fileFields.Inode == 0 { - return nil, errors.New("not found") + return nil, fmt.Errorf("inode `%d` not found: %v", inode, err) } return &fileFields, nil