xref: /linux/fs/bpf_fs_kfuncs.c (revision f4b369c6fe0ceaba2da2daff8c9eb415f85926dd)
1d08e2045SMatt Bobrowski // SPDX-License-Identifier: GPL-2.0
2d08e2045SMatt Bobrowski /* Copyright (c) 2024 Google LLC. */
3d08e2045SMatt Bobrowski 
4d08e2045SMatt Bobrowski #include <linux/bpf.h>
556467292SSong Liu #include <linux/bpf_lsm.h>
6d08e2045SMatt Bobrowski #include <linux/btf.h>
7d08e2045SMatt Bobrowski #include <linux/btf_ids.h>
8d08e2045SMatt Bobrowski #include <linux/dcache.h>
9d08e2045SMatt Bobrowski #include <linux/fs.h>
1056467292SSong Liu #include <linux/fsnotify.h>
11d08e2045SMatt Bobrowski #include <linux/file.h>
12b95ee904SSong Liu #include <linux/kernfs.h>
13d08e2045SMatt Bobrowski #include <linux/mm.h>
14fa4e5afaSSong Liu #include <linux/xattr.h>
15d08e2045SMatt Bobrowski 
16d08e2045SMatt Bobrowski __bpf_kfunc_start_defs();
17d08e2045SMatt Bobrowski 
18d08e2045SMatt Bobrowski /**
19d08e2045SMatt Bobrowski  * bpf_get_task_exe_file - get a reference on the exe_file struct file member of
20d08e2045SMatt Bobrowski  *                         the mm_struct that is nested within the supplied
21d08e2045SMatt Bobrowski  *                         task_struct
22d08e2045SMatt Bobrowski  * @task: task_struct of which the nested mm_struct exe_file member to get a
23d08e2045SMatt Bobrowski  * reference on
24d08e2045SMatt Bobrowski  *
25d08e2045SMatt Bobrowski  * Get a reference on the exe_file struct file member field of the mm_struct
26d08e2045SMatt Bobrowski  * nested within the supplied *task*. The referenced file pointer acquired by
27d08e2045SMatt Bobrowski  * this BPF kfunc must be released using bpf_put_file(). Failing to call
28d08e2045SMatt Bobrowski  * bpf_put_file() on the returned referenced struct file pointer that has been
29d08e2045SMatt Bobrowski  * acquired by this BPF kfunc will result in the BPF program being rejected by
30d08e2045SMatt Bobrowski  * the BPF verifier.
31d08e2045SMatt Bobrowski  *
32d08e2045SMatt Bobrowski  * This BPF kfunc may only be called from BPF LSM programs.
33d08e2045SMatt Bobrowski  *
34d08e2045SMatt Bobrowski  * Internally, this BPF kfunc leans on get_task_exe_file(), such that calling
35d08e2045SMatt Bobrowski  * bpf_get_task_exe_file() would be analogous to calling get_task_exe_file()
36d08e2045SMatt Bobrowski  * directly in kernel context.
37d08e2045SMatt Bobrowski  *
38d08e2045SMatt Bobrowski  * Return: A referenced struct file pointer to the exe_file member of the
39d08e2045SMatt Bobrowski  * mm_struct that is nested within the supplied *task*. On error, NULL is
40d08e2045SMatt Bobrowski  * returned.
41d08e2045SMatt Bobrowski  */
bpf_get_task_exe_file(struct task_struct * task)42d08e2045SMatt Bobrowski __bpf_kfunc struct file *bpf_get_task_exe_file(struct task_struct *task)
43d08e2045SMatt Bobrowski {
44d08e2045SMatt Bobrowski 	return get_task_exe_file(task);
45d08e2045SMatt Bobrowski }
46d08e2045SMatt Bobrowski 
47d08e2045SMatt Bobrowski /**
48d08e2045SMatt Bobrowski  * bpf_put_file - put a reference on the supplied file
49d08e2045SMatt Bobrowski  * @file: file to put a reference on
50d08e2045SMatt Bobrowski  *
51d08e2045SMatt Bobrowski  * Put a reference on the supplied *file*. Only referenced file pointers may be
52d08e2045SMatt Bobrowski  * passed to this BPF kfunc. Attempting to pass an unreferenced file pointer, or
53d08e2045SMatt Bobrowski  * any other arbitrary pointer for that matter, will result in the BPF program
54d08e2045SMatt Bobrowski  * being rejected by the BPF verifier.
55d08e2045SMatt Bobrowski  *
56d08e2045SMatt Bobrowski  * This BPF kfunc may only be called from BPF LSM programs.
57d08e2045SMatt Bobrowski  */
bpf_put_file(struct file * file)58d08e2045SMatt Bobrowski __bpf_kfunc void bpf_put_file(struct file *file)
59d08e2045SMatt Bobrowski {
60d08e2045SMatt Bobrowski 	fput(file);
61d08e2045SMatt Bobrowski }
62d08e2045SMatt Bobrowski 
63d08e2045SMatt Bobrowski /**
64d08e2045SMatt Bobrowski  * bpf_path_d_path - resolve the pathname for the supplied path
65d08e2045SMatt Bobrowski  * @path: path to resolve the pathname for
66d08e2045SMatt Bobrowski  * @buf: buffer to return the resolved pathname in
67d08e2045SMatt Bobrowski  * @buf__sz: length of the supplied buffer
68d08e2045SMatt Bobrowski  *
69d08e2045SMatt Bobrowski  * Resolve the pathname for the supplied *path* and store it in *buf*. This BPF
70d08e2045SMatt Bobrowski  * kfunc is the safer variant of the legacy bpf_d_path() helper and should be
711a5c01d2SPuranjay Mohan  * used in place of bpf_d_path() whenever possible.
72d08e2045SMatt Bobrowski  *
73d08e2045SMatt Bobrowski  * This BPF kfunc may only be called from BPF LSM programs.
74d08e2045SMatt Bobrowski  *
75d08e2045SMatt Bobrowski  * Return: A positive integer corresponding to the length of the resolved
76d08e2045SMatt Bobrowski  * pathname in *buf*, including the NUL termination character. On error, a
77d08e2045SMatt Bobrowski  * negative integer is returned.
78d08e2045SMatt Bobrowski  */
bpf_path_d_path(const struct path * path,char * buf,size_t buf__sz)791b8abbb1SAl Viro __bpf_kfunc int bpf_path_d_path(const struct path *path, char *buf, size_t buf__sz)
80d08e2045SMatt Bobrowski {
81d08e2045SMatt Bobrowski 	int len;
82d08e2045SMatt Bobrowski 	char *ret;
83d08e2045SMatt Bobrowski 
84d08e2045SMatt Bobrowski 	if (!buf__sz)
85d08e2045SMatt Bobrowski 		return -EINVAL;
86d08e2045SMatt Bobrowski 
87d08e2045SMatt Bobrowski 	ret = d_path(path, buf, buf__sz);
88d08e2045SMatt Bobrowski 	if (IS_ERR(ret))
89d08e2045SMatt Bobrowski 		return PTR_ERR(ret);
90d08e2045SMatt Bobrowski 
91d08e2045SMatt Bobrowski 	len = buf + buf__sz - ret;
92d08e2045SMatt Bobrowski 	memmove(buf, ret, len);
93d08e2045SMatt Bobrowski 	return len;
94d08e2045SMatt Bobrowski }
95d08e2045SMatt Bobrowski 
match_security_bpf_prefix(const char * name__str)96531118f1SSong Liu static bool match_security_bpf_prefix(const char *name__str)
97531118f1SSong Liu {
98531118f1SSong Liu 	return !strncmp(name__str, XATTR_NAME_BPF_LSM, XATTR_NAME_BPF_LSM_LEN);
99531118f1SSong Liu }
100531118f1SSong Liu 
bpf_xattr_read_permission(const char * name,struct inode * inode)101531118f1SSong Liu static int bpf_xattr_read_permission(const char *name, struct inode *inode)
102531118f1SSong Liu {
103531118f1SSong Liu 	if (WARN_ON(!inode))
104531118f1SSong Liu 		return -EINVAL;
105531118f1SSong Liu 
106531118f1SSong Liu 	/* Allow reading xattr with user. and security.bpf. prefix */
107531118f1SSong Liu 	if (strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) &&
108531118f1SSong Liu 	    !match_security_bpf_prefix(name))
109531118f1SSong Liu 		return -EPERM;
110531118f1SSong Liu 
111531118f1SSong Liu 	return inode_permission(&nop_mnt_idmap, inode, MAY_READ);
112531118f1SSong Liu }
113531118f1SSong Liu 
114fa4e5afaSSong Liu /**
115ac13a426SSong Liu  * bpf_get_dentry_xattr - get xattr of a dentry
116ac13a426SSong Liu  * @dentry: dentry to get xattr from
117ac13a426SSong Liu  * @name__str: name of the xattr
118ac13a426SSong Liu  * @value_p: output buffer of the xattr value
119ac13a426SSong Liu  *
120ac13a426SSong Liu  * Get xattr *name__str* of *dentry* and store the output in *value_ptr*.
121ac13a426SSong Liu  *
122531118f1SSong Liu  * For security reasons, only *name__str* with prefixes "user." or
123531118f1SSong Liu  * "security.bpf." are allowed.
124ac13a426SSong Liu  *
125531118f1SSong Liu  * Return: length of the xattr value on success, a negative value on error.
126ac13a426SSong Liu  */
bpf_get_dentry_xattr(struct dentry * dentry,const char * name__str,struct bpf_dynptr * value_p)127ac13a426SSong Liu __bpf_kfunc int bpf_get_dentry_xattr(struct dentry *dentry, const char *name__str,
128ac13a426SSong Liu 				     struct bpf_dynptr *value_p)
129ac13a426SSong Liu {
130ac13a426SSong Liu 	struct bpf_dynptr_kern *value_ptr = (struct bpf_dynptr_kern *)value_p;
131ac13a426SSong Liu 	struct inode *inode = d_inode(dentry);
132ac13a426SSong Liu 	u32 value_len;
133ac13a426SSong Liu 	void *value;
134ac13a426SSong Liu 	int ret;
135ac13a426SSong Liu 
136ac13a426SSong Liu 	value_len = __bpf_dynptr_size(value_ptr);
137ac13a426SSong Liu 	value = __bpf_dynptr_data_rw(value_ptr, value_len);
138ac13a426SSong Liu 	if (!value)
139ac13a426SSong Liu 		return -EINVAL;
140ac13a426SSong Liu 
141531118f1SSong Liu 	ret = bpf_xattr_read_permission(name__str, inode);
142ac13a426SSong Liu 	if (ret)
143ac13a426SSong Liu 		return ret;
144ac13a426SSong Liu 	return __vfs_getxattr(dentry, inode, name__str, value, value_len);
145ac13a426SSong Liu }
146ac13a426SSong Liu 
147ac13a426SSong Liu /**
148fa4e5afaSSong Liu  * bpf_get_file_xattr - get xattr of a file
149fa4e5afaSSong Liu  * @file: file to get xattr from
150fa4e5afaSSong Liu  * @name__str: name of the xattr
151fa4e5afaSSong Liu  * @value_p: output buffer of the xattr value
152fa4e5afaSSong Liu  *
153fa4e5afaSSong Liu  * Get xattr *name__str* of *file* and store the output in *value_ptr*.
154fa4e5afaSSong Liu  *
155531118f1SSong Liu  * For security reasons, only *name__str* with prefixes "user." or
156531118f1SSong Liu  * "security.bpf." are allowed.
157fa4e5afaSSong Liu  *
158531118f1SSong Liu  * Return: length of the xattr value on success, a negative value on error.
159fa4e5afaSSong Liu  */
bpf_get_file_xattr(struct file * file,const char * name__str,struct bpf_dynptr * value_p)160fa4e5afaSSong Liu __bpf_kfunc int bpf_get_file_xattr(struct file *file, const char *name__str,
161fa4e5afaSSong Liu 				   struct bpf_dynptr *value_p)
162fa4e5afaSSong Liu {
163fa4e5afaSSong Liu 	struct dentry *dentry;
164fa4e5afaSSong Liu 
165fa4e5afaSSong Liu 	dentry = file_dentry(file);
166ac13a426SSong Liu 	return bpf_get_dentry_xattr(dentry, name__str, value_p);
167fa4e5afaSSong Liu }
168fa4e5afaSSong Liu 
169d08e2045SMatt Bobrowski __bpf_kfunc_end_defs();
170d08e2045SMatt Bobrowski 
bpf_xattr_write_permission(const char * name,struct inode * inode)17156467292SSong Liu static int bpf_xattr_write_permission(const char *name, struct inode *inode)
17256467292SSong Liu {
17356467292SSong Liu 	if (WARN_ON(!inode))
17456467292SSong Liu 		return -EINVAL;
17556467292SSong Liu 
17656467292SSong Liu 	/* Only allow setting and removing security.bpf. xattrs */
17756467292SSong Liu 	if (!match_security_bpf_prefix(name))
17856467292SSong Liu 		return -EPERM;
17956467292SSong Liu 
18056467292SSong Liu 	return inode_permission(&nop_mnt_idmap, inode, MAY_WRITE);
18156467292SSong Liu }
18256467292SSong Liu 
18356467292SSong Liu /**
18456467292SSong Liu  * bpf_set_dentry_xattr_locked - set a xattr of a dentry
18556467292SSong Liu  * @dentry: dentry to get xattr from
18656467292SSong Liu  * @name__str: name of the xattr
18756467292SSong Liu  * @value_p: xattr value
18856467292SSong Liu  * @flags: flags to pass into filesystem operations
18956467292SSong Liu  *
19056467292SSong Liu  * Set xattr *name__str* of *dentry* to the value in *value_ptr*.
19156467292SSong Liu  *
19256467292SSong Liu  * For security reasons, only *name__str* with prefix "security.bpf."
19356467292SSong Liu  * is allowed.
19456467292SSong Liu  *
19556467292SSong Liu  * The caller already locked dentry->d_inode.
19656467292SSong Liu  *
19756467292SSong Liu  * Return: 0 on success, a negative value on error.
19856467292SSong Liu  */
bpf_set_dentry_xattr_locked(struct dentry * dentry,const char * name__str,const struct bpf_dynptr * value_p,int flags)19956467292SSong Liu int bpf_set_dentry_xattr_locked(struct dentry *dentry, const char *name__str,
20056467292SSong Liu 				const struct bpf_dynptr *value_p, int flags)
20156467292SSong Liu {
20256467292SSong Liu 
20356467292SSong Liu 	struct bpf_dynptr_kern *value_ptr = (struct bpf_dynptr_kern *)value_p;
20456467292SSong Liu 	struct inode *inode = d_inode(dentry);
20556467292SSong Liu 	const void *value;
20656467292SSong Liu 	u32 value_len;
20756467292SSong Liu 	int ret;
20856467292SSong Liu 
20956467292SSong Liu 	value_len = __bpf_dynptr_size(value_ptr);
21056467292SSong Liu 	value = __bpf_dynptr_data(value_ptr, value_len);
21156467292SSong Liu 	if (!value)
21256467292SSong Liu 		return -EINVAL;
21356467292SSong Liu 
21456467292SSong Liu 	ret = bpf_xattr_write_permission(name__str, inode);
21556467292SSong Liu 	if (ret)
21656467292SSong Liu 		return ret;
21756467292SSong Liu 
21856467292SSong Liu 	ret = __vfs_setxattr(&nop_mnt_idmap, dentry, inode, name__str,
21956467292SSong Liu 			     value, value_len, flags);
22056467292SSong Liu 	if (!ret) {
22156467292SSong Liu 		fsnotify_xattr(dentry);
22256467292SSong Liu 
22356467292SSong Liu 		/* This xattr is set by BPF LSM, so we do not call
22456467292SSong Liu 		 * security_inode_post_setxattr. Otherwise, we would
22556467292SSong Liu 		 * risk deadlocks by calling back to the same kfunc.
22656467292SSong Liu 		 *
22756467292SSong Liu 		 * This is the same as security_inode_setsecurity().
22856467292SSong Liu 		 */
22956467292SSong Liu 	}
23056467292SSong Liu 	return ret;
23156467292SSong Liu }
23256467292SSong Liu 
23356467292SSong Liu /**
23456467292SSong Liu  * bpf_remove_dentry_xattr_locked - remove a xattr of a dentry
23556467292SSong Liu  * @dentry: dentry to get xattr from
23656467292SSong Liu  * @name__str: name of the xattr
23756467292SSong Liu  *
23856467292SSong Liu  * Rmove xattr *name__str* of *dentry*.
23956467292SSong Liu  *
24056467292SSong Liu  * For security reasons, only *name__str* with prefix "security.bpf."
24156467292SSong Liu  * is allowed.
24256467292SSong Liu  *
24356467292SSong Liu  * The caller already locked dentry->d_inode.
24456467292SSong Liu  *
24556467292SSong Liu  * Return: 0 on success, a negative value on error.
24656467292SSong Liu  */
bpf_remove_dentry_xattr_locked(struct dentry * dentry,const char * name__str)24756467292SSong Liu int bpf_remove_dentry_xattr_locked(struct dentry *dentry, const char *name__str)
24856467292SSong Liu {
24956467292SSong Liu 	struct inode *inode = d_inode(dentry);
25056467292SSong Liu 	int ret;
25156467292SSong Liu 
25256467292SSong Liu 	ret = bpf_xattr_write_permission(name__str, inode);
25356467292SSong Liu 	if (ret)
25456467292SSong Liu 		return ret;
25556467292SSong Liu 
25656467292SSong Liu 	ret = __vfs_removexattr(&nop_mnt_idmap, dentry, name__str);
25756467292SSong Liu 	if (!ret) {
25856467292SSong Liu 		fsnotify_xattr(dentry);
25956467292SSong Liu 
26056467292SSong Liu 		/* This xattr is removed by BPF LSM, so we do not call
26156467292SSong Liu 		 * security_inode_post_removexattr. Otherwise, we would
26256467292SSong Liu 		 * risk deadlocks by calling back to the same kfunc.
26356467292SSong Liu 		 */
26456467292SSong Liu 	}
26556467292SSong Liu 	return ret;
26656467292SSong Liu }
26756467292SSong Liu 
26856467292SSong Liu __bpf_kfunc_start_defs();
26956467292SSong Liu 
27056467292SSong Liu /**
27156467292SSong Liu  * bpf_set_dentry_xattr - set a xattr of a dentry
27256467292SSong Liu  * @dentry: dentry to get xattr from
27356467292SSong Liu  * @name__str: name of the xattr
27456467292SSong Liu  * @value_p: xattr value
27556467292SSong Liu  * @flags: flags to pass into filesystem operations
27656467292SSong Liu  *
27756467292SSong Liu  * Set xattr *name__str* of *dentry* to the value in *value_ptr*.
27856467292SSong Liu  *
27956467292SSong Liu  * For security reasons, only *name__str* with prefix "security.bpf."
28056467292SSong Liu  * is allowed.
28156467292SSong Liu  *
28256467292SSong Liu  * The caller has not locked dentry->d_inode.
28356467292SSong Liu  *
28456467292SSong Liu  * Return: 0 on success, a negative value on error.
28556467292SSong Liu  */
bpf_set_dentry_xattr(struct dentry * dentry,const char * name__str,const struct bpf_dynptr * value_p,int flags)28656467292SSong Liu __bpf_kfunc int bpf_set_dentry_xattr(struct dentry *dentry, const char *name__str,
28756467292SSong Liu 				     const struct bpf_dynptr *value_p, int flags)
28856467292SSong Liu {
28956467292SSong Liu 	struct inode *inode = d_inode(dentry);
29056467292SSong Liu 	int ret;
29156467292SSong Liu 
29256467292SSong Liu 	inode_lock(inode);
29356467292SSong Liu 	ret = bpf_set_dentry_xattr_locked(dentry, name__str, value_p, flags);
29456467292SSong Liu 	inode_unlock(inode);
29556467292SSong Liu 	return ret;
29656467292SSong Liu }
29756467292SSong Liu 
29856467292SSong Liu /**
29956467292SSong Liu  * bpf_remove_dentry_xattr - remove a xattr of a dentry
30056467292SSong Liu  * @dentry: dentry to get xattr from
30156467292SSong Liu  * @name__str: name of the xattr
30256467292SSong Liu  *
30356467292SSong Liu  * Rmove xattr *name__str* of *dentry*.
30456467292SSong Liu  *
30556467292SSong Liu  * For security reasons, only *name__str* with prefix "security.bpf."
30656467292SSong Liu  * is allowed.
30756467292SSong Liu  *
30856467292SSong Liu  * The caller has not locked dentry->d_inode.
30956467292SSong Liu  *
31056467292SSong Liu  * Return: 0 on success, a negative value on error.
31156467292SSong Liu  */
bpf_remove_dentry_xattr(struct dentry * dentry,const char * name__str)31256467292SSong Liu __bpf_kfunc int bpf_remove_dentry_xattr(struct dentry *dentry, const char *name__str)
31356467292SSong Liu {
31456467292SSong Liu 	struct inode *inode = d_inode(dentry);
31556467292SSong Liu 	int ret;
31656467292SSong Liu 
31756467292SSong Liu 	inode_lock(inode);
31856467292SSong Liu 	ret = bpf_remove_dentry_xattr_locked(dentry, name__str);
31956467292SSong Liu 	inode_unlock(inode);
32056467292SSong Liu 	return ret;
32156467292SSong Liu }
32256467292SSong Liu 
323b95ee904SSong Liu #ifdef CONFIG_CGROUPS
324b95ee904SSong Liu /**
325b95ee904SSong Liu  * bpf_cgroup_read_xattr - read xattr of a cgroup's node in cgroupfs
326b95ee904SSong Liu  * @cgroup: cgroup to get xattr from
327b95ee904SSong Liu  * @name__str: name of the xattr
328b95ee904SSong Liu  * @value_p: output buffer of the xattr value
329b95ee904SSong Liu  *
330b95ee904SSong Liu  * Get xattr *name__str* of *cgroup* and store the output in *value_ptr*.
331b95ee904SSong Liu  *
332b95ee904SSong Liu  * For security reasons, only *name__str* with prefix "user." is allowed.
333b95ee904SSong Liu  *
334b95ee904SSong Liu  * Return: length of the xattr value on success, a negative value on error.
335b95ee904SSong Liu  */
bpf_cgroup_read_xattr(struct cgroup * cgroup,const char * name__str,struct bpf_dynptr * value_p)336b95ee904SSong Liu __bpf_kfunc int bpf_cgroup_read_xattr(struct cgroup *cgroup, const char *name__str,
337b95ee904SSong Liu 					struct bpf_dynptr *value_p)
338b95ee904SSong Liu {
339b95ee904SSong Liu 	struct bpf_dynptr_kern *value_ptr = (struct bpf_dynptr_kern *)value_p;
340b95ee904SSong Liu 	u32 value_len;
341b95ee904SSong Liu 	void *value;
342b95ee904SSong Liu 
343b95ee904SSong Liu 	/* Only allow reading "user.*" xattrs */
344b95ee904SSong Liu 	if (strncmp(name__str, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
345b95ee904SSong Liu 		return -EPERM;
346b95ee904SSong Liu 
347b95ee904SSong Liu 	value_len = __bpf_dynptr_size(value_ptr);
348b95ee904SSong Liu 	value = __bpf_dynptr_data_rw(value_ptr, value_len);
349b95ee904SSong Liu 	if (!value)
350b95ee904SSong Liu 		return -EINVAL;
351b95ee904SSong Liu 
352b95ee904SSong Liu 	return kernfs_xattr_get(cgroup->kn, name__str, value, value_len);
353b95ee904SSong Liu }
354b95ee904SSong Liu #endif /* CONFIG_CGROUPS */
355b95ee904SSong Liu 
35656467292SSong Liu __bpf_kfunc_end_defs();
35756467292SSong Liu 
358d08e2045SMatt Bobrowski BTF_KFUNCS_START(bpf_fs_kfunc_set_ids)
359*7646c7afSPuranjay Mohan BTF_ID_FLAGS(func, bpf_get_task_exe_file, KF_ACQUIRE | KF_RET_NULL)
BTF_ID_FLAGS(func,bpf_put_file,KF_RELEASE)360d08e2045SMatt Bobrowski BTF_ID_FLAGS(func, bpf_put_file, KF_RELEASE)
361*7646c7afSPuranjay Mohan BTF_ID_FLAGS(func, bpf_path_d_path)
362*7646c7afSPuranjay Mohan BTF_ID_FLAGS(func, bpf_get_dentry_xattr, KF_SLEEPABLE)
363*7646c7afSPuranjay Mohan BTF_ID_FLAGS(func, bpf_get_file_xattr, KF_SLEEPABLE)
364*7646c7afSPuranjay Mohan BTF_ID_FLAGS(func, bpf_set_dentry_xattr, KF_SLEEPABLE)
365*7646c7afSPuranjay Mohan BTF_ID_FLAGS(func, bpf_remove_dentry_xattr, KF_SLEEPABLE)
366d08e2045SMatt Bobrowski BTF_KFUNCS_END(bpf_fs_kfunc_set_ids)
367d08e2045SMatt Bobrowski 
368d08e2045SMatt Bobrowski static int bpf_fs_kfuncs_filter(const struct bpf_prog *prog, u32 kfunc_id)
369d08e2045SMatt Bobrowski {
370d08e2045SMatt Bobrowski 	if (!btf_id_set8_contains(&bpf_fs_kfunc_set_ids, kfunc_id) ||
371d08e2045SMatt Bobrowski 	    prog->type == BPF_PROG_TYPE_LSM)
372d08e2045SMatt Bobrowski 		return 0;
373d08e2045SMatt Bobrowski 	return -EACCES;
374d08e2045SMatt Bobrowski }
375d08e2045SMatt Bobrowski 
3761a5c01d2SPuranjay Mohan /* bpf_[set|remove]_dentry_xattr.* hooks have KF_SLEEPABLE, so they are only
3771a5c01d2SPuranjay Mohan  * available to sleepable hooks with dentry arguments.
37856467292SSong Liu  *
37956467292SSong Liu  * Setting and removing xattr requires exclusive lock on dentry->d_inode.
38056467292SSong Liu  * Some hooks already locked d_inode, while some hooks have not locked
38156467292SSong Liu  * d_inode. Therefore, we need different kfuncs for different hooks.
38256467292SSong Liu  * Specifically, hooks in the following list (d_inode_locked_hooks)
38356467292SSong Liu  * should call bpf_[set|remove]_dentry_xattr_locked; while other hooks
38456467292SSong Liu  * should call bpf_[set|remove]_dentry_xattr.
38556467292SSong Liu  */
38656467292SSong Liu BTF_SET_START(d_inode_locked_hooks)
BTF_ID(func,bpf_lsm_inode_post_removexattr)38756467292SSong Liu BTF_ID(func, bpf_lsm_inode_post_removexattr)
38856467292SSong Liu BTF_ID(func, bpf_lsm_inode_post_setattr)
38956467292SSong Liu BTF_ID(func, bpf_lsm_inode_post_setxattr)
39056467292SSong Liu BTF_ID(func, bpf_lsm_inode_removexattr)
39156467292SSong Liu BTF_ID(func, bpf_lsm_inode_rmdir)
39256467292SSong Liu BTF_ID(func, bpf_lsm_inode_setattr)
39356467292SSong Liu BTF_ID(func, bpf_lsm_inode_setxattr)
39456467292SSong Liu BTF_ID(func, bpf_lsm_inode_unlink)
39556467292SSong Liu #ifdef CONFIG_SECURITY_PATH
39656467292SSong Liu BTF_ID(func, bpf_lsm_path_unlink)
39756467292SSong Liu BTF_ID(func, bpf_lsm_path_rmdir)
39856467292SSong Liu #endif /* CONFIG_SECURITY_PATH */
39956467292SSong Liu BTF_SET_END(d_inode_locked_hooks)
40056467292SSong Liu 
40156467292SSong Liu bool bpf_lsm_has_d_inode_locked(const struct bpf_prog *prog)
40256467292SSong Liu {
40356467292SSong Liu 	return btf_id_set_contains(&d_inode_locked_hooks, prog->aux->attach_btf_id);
40456467292SSong Liu }
40556467292SSong Liu 
406d08e2045SMatt Bobrowski static const struct btf_kfunc_id_set bpf_fs_kfunc_set = {
407d08e2045SMatt Bobrowski 	.owner = THIS_MODULE,
408d08e2045SMatt Bobrowski 	.set = &bpf_fs_kfunc_set_ids,
409d08e2045SMatt Bobrowski 	.filter = bpf_fs_kfuncs_filter,
410d08e2045SMatt Bobrowski };
411d08e2045SMatt Bobrowski 
bpf_fs_kfuncs_init(void)412d08e2045SMatt Bobrowski static int __init bpf_fs_kfuncs_init(void)
413d08e2045SMatt Bobrowski {
414d08e2045SMatt Bobrowski 	return register_btf_kfunc_id_set(BPF_PROG_TYPE_LSM, &bpf_fs_kfunc_set);
415d08e2045SMatt Bobrowski }
416d08e2045SMatt Bobrowski 
417d08e2045SMatt Bobrowski late_initcall(bpf_fs_kfuncs_init);
418