Skip to content

Commit

Permalink
[CWS] fix inode i_ino offset on aws kernel >= 6.8 (#32370)
Browse files Browse the repository at this point in the history
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
(cherry picked from commit baa23e0)
  • Loading branch information
safchain authored and YoannGh committed Dec 19, 2024
1 parent 0e4eb16 commit 3e130e9
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 9 deletions.
5 changes: 4 additions & 1 deletion pkg/security/ebpf/c/include/constants/offsets/filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
struct mount;

unsigned long __attribute__((always_inline)) get_inode_ino(struct inode *inode) {
u64 inode_ino_offset;
LOAD_CONSTANT("inode_ino_offset", inode_ino_offset);

unsigned long ino;
bpf_probe_read(&ino, sizeof(inode), &inode->i_ino);
bpf_probe_read(&ino, sizeof(inode), (void *)inode + inode_ino_offset);
return ino;
}

Expand Down
19 changes: 15 additions & 4 deletions pkg/security/ebpf/c/include/helpers/filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,15 @@ void __attribute__((always_inline)) fill_file(struct dentry *dentry, struct file

file->dev = get_dentry_dev(dentry);

bpf_probe_read(&file->metadata.nlink, sizeof(file->metadata.nlink), (void *)&d_inode->i_nlink);
u64 inode_nlink_offset;
LOAD_CONSTANT("inode_nlink_offset", inode_nlink_offset);
u64 inode_gid_offset;
LOAD_CONSTANT("inode_gid_offset", inode_gid_offset);

bpf_probe_read(&file->metadata.nlink, sizeof(file->metadata.nlink), (void *)d_inode + inode_nlink_offset);
bpf_probe_read(&file->metadata.mode, sizeof(file->metadata.mode), &d_inode->i_mode);
bpf_probe_read(&file->metadata.uid, sizeof(file->metadata.uid), &d_inode->i_uid);
bpf_probe_read(&file->metadata.gid, sizeof(file->metadata.gid), &d_inode->i_gid);
bpf_probe_read(&file->metadata.gid, sizeof(file->metadata.gid), (void *)d_inode + inode_gid_offset);

u64 inode_ctime_sec_offset;
LOAD_CONSTANT("inode_ctime_sec_offset", inode_ctime_sec_offset);
Expand All @@ -121,7 +126,10 @@ void __attribute__((always_inline)) fill_file(struct dentry *dentry, struct file
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
bpf_probe_read(&file->metadata.ctime, sizeof(file->metadata.ctime), &d_inode->i_ctime);
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 11, 0)
bpf_probe_read(&file->metadata.ctime, sizeof(file->metadata.ctime), &d_inode->__i_ctime);
u64 inode_ctime_offset;
LOAD_CONSTANT("inode_ctime_offset", inode_ctime_offset);

bpf_probe_read(&file->metadata.ctime, sizeof(file->metadata.ctime), (void *)d_inode + inode_ctime_offset);
#else
bpf_probe_read(&file->metadata.ctime.tv_sec, sizeof(file->metadata.ctime.tv_sec), &d_inode->i_ctime_sec);
bpf_probe_read(&file->metadata.ctime.tv_nsec, sizeof(file->metadata.ctime.tv_nsec), &d_inode->i_ctime_nsec);
Expand All @@ -142,7 +150,10 @@ void __attribute__((always_inline)) fill_file(struct dentry *dentry, struct file
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 7, 0)
bpf_probe_read(&file->metadata.mtime, sizeof(file->metadata.mtime), &d_inode->i_mtime);
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 11, 0)
bpf_probe_read(&file->metadata.mtime, sizeof(file->metadata.mtime), &d_inode->__i_mtime);
u64 inode_mtime_offset;
LOAD_CONSTANT("inode_mtime_offset", inode_mtime_offset);

bpf_probe_read(&file->metadata.mtime, sizeof(file->metadata.mtime), (void *)d_inode + inode_mtime_offset);
#else
bpf_probe_read(&file->metadata.mtime.tv_sec, sizeof(file->metadata.mtime.tv_sec), &d_inode->i_mtime_sec);
bpf_probe_read(&file->metadata.mtime.tv_nsec, sizeof(file->metadata.mtime.tv_nsec), &d_inode->i_mtime_nsec);
Expand Down
7 changes: 7 additions & 0 deletions pkg/security/probe/constantfetch/constant_names.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ const (
OffsetNameFileFpath = "file_f_path_offset"
OffsetNameMountMntID = "mount_id_offset"

// inode
OffsetInodeIno = "inode_ino_offset"
OffsetInodeNlink = "inode_nlink_offset"
OffsetInodeGid = "inode_gid_offset"
OffsetInodeMtime = "inode_mtime_offset"
OffsetInodeCtime = "inode_ctime_offset"

// inode times
OffsetNameInodeCtimeSec = "inode_ctime_sec_offset"
OffsetNameInodeCtimeNsec = "inode_ctime_nsec_offset"
Expand Down
30 changes: 30 additions & 0 deletions pkg/security/probe/constantfetch/fallback.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,16 @@ func (f *FallbackConstantFetcher) appendRequest(id string) {
value = getRenameStructOldDentryOffset(f.kernelVersion)
case OffsetNameRenameStructNewDentry:
value = getRenameStructNewDentryOffset(f.kernelVersion)
case OffsetInodeIno:
value = getInodeInoOffset(f.kernelVersion)
case OffsetInodeGid:
value = getInodeGIDOffset(f.kernelVersion)
case OffsetInodeNlink:
value = getInodeNlinkOffset(f.kernelVersion)
case OffsetInodeMtime:
value = getInodeMtimeOffset(f.kernelVersion)
case OffsetInodeCtime:
value = getInodeCtimeOffset(f.kernelVersion)
}
f.res[id] = value
}
Expand Down Expand Up @@ -234,6 +244,26 @@ func getSizeOfStructInode(kv *kernel.Version) uint64 {
return sizeOf
}

func getInodeInoOffset(_ *kernel.Version) uint64 {
return uint64(64)
}

func getInodeGIDOffset(_ *kernel.Version) uint64 {
return uint64(8)
}

func getInodeNlinkOffset(_ *kernel.Version) uint64 {
return uint64(72)
}

func getInodeMtimeOffset(_ *kernel.Version) uint64 {
return uint64(104)
}

func getInodeCtimeOffset(_ *kernel.Version) uint64 {
return uint64(120)
}

func getSuperBlockFlagsOffset(_ *kernel.Version) uint64 {
return uint64(80)
}
Expand Down
7 changes: 7 additions & 0 deletions pkg/security/probe/probe_ebpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -2491,6 +2491,13 @@ 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")
constantFetcher.AppendOffsetofRequest(constantfetch.OffsetInodeGid, "struct inode", "i_gid", "linux/fs.h")
constantFetcher.AppendOffsetofRequest(constantfetch.OffsetInodeNlink, "struct inode", "i_nlink", "linux/fs.h")
constantFetcher.AppendOffsetofRequest(constantfetch.OffsetInodeMtime, "struct inode", "__i_mtime", "linux/fs.h")
constantFetcher.AppendOffsetofRequest(constantfetch.OffsetInodeCtime, "struct inode", "__i_ctime", "linux/fs.h")
}

// HandleActions handles the rule actions
Expand Down
11 changes: 7 additions & 4 deletions pkg/security/resolvers/process/resolver_ebpf.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,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)
}

Expand Down Expand Up @@ -485,11 +488,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

Expand All @@ -503,11 +506,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
Expand Down

0 comments on commit 3e130e9

Please sign in to comment.