File Index
Files and directories
Sign in
FILE

test_set_remove_xattr.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/progs/test_set_remove_xattr.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
  3
  4#include "vmlinux.h"
  5#include <errno.h>
  6#include <bpf/bpf_tracing.h>
  7#include "bpf_kfuncs.h"
  8#include "bpf_misc.h"
  9
 10char _license[] SEC("license") = "GPL";
 11
 12__u32 monitored_pid;
 13
 14const char xattr_foo[] = "security.bpf.foo";
 15const char xattr_bar[] = "security.bpf.bar";
 16static const char xattr_selinux[] = "security.selinux";
 17char value_bar[] = "world";
 18char read_value[32];
 19
 20bool set_security_bpf_bar_success;
 21bool remove_security_bpf_bar_success;
 22bool set_security_selinux_fail;
 23bool remove_security_selinux_fail;
 24
 25char name_buf[32];
 26
 27static inline bool name_match_foo(const char *name)
 28{
 29	bpf_probe_read_kernel(name_buf, sizeof(name_buf), name);
 30
 31	return !bpf_strncmp(name_buf, sizeof(xattr_foo), xattr_foo);
 32}
 33
 34/* Test bpf_set_dentry_xattr and bpf_remove_dentry_xattr */
 35SEC("lsm.s/inode_getxattr")
 36int BPF_PROG(test_inode_getxattr, struct dentry *dentry, char *name)
 37{
 38	struct bpf_dynptr value_ptr;
 39	__u32 pid;
 40	int ret;
 41
 42	pid = bpf_get_current_pid_tgid() >> 32;
 43	if (pid != monitored_pid)
 44		return 0;
 45
 46	/* Only do the following for security.bpf.foo */
 47	if (!name_match_foo(name))
 48		return 0;
 49
 50	bpf_dynptr_from_mem(read_value, sizeof(read_value), 0, &value_ptr);
 51
 52	/* read security.bpf.bar */
 53	ret = bpf_get_dentry_xattr(dentry, xattr_bar, &value_ptr);
 54
 55	if (ret < 0) {
 56		/* If security.bpf.bar doesn't exist, set it */
 57		bpf_dynptr_from_mem(value_bar, sizeof(value_bar), 0, &value_ptr);
 58
 59		ret = bpf_set_dentry_xattr(dentry, xattr_bar, &value_ptr, 0);
 60		if (!ret)
 61			set_security_bpf_bar_success = true;
 62		ret = bpf_set_dentry_xattr(dentry, xattr_selinux, &value_ptr, 0);
 63		if (ret)
 64			set_security_selinux_fail = true;
 65	} else {
 66		/* If security.bpf.bar exists, remove it */
 67		ret = bpf_remove_dentry_xattr(dentry, xattr_bar);
 68		if (!ret)
 69			remove_security_bpf_bar_success = true;
 70
 71		ret = bpf_remove_dentry_xattr(dentry, xattr_selinux);
 72		if (ret)
 73			remove_security_selinux_fail = true;
 74	}
 75
 76	return 0;
 77}
 78
 79bool locked_set_security_bpf_bar_success;
 80bool locked_remove_security_bpf_bar_success;
 81bool locked_set_security_selinux_fail;
 82bool locked_remove_security_selinux_fail;
 83
 84/* Test bpf_set_dentry_xattr_locked and bpf_remove_dentry_xattr_locked.
 85 * It not necessary to differentiate the _locked version and the
 86 * not-_locked version in the BPF program. The verifier will fix them up
 87 * properly.
 88 */
 89SEC("lsm.s/inode_setxattr")
 90int BPF_PROG(test_inode_setxattr, struct mnt_idmap *idmap,
 91	     struct dentry *dentry, const char *name,
 92	     const void *value, size_t size, int flags)
 93{
 94	struct bpf_dynptr value_ptr;
 95	__u32 pid;
 96	int ret;
 97
 98	pid = bpf_get_current_pid_tgid() >> 32;
 99	if (pid != monitored_pid)
100		return 0;
101
102	/* Only do the following for security.bpf.foo */
103	if (!name_match_foo(name))
104		return 0;
105
106	bpf_dynptr_from_mem(read_value, sizeof(read_value), 0, &value_ptr);
107
108	/* read security.bpf.bar */
109	ret = bpf_get_dentry_xattr(dentry, xattr_bar, &value_ptr);
110
111	if (ret < 0) {
112		/* If security.bpf.bar doesn't exist, set it */
113		bpf_dynptr_from_mem(value_bar, sizeof(value_bar), 0, &value_ptr);
114
115		ret = bpf_set_dentry_xattr(dentry, xattr_bar, &value_ptr, 0);
116		if (!ret)
117			locked_set_security_bpf_bar_success = true;
118		ret = bpf_set_dentry_xattr(dentry, xattr_selinux, &value_ptr, 0);
119		if (ret)
120			locked_set_security_selinux_fail = true;
121	} else {
122		/* If security.bpf.bar exists, remove it */
123		ret = bpf_remove_dentry_xattr(dentry, xattr_bar);
124		if (!ret)
125			locked_remove_security_bpf_bar_success = true;
126
127		ret = bpf_remove_dentry_xattr(dentry, xattr_selinux);
128		if (ret)
129			locked_remove_security_selinux_fail = true;
130	}
131
132	return 0;
133}
~/ Read-only file preview.