SeaBee
Loading...
Searching...
No Matches
Data Structures | Macros | Functions | Variables
seabee.bpf.c File Reference
#include <bpf/vmlinux.h>
#include <bpf/vmlinux_features.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include "logging.h"
#include "logging_types.h"
#include "seabee_log.h"
#include "seabee_maps.h"
#include "seabee_utils.h"
#include "shared_rust_types.h"
Include dependency graph for seabee.bpf.c:

Data Structures

struct  path_to_pol_id
 
struct  path_storage
 storage path buffers which cannot fit on ebpf stack per cpu is important to prevent concurrency issues More...
 

Macros

#define FMODE_WRITE   (1 << 1)
 

Functions

int seabee_bpf_map (struct bpf_map *map, fmode_t fmode, int ret)
 Blocks manipulation a protected map.
 
int seabee_locked_down (enum lockdown_reason what,)
 Blocks the use of the bpf_write_user() helper.
 
int seabee_task_kill (struct task_struct *p, struct kernel_siginfo *info, int sig, const struct cred *cred, int ret)
 Block unwanted signals to the seabee userspace process.
 
int seabee_file_open (struct file *file,)
 make protected files read-only.
 
int seabee_inode_permission (struct inode *inode, int mask)
 prevent writes to protected inodes
 
int seabee_inode_unlink (struct inode *dir, struct dentry *dentry)
 Prevents unlinking/removing protected files or pins.
 
int seabee_inode_rmdir (struct inode *dir, struct dentry *dentry)
 Prevents unlinking/removing protected folders.
 
int seabee_inode_setattr (struct dentry *dentry, struct iattr *attr)
 prevents modification of attributes on protected inodes
 
int seabee_inode_setxattr (struct user_namespace *mnt_userns, struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
 prevent modification of extended attributes on protected inodes
 
int seabee_inode_rename (struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags)
 prevent rename of a protected inode
 
int seabee_sb_umount (struct vfsmount *mnt, int flags, int ret)
 Prevent unmounting the BPF filesystem.
 
int seabee_kernel_module_request (char *kmod_name,)
 Prevent a kernel module from being automatically loaded by the kernel.
 
int seabee_kernel_read_file (struct file *file, enum kernel_read_file_id id, bool contents)
 Blocks the loading of a kernel module via a file handle.
 
int seabee_kernel_load_data (enum kernel_load_data_id id, bool contents)
 Blocks the loading of a kernel module via a data blob.
 
int seabee_ptrace_access_check (struct task_struct *child, unsigned int mode, int ret)
 Blocks attempts to ptrace a protected process.
 
int seabee_task_alloc (struct task_struct *task, unsigned long clone_flags, int ret)
 Blocks attempts to fork() the seabee process.
 
int seabee_label_sock (struct socket *sock, struct sockaddr *address, int addrlen)
 used to label a socket on creation.
 
int seabeectl_auth (struct sock *sock, struct sock *other, struct sock *newsk)
 check if a process is allowed to connect to a socket.
 
int seabee_label_process (struct linux_binprm *bprm, int ret)
 Label a process when it starts.
 
int seabee_label_child_process (struct task_struct *child_task, unsigned long clone_flags)
 Label a child process with same policy id as its parent.
 
int seabee_label_map (struct bpf_map *map, int ret)
 Label a bpf map on creation using the same label as the process that created it.
 
int seabee_unlabel_map (struct bpf_map *map, int ret)
 Unlabel an eBPF map when it is freed.
 
int seabee_start_pin (int cmd, union bpf_attr *attr, unsigned int size, int ret)
 Used to identify a bpf program is being pinned.
 
int seabee_label_pin (struct dentry *dentry, struct inode *inode)
 Label an inode associated with a bpf pin.
 
int seabee_stop_pin (struct dentry *dentry, struct inode *inode)
 Used to identify that a process has finished pinning.
 
int seabee_label_inode_runtime (struct dentry *dentry, struct inode *inode)
 Label inodes created at runtime giving them the same label as the parent.
 

Variables

char LICENSE [] = "GPL"
 License of the BPF program.
 
u32 log_level
 The level of the logs to filter out.
 
u32 kmod_modification
 The level of access for kernel modules.
 
u32 my_pid
 The process id of the userspace that loads these programs.
 
u64 bpf_dev_id
 The device id of the /sys/bpf mount point inode.
 
u64 sys_dev_id
 The device id of the /sys mount point inode.
 
u8 my_binary_path [PATH_MAX]
 The path of the seabee binary. u8 plays nicer with rust.
 
u8 null_path [PATH_MAX]
 used to null a buffer
 
struct log_ringbuf log_ringbuf
 eBPF Maps
 
struct inode_storage inode_storage
 maps and inode to a policy id
 
struct policy_map policy_map
 Hashmap from policy id to policy config.
 
struct task_storage task_storage
 maps process pid to policy id
 
struct sk_storage sk_storage
 struct sock to policy id
 
struct map_to_pol_id map_to_pol_id
 maps a map id to a policy id
 
struct path_to_pol_id path_to_pol_id
 Maps a filename to a policy id.
 
struct path_storage path_storage
 storage for paths
 

Function Documentation

◆ seabee_bpf_map()

int seabee_bpf_map ( struct bpf_map *  map,
fmode_t  fmode,
int  ret 
)

Blocks manipulation a protected map.

This is achieved by preventing BPF file descriptors from being created for protected maps.

A file descriptor for a map can be obtained via the commands:

Parameters
mapinternal BPF map structure
fmodefile mode to open with (read / write / etc)
retreturn code from previous LSM hook
Returns
ALLOW or DENY

◆ seabee_file_open()

int seabee_file_open ( struct file *  file)

make protected files read-only.

This hook is called to check if a file is allowed to be accessed. Deny access to protected files by checking file->f_mode. This tells if the file is being opened for reading or writing.

◆ seabee_inode_permission()

int seabee_inode_permission ( struct inode *  inode,
int  mask 
)

prevent writes to protected inodes

Parameters
inodeinode
maskaccess mask

◆ seabee_inode_rename()

int seabee_inode_rename ( struct inode *  old_dir,
struct dentry *  old_dentry,
struct inode *  new_dir,
struct dentry *  new_dentry,
unsigned int  flags 
)

prevent rename of a protected inode

Parameters
new_dentrythe new file which will be replaced by old file

◆ seabee_inode_rmdir()

int seabee_inode_rmdir ( struct inode *  dir,
struct dentry *  dentry 
)

Prevents unlinking/removing protected folders.

Parameters
dirthe parent directory
dentrythe directory to be removed
Returns
ALLOW or DENY

◆ seabee_inode_setattr()

int seabee_inode_setattr ( struct dentry *  dentry,
struct iattr *  attr 
)

prevents modification of attributes on protected inodes

Parameters
dentryfile

◆ seabee_inode_setxattr()

int seabee_inode_setxattr ( struct user_namespace *  mnt_userns,
struct dentry *  dentry,
const char *  name,
const void *  value,
size_t  size,
int  flags 
)

prevent modification of extended attributes on protected inodes

Parameters
dentryfile

◆ seabee_inode_unlink()

int seabee_inode_unlink ( struct inode *  dir,
struct dentry *  dentry 
)

Prevents unlinking/removing protected files or pins.

Parameters
dirthe parent directory
dentrythe file being unlinked
Returns
ALLOW or DENY

◆ seabee_kernel_load_data()

int seabee_kernel_load_data ( enum kernel_load_data_id  id,
bool  contents 
)

Blocks the loading of a kernel module via a data blob.

lsm/kernel_load_data is invoked when userspace tries to load a data blob from its memory into the kernel, including but not limited to kernel modules loaded via init_module().

enum kernel_load_data_id is the same as __kernel_read_file_id defined in https://elixir.bootlin.com/linux/latest/source/include/linux/kernel_read_file.h#L9 It has several types including unknown, firmware, module, kexec-image, kexec-initramfs, security-policy, and x509-certificate. kernel-module seems most appropriate for our purposes, but the others should be taken into account later on.

Parameters
iddefines what kind of data is being read.
contentstrue if security_kernel_post_load_data() will be called
Returns
ALLOW or DENY

◆ seabee_kernel_module_request()

int seabee_kernel_module_request ( char *  kmod_name)

Prevent a kernel module from being automatically loaded by the kernel.

lsm/kernel_module_request is invoked when module auto-loading is triggered by some attempt to access kernel functionality implemented by a module. It is used internally by the kernel to check if loading a module is allowed.

Parameters
kmod_namethe name of ther kernel module to be loaded
Returns
ALLOW or DENY

◆ seabee_kernel_read_file()

int seabee_kernel_read_file ( struct file *  file,
enum kernel_read_file_id  id,
bool  contents 
)

Blocks the loading of a kernel module via a file handle.

lsm/kernel_read_file is invoked when the kernel is about to directly read from a file or the file system specified by userspace for some purpose including but not limited to kernel modules loaded via finit_module()

enum kernel_load_data_id is the same as __kernel_read_file_id defined in https://elixir.bootlin.com/linux/latest/source/include/linux/kernel_read_file.h#L9 It has several types including unknown, firmware, module, kexec-image, kexec-initramfs, security-policy, and x509-certificate. kernel-module seems most appropriate for our purposes, but the others should be taken into account later on.

Parameters
filethe file from which to read
ididentifies the type of data that is being read
contentstrue if security_post_read_file() will be called
Returns
ALLOW or DENY

◆ seabee_label_inode_runtime()

int seabee_label_inode_runtime ( struct dentry *  dentry,
struct inode *  inode 
)

Label inodes created at runtime giving them the same label as the parent.

security_d_instantiate is called whenever a dentry is first associated with an inode. That could be on creation or when it is first looked up.

Parameters
dentrydentry
inodeinode

◆ seabee_label_pin()

int seabee_label_pin ( struct dentry *  dentry,
struct inode *  inode 
)

Label an inode associated with a bpf pin.

This hook is called when a dentry becomes associated with an inode.

◆ seabee_label_process()

int seabee_label_process ( struct linux_binprm *  bprm,
int  ret 
)

Label a process when it starts.

This uses the path_to_pol_id map and the linux_binprm structure to attach a label to a task based on the path of the executable that started the task. This hook can be called multiple times during an execve, for example, if executing a script.

Parameters
bprmholds information about a binary that is going to be executed
Returns
ALLOW since this check is just for labeling and not for enforcement

◆ seabee_label_sock()

int seabee_label_sock ( struct socket *  sock,
struct sockaddr *  address,
int  addrlen 
)

used to label a socket on creation.

This will only label sockets created by the SeaBee userspace. Specifically this is used to control access to SeaBee's listening socket to ensure only seabeectl can connect to it.

Parameters
sockthe socket being bound
addressrequested bind address
addrlenlength of address
Returns
ALLOW to allow access

◆ seabee_locked_down()

int seabee_locked_down ( enum lockdown_reason  what)

Blocks the use of the bpf_write_user() helper.

This helper function is dangerous and it is better to disable it.

Parameters
whatwhy the lockdown hook is firing.
See also
man 7 kernel_lockdown

◆ seabee_ptrace_access_check()

int seabee_ptrace_access_check ( struct task_struct *  child,
unsigned int  mode,
int  ret 
)

Blocks attempts to ptrace a protected process.

This hook is called by a "tracer" process that is trying to use ptrace on a "tracee" process. In this case, the "child" argument.

note: there is also an lsm/ptrace_traceme hook. This hook is not checked because it is only invoked by the child process.

Parameters
childthe process that is going to be traced (tracee)
modePTRACE_MODE flags, see linux/ptrace.h
retthe return code of the previous LSM hook
Returns
ALLOW or DENY

◆ seabee_sb_umount()

int seabee_sb_umount ( struct vfsmount *  mnt,
int  flags,
int  ret 
)

Prevent unmounting the BPF filesystem.

Parameters
mntmounted filesystem
flagsunmount flags
retthe return code of the previous LSM hook
Returns
ALLOW or DENY

◆ seabee_task_alloc()

int seabee_task_alloc ( struct task_struct *  task,
unsigned long  clone_flags,
int  ret 
)

Blocks attempts to fork() the seabee process.

A fork() / clone() of the seabee process will inherit all of the memory and file-descriptors of the parent process. This would allow the child process to unload the BPF program or alter the map contents. This is more of a safety-net than anything.

Parameters
taskthe process that is going to be forked
clone_flagsflags from struct kernel_clone_args
retthe return code of the previous LSM hook
Returns
ALLOW or DENY

◆ seabee_task_kill()

int seabee_task_kill ( struct task_struct *  p,
struct kernel_siginfo *  info,
int  sig,
const struct cred *  cred,
int  ret 
)

Block unwanted signals to the seabee userspace process.

Deny any outside userspace signal that will stop our corresponding userspace process almost every signal will kill our process, we choose to enumerate (and allow) those which do not stop our process. Signals that originate from the kernel may not be caught because they may use a different code path that does not include this lsm hook. These signals include the ZERO signal and any signal specified in the signal_allow_mask

Parameters
ptarget process
infosignal info, can also be NULL or 1
sigsignal value
credcredentials of sender, may be NULL
retthe return code of the previous LSM hook
Returns
ALLOW or DENY
See also
signal numbering and default actions: man signal

◆ seabeectl_auth()

int seabeectl_auth ( struct sock *  sock,
struct sock *  other,
struct sock *  newsk 
)

check if a process is allowed to connect to a socket.

This is used to enforce that only seabeectl is allowed to connect to the listening socket of SeaBee in order to receive commands.

Parameters
sockoriginating sock
otherpeer sock
newsknew sock
Returns
ALLOW to allow access

Variable Documentation

◆ inode_storage

maps and inode to a policy id

local storage for inodes

◆ log_level

u32 log_level

The level of the logs to filter out.

Defined in each .bpf.c file. Specifies which logs to output to the ringbuf.

◆ log_ringbuf

eBPF Maps

Defined in each .bpf.c file. Specifies the ringbuf map to output logs to.

logs data back to userspace

◆ task_storage

maps process pid to policy id

local storage for tasks