Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions lockc/src/bpf/lockc.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,67 @@ int BPF_PROG(mount_audit, const char *dev_name, const struct path *path,
return ret;
}

/*
* setuid_audit - LSM program triggered when user UID is changed.
* The goal is to deny changing user ID from regular account to root user account.
* @cred *new: data structure with new user context
* @cred *old: data structure with old user context
* @flags: additional flags
* @ret_prev: return code of a previous BPF program using the sb_mount hook
*
* Return: 0 if changing UID is allowed. -EPERM if root account not allowed. -EFAULT if there was
* a problem with reading the kernel strings into buffers or any important
* buffer is NULL.
*/
SEC("lsm/task_fix_setuid")
int BPF_PROG(setuid_audit, struct cred *new, const struct cred *old, int flags, int ret_prev)
{
int ret = 0;
char comm[TASK_COMM_LEN];

pid_t pid = bpf_get_current_pid_tgid() >> 32;
enum container_policy_level policy_level = get_policy_level(pid);

if (bpf_get_current_comm(&comm, sizeof(comm)) < 0)
return -EFAULT;

bpf_printk("setuid: process command: %s\n", comm);

uid_t uid_old = BPF_CORE_READ(old, uid).val;
bpf_printk("setuid: user current UID: %d\n", uid_old);

uid_t uid_new = BPF_CORE_READ(new, uid).val;
bpf_printk("setuid: user requested UID: %d\n", uid_new);

switch (policy_level) {
case POLICY_LEVEL_LOOKUP_ERR:
ret = -EPERM;
goto out;
case POLICY_LEVEL_NOT_FOUND:
goto out;
case POLICY_LEVEL_RESTRICTED:
bpf_printk("setuid: policy: restricted\n");
break;
case POLICY_LEVEL_BASELINE:
bpf_printk("setuid: policy: baseline\n");
break;
case POLICY_LEVEL_PRIVILEGED:
bpf_printk("setuid: root user allow\n");
goto out;
}

// TODO mjura: add configuration option for what UID this restrion should be applied
if ((uid_new == 0) && (uid_old >= 1000)) {
bpf_printk("setuid: root user deny\n");
ret = -EPERM;
}

out:
if (ret_prev != 0)
return ret_prev;
return ret;
}

SEC("lsm/file_open")
int BPF_PROG(open_audit, struct file *file, int ret_prev)
{
Expand Down
7 changes: 7 additions & 0 deletions lockc/src/load.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ pub fn attach_programs(bpf: &mut Bpf) -> Result<(), AttachError> {
open_audit.load("file_open", &btf)?;
open_audit.attach()?;

let setuid_audit: &mut Lsm = bpf
.program_mut("setuid_audit")
.ok_or(AttachError::ProgLoad)?
.try_into()?;
setuid_audit.load("setuid_audit", &btf)?;
setuid_audit.attach()?;

Ok(())
}

Expand Down