Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at nocache-cleanup 133 lines 3.7 kB view raw
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}