Skip to content

Commit be542ca

Browse files
committed
Add BPF LSM task_kill hook for cross-branch signal isolation
Signed-off-by: Cong Wang <cwang@multikernel.io>
1 parent 33321db commit be542ca

2 files changed

Lines changed: 41 additions & 3 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ build/
1111

1212
# Generated BPF headers (regenerate via: make -C src/branching/process/bpf vmlinux.h)
1313
src/branching/process/bpf/vmlinux.h
14+
src/branching/process/bpf/*.o

src/branching/process/bpf/branch_tracker.bpf.c

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
/*
33
* branch_tracker.bpf.c — BPF LSM program for branch process tracking.
44
*
5-
* Hooks task_alloc and task_free to inescapably track all descendants
6-
* of registered branch root PIDs. Supports atomic fork-denial during
7-
* branch teardown.
5+
* Hooks task_alloc, task_free, and task_kill to inescapably track all
6+
* descendants of registered branch root PIDs. Supports atomic
7+
* fork-denial during branch teardown and cross-branch signal isolation.
88
*
99
* Compile:
1010
* clang -g -O2 -target bpf -D__TARGET_ARCH_x86 \
@@ -62,6 +62,43 @@ int BPF_PROG(branch_task_alloc, struct task_struct *task,
6262
return 0;
6363
}
6464

65+
/*
66+
* LSM hook: task_kill — fires on signal delivery (kill, tkill, tgkill).
67+
*
68+
* Enforces cross-branch signal isolation:
69+
* - Untracked process → any target: allowed (parent/orchestrator)
70+
* - Tracked process → same branch: allowed
71+
* - Tracked process → different branch or untracked: denied (-EPERM)
72+
*
73+
* This prevents a child in one branch from killing processes in
74+
* another branch or the parent orchestrator.
75+
*/
76+
SEC("lsm/task_kill")
77+
int BPF_PROG(branch_task_kill, struct task_struct *target,
78+
struct kernel_siginfo *info, int sig,
79+
const struct cred *cred)
80+
{
81+
__u32 sender_pid = bpf_get_current_pid_tgid() >> 32;
82+
__u64 *sender_bid = bpf_map_lookup_elem(&branch_pids, &sender_pid);
83+
84+
/* Untracked sender (parent/orchestrator) — always allow. */
85+
if (!sender_bid)
86+
return 0;
87+
88+
__u32 target_pid = BPF_CORE_READ(target, tgid);
89+
__u64 *target_bid = bpf_map_lookup_elem(&branch_pids, &target_pid);
90+
91+
/* Target is not tracked — deny (protects parent). */
92+
if (!target_bid)
93+
return -1; /* -EPERM */
94+
95+
/* Both tracked — allow only within the same branch. */
96+
if (*sender_bid != *target_bid)
97+
return -1; /* -EPERM */
98+
99+
return 0;
100+
}
101+
65102
/*
66103
* LSM hook: task_free — fires when a process exits.
67104
*

0 commit comments

Comments
 (0)