1*d08e2045SMatt Bobrowski // SPDX-License-Identifier: GPL-2.0 2*d08e2045SMatt Bobrowski /* Copyright (c) 2024 Google LLC. */ 3*d08e2045SMatt Bobrowski 4*d08e2045SMatt Bobrowski #include <linux/bpf.h> 5*d08e2045SMatt Bobrowski #include <linux/btf.h> 6*d08e2045SMatt Bobrowski #include <linux/btf_ids.h> 7*d08e2045SMatt Bobrowski #include <linux/dcache.h> 8*d08e2045SMatt Bobrowski #include <linux/fs.h> 9*d08e2045SMatt Bobrowski #include <linux/file.h> 10*d08e2045SMatt Bobrowski #include <linux/mm.h> 11*d08e2045SMatt Bobrowski 12*d08e2045SMatt Bobrowski __bpf_kfunc_start_defs(); 13*d08e2045SMatt Bobrowski 14*d08e2045SMatt Bobrowski /** 15*d08e2045SMatt Bobrowski * bpf_get_task_exe_file - get a reference on the exe_file struct file member of 16*d08e2045SMatt Bobrowski * the mm_struct that is nested within the supplied 17*d08e2045SMatt Bobrowski * task_struct 18*d08e2045SMatt Bobrowski * @task: task_struct of which the nested mm_struct exe_file member to get a 19*d08e2045SMatt Bobrowski * reference on 20*d08e2045SMatt Bobrowski * 21*d08e2045SMatt Bobrowski * Get a reference on the exe_file struct file member field of the mm_struct 22*d08e2045SMatt Bobrowski * nested within the supplied *task*. The referenced file pointer acquired by 23*d08e2045SMatt Bobrowski * this BPF kfunc must be released using bpf_put_file(). Failing to call 24*d08e2045SMatt Bobrowski * bpf_put_file() on the returned referenced struct file pointer that has been 25*d08e2045SMatt Bobrowski * acquired by this BPF kfunc will result in the BPF program being rejected by 26*d08e2045SMatt Bobrowski * the BPF verifier. 27*d08e2045SMatt Bobrowski * 28*d08e2045SMatt Bobrowski * This BPF kfunc may only be called from BPF LSM programs. 29*d08e2045SMatt Bobrowski * 30*d08e2045SMatt Bobrowski * Internally, this BPF kfunc leans on get_task_exe_file(), such that calling 31*d08e2045SMatt Bobrowski * bpf_get_task_exe_file() would be analogous to calling get_task_exe_file() 32*d08e2045SMatt Bobrowski * directly in kernel context. 33*d08e2045SMatt Bobrowski * 34*d08e2045SMatt Bobrowski * Return: A referenced struct file pointer to the exe_file member of the 35*d08e2045SMatt Bobrowski * mm_struct that is nested within the supplied *task*. On error, NULL is 36*d08e2045SMatt Bobrowski * returned. 37*d08e2045SMatt Bobrowski */ 38*d08e2045SMatt Bobrowski __bpf_kfunc struct file *bpf_get_task_exe_file(struct task_struct *task) 39*d08e2045SMatt Bobrowski { 40*d08e2045SMatt Bobrowski return get_task_exe_file(task); 41*d08e2045SMatt Bobrowski } 42*d08e2045SMatt Bobrowski 43*d08e2045SMatt Bobrowski /** 44*d08e2045SMatt Bobrowski * bpf_put_file - put a reference on the supplied file 45*d08e2045SMatt Bobrowski * @file: file to put a reference on 46*d08e2045SMatt Bobrowski * 47*d08e2045SMatt Bobrowski * Put a reference on the supplied *file*. Only referenced file pointers may be 48*d08e2045SMatt Bobrowski * passed to this BPF kfunc. Attempting to pass an unreferenced file pointer, or 49*d08e2045SMatt Bobrowski * any other arbitrary pointer for that matter, will result in the BPF program 50*d08e2045SMatt Bobrowski * being rejected by the BPF verifier. 51*d08e2045SMatt Bobrowski * 52*d08e2045SMatt Bobrowski * This BPF kfunc may only be called from BPF LSM programs. 53*d08e2045SMatt Bobrowski */ 54*d08e2045SMatt Bobrowski __bpf_kfunc void bpf_put_file(struct file *file) 55*d08e2045SMatt Bobrowski { 56*d08e2045SMatt Bobrowski fput(file); 57*d08e2045SMatt Bobrowski } 58*d08e2045SMatt Bobrowski 59*d08e2045SMatt Bobrowski /** 60*d08e2045SMatt Bobrowski * bpf_path_d_path - resolve the pathname for the supplied path 61*d08e2045SMatt Bobrowski * @path: path to resolve the pathname for 62*d08e2045SMatt Bobrowski * @buf: buffer to return the resolved pathname in 63*d08e2045SMatt Bobrowski * @buf__sz: length of the supplied buffer 64*d08e2045SMatt Bobrowski * 65*d08e2045SMatt Bobrowski * Resolve the pathname for the supplied *path* and store it in *buf*. This BPF 66*d08e2045SMatt Bobrowski * kfunc is the safer variant of the legacy bpf_d_path() helper and should be 67*d08e2045SMatt Bobrowski * used in place of bpf_d_path() whenever possible. It enforces KF_TRUSTED_ARGS 68*d08e2045SMatt Bobrowski * semantics, meaning that the supplied *path* must itself hold a valid 69*d08e2045SMatt Bobrowski * reference, or else the BPF program will be outright rejected by the BPF 70*d08e2045SMatt Bobrowski * verifier. 71*d08e2045SMatt Bobrowski * 72*d08e2045SMatt Bobrowski * This BPF kfunc may only be called from BPF LSM programs. 73*d08e2045SMatt Bobrowski * 74*d08e2045SMatt Bobrowski * Return: A positive integer corresponding to the length of the resolved 75*d08e2045SMatt Bobrowski * pathname in *buf*, including the NUL termination character. On error, a 76*d08e2045SMatt Bobrowski * negative integer is returned. 77*d08e2045SMatt Bobrowski */ 78*d08e2045SMatt Bobrowski __bpf_kfunc int bpf_path_d_path(struct path *path, char *buf, size_t buf__sz) 79*d08e2045SMatt Bobrowski { 80*d08e2045SMatt Bobrowski int len; 81*d08e2045SMatt Bobrowski char *ret; 82*d08e2045SMatt Bobrowski 83*d08e2045SMatt Bobrowski if (!buf__sz) 84*d08e2045SMatt Bobrowski return -EINVAL; 85*d08e2045SMatt Bobrowski 86*d08e2045SMatt Bobrowski ret = d_path(path, buf, buf__sz); 87*d08e2045SMatt Bobrowski if (IS_ERR(ret)) 88*d08e2045SMatt Bobrowski return PTR_ERR(ret); 89*d08e2045SMatt Bobrowski 90*d08e2045SMatt Bobrowski len = buf + buf__sz - ret; 91*d08e2045SMatt Bobrowski memmove(buf, ret, len); 92*d08e2045SMatt Bobrowski return len; 93*d08e2045SMatt Bobrowski } 94*d08e2045SMatt Bobrowski 95*d08e2045SMatt Bobrowski __bpf_kfunc_end_defs(); 96*d08e2045SMatt Bobrowski 97*d08e2045SMatt Bobrowski BTF_KFUNCS_START(bpf_fs_kfunc_set_ids) 98*d08e2045SMatt Bobrowski BTF_ID_FLAGS(func, bpf_get_task_exe_file, 99*d08e2045SMatt Bobrowski KF_ACQUIRE | KF_TRUSTED_ARGS | KF_RET_NULL) 100*d08e2045SMatt Bobrowski BTF_ID_FLAGS(func, bpf_put_file, KF_RELEASE) 101*d08e2045SMatt Bobrowski BTF_ID_FLAGS(func, bpf_path_d_path, KF_TRUSTED_ARGS) 102*d08e2045SMatt Bobrowski BTF_KFUNCS_END(bpf_fs_kfunc_set_ids) 103*d08e2045SMatt Bobrowski 104*d08e2045SMatt Bobrowski static int bpf_fs_kfuncs_filter(const struct bpf_prog *prog, u32 kfunc_id) 105*d08e2045SMatt Bobrowski { 106*d08e2045SMatt Bobrowski if (!btf_id_set8_contains(&bpf_fs_kfunc_set_ids, kfunc_id) || 107*d08e2045SMatt Bobrowski prog->type == BPF_PROG_TYPE_LSM) 108*d08e2045SMatt Bobrowski return 0; 109*d08e2045SMatt Bobrowski return -EACCES; 110*d08e2045SMatt Bobrowski } 111*d08e2045SMatt Bobrowski 112*d08e2045SMatt Bobrowski static const struct btf_kfunc_id_set bpf_fs_kfunc_set = { 113*d08e2045SMatt Bobrowski .owner = THIS_MODULE, 114*d08e2045SMatt Bobrowski .set = &bpf_fs_kfunc_set_ids, 115*d08e2045SMatt Bobrowski .filter = bpf_fs_kfuncs_filter, 116*d08e2045SMatt Bobrowski }; 117*d08e2045SMatt Bobrowski 118*d08e2045SMatt Bobrowski static int __init bpf_fs_kfuncs_init(void) 119*d08e2045SMatt Bobrowski { 120*d08e2045SMatt Bobrowski return register_btf_kfunc_id_set(BPF_PROG_TYPE_LSM, &bpf_fs_kfunc_set); 121*d08e2045SMatt Bobrowski } 122*d08e2045SMatt Bobrowski 123*d08e2045SMatt Bobrowski late_initcall(bpf_fs_kfuncs_init); 124