Skip to content

Commit 7484e7c

Browse files
laoarAlexei Starovoitov
authored andcommitted
bpf: mark vma->{vm_mm,vm_file} as __safe_trusted_or_null
The vma->vm_mm might be NULL and it can be accessed outside of RCU. Thus, we can mark it as trusted_or_null. With this change, BPF helpers can safely access vma->vm_mm to retrieve the associated mm_struct from the VMA. Then we can make policy decision from the VMA. The "trusted" annotation enables direct access to vma->vm_mm within kfuncs marked with KF_TRUSTED_ARGS or KF_RCU, such as bpf_task_get_cgroup1() and bpf_task_under_cgroup(). Conversely, "null" enforcement requires all callsites using vma->vm_mm to perform NULL checks. The lsm selftest must be modified because it directly accesses vma->vm_mm without a NULL pointer check; otherwise it will break due to this change. For the VMA based THP policy, the use case is as follows, @mm = @vma->vm_mm; // vm_area_struct::vm_mm is trusted or null if (!@mm) return; bpf_rcu_read_lock(); // rcu lock must be held to dereference the owner @owner = @mm->owner; // mm_struct::owner is rcu trusted or null if (!@owner) goto out; @Cgroup1 = bpf_task_get_cgroup1(@owner, MEMCG_HIERARCHY_ID); /* make the decision based on the @Cgroup1 attribute */ bpf_cgroup_release(@Cgroup1); // release the associated cgroup out: bpf_rcu_read_unlock(); PSI memory information can be obtained from the associated cgroup to inform policy decisions. Since upstream PSI support is currently limited to cgroup v2, the following example demonstrates cgroup v2 implementation: @owner = @mm->owner; if (@owner) { // @ancestor_cgid is user-configured @ancestor = bpf_cgroup_from_id(@ancestor_cgid); if (bpf_task_under_cgroup(@owner, @ancestor)) { @psi_group = @ancestor->psi; /* Extract PSI metrics from @psi_group and * implement policy logic based on the values */ } } The vma::vm_file can also be marked with __safe_trusted_or_null. No additional selftests are required since vma->vm_file and vma->vm_mm are already validated in the existing selftest suite. Signed-off-by: Yafang Shao <[email protected]> Acked-by: Lorenzo Stoakes <[email protected]> Cc: "Liam R. Howlett" <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent ec8e3e2 commit 7484e7c

File tree

2 files changed

+11
-3
lines changed

2 files changed

+11
-3
lines changed

kernel/bpf/verifier.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7096,6 +7096,11 @@ BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct socket) {
70967096
struct sock *sk;
70977097
};
70987098

7099+
BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct vm_area_struct) {
7100+
struct mm_struct *vm_mm;
7101+
struct file *vm_file;
7102+
};
7103+
70997104
static bool type_is_rcu(struct bpf_verifier_env *env,
71007105
struct bpf_reg_state *reg,
71017106
const char *field_name, u32 btf_id)
@@ -7137,6 +7142,7 @@ static bool type_is_trusted_or_null(struct bpf_verifier_env *env,
71377142
{
71387143
BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct socket));
71397144
BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct dentry));
7145+
BTF_TYPE_EMIT(BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct vm_area_struct));
71407146

71417147
return btf_nested_type_is_trusted(&env->log, reg, field_name, btf_id,
71427148
"__safe_trusted_or_null");

tools/testing/selftests/bpf/progs/lsm.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,16 @@ SEC("lsm/file_mprotect")
8989
int BPF_PROG(test_int_hook, struct vm_area_struct *vma,
9090
unsigned long reqprot, unsigned long prot, int ret)
9191
{
92-
if (ret != 0)
92+
struct mm_struct *mm = vma->vm_mm;
93+
94+
if (ret != 0 || !mm)
9395
return ret;
9496

9597
__s32 pid = bpf_get_current_pid_tgid() >> 32;
9698
int is_stack = 0;
9799

98-
is_stack = (vma->vm_start <= vma->vm_mm->start_stack &&
99-
vma->vm_end >= vma->vm_mm->start_stack);
100+
is_stack = (vma->vm_start <= mm->start_stack &&
101+
vma->vm_end >= mm->start_stack);
100102

101103
if (is_stack && monitored_pid == pid) {
102104
mprotect_count++;

0 commit comments

Comments
 (0)