Skip to content

Commit

Permalink
cleanup(driver): simplify exe_upper_layer extraction
Browse files Browse the repository at this point in the history
Signed-off-by: Andrea Terzolo <[email protected]>
  • Loading branch information
Andreagit97 committed Jul 15, 2024
1 parent 0a9ede3 commit 9299ebe
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 249 deletions.
125 changes: 37 additions & 88 deletions driver/bpf/fillers.h
Original file line number Diff line number Diff line change
Expand Up @@ -2314,48 +2314,28 @@ static __always_inline bool get_exe_writable(struct inode *inode, struct cred *c
return false;
}

static __always_inline bool get_exe_upper_layer(struct dentry *dentry, struct super_block *sb)
static __always_inline bool get_exe_upper_layer(struct file *file)
{
struct dentry* dentry = NULL;
bpf_probe_read_kernel(&dentry, sizeof(dentry), &file->f_path.dentry);
struct super_block* sb = (struct super_block*)_READ(dentry->d_sb);
unsigned long sb_magic = _READ(sb->s_magic);
if(sb_magic == PPM_OVERLAYFS_SUPER_MAGIC)
{
struct dentry *upper_dentry = NULL;
char *vfs_inode = (char *)_READ(dentry->d_inode);

// Pointer arithmetics due to unexported ovl_inode struct
// warning: this works if and only if the dentry pointer is placed right after the inode struct
struct dentry *tmp = (struct dentry *)(vfs_inode + sizeof(struct inode));
upper_dentry = _READ(tmp);
if(!upper_dentry)
{
return false;
}

unsigned int d_flags = _READ(dentry->d_flags);
bool disconnected = (d_flags & DCACHE_DISCONNECTED);
if(disconnected)
{
return true;
}

#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)
struct ovl_entry *oe = (struct ovl_entry*)_READ(dentry->d_fsdata);
unsigned long has_upper = (unsigned long)_READ(oe->has_upper);
#elif LINUX_VERSION_CODE < KERNEL_VERSION(6, 5, 0)
struct ovl_entry *oe = (struct ovl_entry*)_READ(dentry->d_fsdata);
unsigned long flags = _READ(oe->flags);
unsigned long has_upper = (flags & (1U << (OVL_E_UPPER_ALIAS)));
#else
unsigned long flags = (unsigned long)_READ(dentry->d_fsdata);
unsigned long has_upper = (flags & (1U << (OVL_E_UPPER_ALIAS)));
#endif
if(sb_magic != PPM_OVERLAYFS_SUPER_MAGIC)
{
return false;
}

if(has_upper)
{
return true;
}
char *vfs_inode = (char *)_READ(dentry->d_inode);
struct dentry *upper_dentry = NULL;
bpf_probe_read_kernel(&upper_dentry, sizeof(upper_dentry), (char *)vfs_inode + sizeof(struct inode));
if(!upper_dentry)
{
return false;
}
return false;

struct inode *upper_ino = _READ(upper_dentry->d_inode);
return _READ(upper_ino->i_ino) != 0;
}

FILLER(proc_startupdate, true)
Expand Down Expand Up @@ -2867,43 +2847,27 @@ FILLER(execve_extra_tail_1, true)
struct cred *cred = (struct cred *)_READ(task->cred);
struct file *exe_file = get_exe_file(task);
struct inode *inode = get_file_inode(exe_file);
struct path f_path = (struct path)_READ(exe_file->f_path);
struct dentry* dentry = f_path.dentry;

#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0)
struct super_block* sb = _READ(dentry->d_sb);
#else
struct super_block *sb = _READ(inode->i_sb);
#endif

/* `exe_writable` and `exe_upper_layer` flag logic */
bool exe_writable = false;
bool exe_upper_layer = false;

uint32_t flags = 0;
kuid_t euid;
kuid_t euid = {0};

if(sb && inode)
if(inode)
{
/*
* exe_writable
*/
exe_writable = get_exe_writable(inode, cred);
bool exe_writable = get_exe_writable(inode, cred);
if (exe_writable)
{
flags |= PPM_EXE_WRITABLE;
}
}

/*
* exe_upper_layer
*/
exe_upper_layer = get_exe_upper_layer(dentry,sb);
if (exe_upper_layer)
{
flags |= PPM_EXE_UPPER_LAYER;
}

// write all additional flags for execve family here...
/*
* exe_upper_layer
*/
if(exe_file && get_exe_upper_layer(exe_file))
{
flags |= PPM_EXE_UPPER_LAYER;
}

if(exe_file && get_exe_from_memfd(exe_file))
Expand Down Expand Up @@ -6791,42 +6755,27 @@ FILLER(sched_prog_exec_4, false)
struct cred *cred = (struct cred *)_READ(task->cred);
struct file *exe_file = get_exe_file(task);
struct inode *inode = get_file_inode(exe_file);
struct path f_path = (struct path)_READ(exe_file->f_path);
struct dentry* dentry = f_path.dentry;

#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 18, 0)
struct super_block* sb = _READ(dentry->d_sb);
#else
struct super_block *sb = _READ(inode->i_sb);
#endif

/* `exe_writable` and `exe_upper_layer` flag logic */
bool exe_writable = false;
bool exe_upper_layer = false;
uint32_t flags = 0;
kuid_t euid;
kuid_t euid = {0};

if(sb && inode)
if(inode)
{
/*
* exe_writable
*/
exe_writable = get_exe_writable(inode, cred);
bool exe_writable = get_exe_writable(inode, cred);
if (exe_writable)
{
flags |= PPM_EXE_WRITABLE;
}
}

/*
* exe_upper_layer
*/
exe_upper_layer = get_exe_upper_layer(dentry,sb);
if (exe_upper_layer)
{
flags |= PPM_EXE_UPPER_LAYER;
}

// write all additional flags for execve family here...
/*
* exe_upper_layer
*/
if (exe_file && get_exe_upper_layer(exe_file))
{
flags |= PPM_EXE_UPPER_LAYER;
}

if(exe_file && get_exe_from_memfd(exe_file))
Expand Down
31 changes: 0 additions & 31 deletions driver/bpf/missing_definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,6 @@ or GPL2.txt for full copies of the license.
#ifndef __BPF_MISSING_DEFINITIONS_H__
#define __BPF_MISSING_DEFINITIONS_H__

#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)
struct ovl_entry {
union {
struct {
unsigned long has_upper;
bool opaque;
};
struct rcu_head rcu;
};
unsigned numlower;
struct path lowerstack[];
};
#else
struct ovl_entry {
union {
struct {
unsigned long flags;
};
struct rcu_head rcu;
};
unsigned numlower;
//struct ovl_path lowerstack[];
};

enum ovl_entry_flag {
OVL_E_UPPER_ALIAS,
OVL_E_OPAQUE,
OVL_E_CONNECTED,
};
#endif

#include <linux/mount.h>
/* This require the inlclude `linux/mount.h` for `vfsmount` definition */
struct mount {
Expand Down
5 changes: 0 additions & 5 deletions driver/modern_bpf/definitions/missing_definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -1586,9 +1586,4 @@
#define MODULE_INIT_COMPRESSED_FILE 4
/*==================================== FINIT FLAGS ================================*/

/*==================================== OVERLAY FLAGS ================================*/
#define DCACHE_DISCONNECTED 0x20
#define OVL_E_UPPER_ALIAS 0
/*==================================== OVERLAY FLAGS ================================*/

#endif /* __MISSING_DEFINITIONS_H__ */
5 changes: 0 additions & 5 deletions driver/modern_bpf/definitions/struct_flavors.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,6 @@ struct inode___v6_7 {
struct timespec64 __i_mtime;
};

struct ovl_entry___before_v6_5
{
long unsigned int flags;
};

#ifndef BPF_NO_PRESERVE_ACCESS_INDEX
#pragma clang attribute pop
#endif
Expand Down
65 changes: 20 additions & 45 deletions driver/modern_bpf/helpers/extract/extract_from_kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -831,60 +831,35 @@ static __always_inline void extract__egid(struct task_struct *task, uint32_t *eg
// EXECVE FLAGS EXTRACTION
////////////////////////

static __always_inline bool extract__exe_upper_layer(struct inode *inode, struct file *exe_file)
static __always_inline bool extract__exe_upper_layer(struct file *file)
{
unsigned long sb_magic = BPF_CORE_READ(inode, i_sb, s_magic);
struct dentry *dentry = (struct dentry *)BPF_CORE_READ(file, f_path.dentry);
unsigned long sb_magic = BPF_CORE_READ(dentry, d_sb, s_magic);

if(sb_magic == PPM_OVERLAYFS_SUPER_MAGIC)
if(sb_magic != PPM_OVERLAYFS_SUPER_MAGIC)
{
struct dentry *upper_dentry = NULL;
char *vfs_inode = (char *)inode;
unsigned long inode_size = bpf_core_type_size(struct inode);
if(!inode_size)
{
return false;
}

bpf_probe_read_kernel(&upper_dentry, sizeof(upper_dentry), vfs_inode + inode_size);

if(!upper_dentry)
{
return false;
}

struct dentry *dentry = (struct dentry *)BPF_CORE_READ(exe_file, f_path.dentry);

unsigned int d_flags = BPF_CORE_READ(dentry, d_flags);
bool disconnected = (d_flags & DCACHE_DISCONNECTED);
if(disconnected)
{
return true;
}

unsigned long flags = 0;
if(bpf_core_field_exists(((struct ovl_entry___before_v6_5*)0)->flags))
{
// kernel <6.5
struct ovl_entry___before_v6_5 *oe = (struct ovl_entry___before_v6_5*)BPF_CORE_READ(dentry, d_fsdata);
flags = (unsigned long)BPF_CORE_READ(oe, flags);
}
else
{
// In kernels >=6.5 d_fsdata represents an ovl_entry_flag.
flags = (unsigned long)BPF_CORE_READ(dentry, d_fsdata);
}
return false;
}

unsigned long has_upper = (flags & (1U << (OVL_E_UPPER_ALIAS)));
if(has_upper)
{
return true;
}
char *vfs_inode = (char *)BPF_CORE_READ(dentry, d_inode);
// We need to compute the size of the inode struct at load time since it can change between kernel versions
unsigned long inode_size = bpf_core_type_size(struct inode);
if(!inode_size)
{
return false;
}

struct dentry *upper_dentry = NULL;
bpf_probe_read_kernel(&upper_dentry, sizeof(upper_dentry), (char *)vfs_inode + inode_size);
if(!upper_dentry)
{
return false;
}

return false;
return BPF_CORE_READ(upper_dentry, d_inode, i_ino) != 0;
}


/*
* Detect whether the file being referenced is an anonymous file created using memfd_create()
* and is being executed by referencing its file descriptor (fd). This type of file does not
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ int BPF_PROG(t1_sched_p_exec,
{
flags |= PPM_EXE_WRITABLE;
}
if(extract__exe_upper_layer(exe_inode, exe_file))
if(extract__exe_upper_layer(exe_file))
{
flags |= PPM_EXE_UPPER_LAYER;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ int BPF_PROG(t1_execve_x,
{
flags |= PPM_EXE_WRITABLE;
}
if(extract__exe_upper_layer(exe_inode, exe_file))
if(extract__exe_upper_layer(exe_file))
{
flags |= PPM_EXE_UPPER_LAYER;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ int BPF_PROG(t1_execveat_x,
{
flags |= PPM_EXE_WRITABLE;
}
if(extract__exe_upper_layer(exe_inode, exe_file))
if(extract__exe_upper_layer(exe_file))
{
flags |= PPM_EXE_UPPER_LAYER;
}
Expand Down
Loading

0 comments on commit 9299ebe

Please sign in to comment.