summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/bpf.h3
-rw-r--r--kernel/bpf/syscall.c4
-rw-r--r--security/selinux/hooks.c49
3 files changed, 54 insertions, 2 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 84c192da3e0b..1e334b248ff6 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -288,6 +288,9 @@ int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *progs,
288#ifdef CONFIG_BPF_SYSCALL 288#ifdef CONFIG_BPF_SYSCALL
289DECLARE_PER_CPU(int, bpf_prog_active); 289DECLARE_PER_CPU(int, bpf_prog_active);
290 290
291extern const struct file_operations bpf_map_fops;
292extern const struct file_operations bpf_prog_fops;
293
291#define BPF_PROG_TYPE(_id, _name) \ 294#define BPF_PROG_TYPE(_id, _name) \
292 extern const struct bpf_prog_ops _name ## _prog_ops; \ 295 extern const struct bpf_prog_ops _name ## _prog_ops; \
293 extern const struct bpf_verifier_ops _name ## _verifier_ops; 296 extern const struct bpf_verifier_ops _name ## _verifier_ops;
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 5cb56d06b48d..323be2473c4b 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -315,7 +315,7 @@ static ssize_t bpf_dummy_write(struct file *filp, const char __user *buf,
315 return -EINVAL; 315 return -EINVAL;
316} 316}
317 317
318static const struct file_operations bpf_map_fops = { 318const struct file_operations bpf_map_fops = {
319#ifdef CONFIG_PROC_FS 319#ifdef CONFIG_PROC_FS
320 .show_fdinfo = bpf_map_show_fdinfo, 320 .show_fdinfo = bpf_map_show_fdinfo,
321#endif 321#endif
@@ -975,7 +975,7 @@ static void bpf_prog_show_fdinfo(struct seq_file *m, struct file *filp)
975} 975}
976#endif 976#endif
977 977
978static const struct file_operations bpf_prog_fops = { 978const struct file_operations bpf_prog_fops = {
979#ifdef CONFIG_PROC_FS 979#ifdef CONFIG_PROC_FS
980 .show_fdinfo = bpf_prog_show_fdinfo, 980 .show_fdinfo = bpf_prog_show_fdinfo,
981#endif 981#endif
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 12cf7de8cbed..2e3a627fc0b1 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1815,6 +1815,10 @@ static inline int file_path_has_perm(const struct cred *cred,
1815 return inode_has_perm(cred, file_inode(file), av, &ad); 1815 return inode_has_perm(cred, file_inode(file), av, &ad);
1816} 1816}
1817 1817
1818#ifdef CONFIG_BPF_SYSCALL
1819static int bpf_fd_pass(struct file *file, u32 sid);
1820#endif
1821
1818/* Check whether a task can use an open file descriptor to 1822/* Check whether a task can use an open file descriptor to
1819 access an inode in a given way. Check access to the 1823 access an inode in a given way. Check access to the
1820 descriptor itself, and then use dentry_has_perm to 1824 descriptor itself, and then use dentry_has_perm to
@@ -1845,6 +1849,12 @@ static int file_has_perm(const struct cred *cred,
1845 goto out; 1849 goto out;
1846 } 1850 }
1847 1851
1852#ifdef CONFIG_BPF_SYSCALL
1853 rc = bpf_fd_pass(file, cred_sid(cred));
1854 if (rc)
1855 return rc;
1856#endif
1857
1848 /* av is zero if only checking access to the descriptor. */ 1858 /* av is zero if only checking access to the descriptor. */
1849 rc = 0; 1859 rc = 0;
1850 if (av) 1860 if (av)
@@ -2165,6 +2175,12 @@ static int selinux_binder_transfer_file(struct task_struct *from,
2165 return rc; 2175 return rc;
2166 } 2176 }
2167 2177
2178#ifdef CONFIG_BPF_SYSCALL
2179 rc = bpf_fd_pass(file, sid);
2180 if (rc)
2181 return rc;
2182#endif
2183
2168 if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) 2184 if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
2169 return 0; 2185 return 0;
2170 2186
@@ -6288,6 +6304,39 @@ static u32 bpf_map_fmode_to_av(fmode_t fmode)
6288 return av; 6304 return av;
6289} 6305}
6290 6306
6307/* This function will check the file pass through unix socket or binder to see
6308 * if it is a bpf related object. And apply correspinding checks on the bpf
6309 * object based on the type. The bpf maps and programs, not like other files and
6310 * socket, are using a shared anonymous inode inside the kernel as their inode.
6311 * So checking that inode cannot identify if the process have privilege to
6312 * access the bpf object and that's why we have to add this additional check in
6313 * selinux_file_receive and selinux_binder_transfer_files.
6314 */
6315static int bpf_fd_pass(struct file *file, u32 sid)
6316{
6317 struct bpf_security_struct *bpfsec;
6318 struct bpf_prog *prog;
6319 struct bpf_map *map;
6320 int ret;
6321
6322 if (file->f_op == &bpf_map_fops) {
6323 map = file->private_data;
6324 bpfsec = map->security;
6325 ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
6326 bpf_map_fmode_to_av(file->f_mode), NULL);
6327 if (ret)
6328 return ret;
6329 } else if (file->f_op == &bpf_prog_fops) {
6330 prog = file->private_data;
6331 bpfsec = prog->aux->security;
6332 ret = avc_has_perm(sid, bpfsec->sid, SECCLASS_BPF,
6333 BPF__PROG_RUN, NULL);
6334 if (ret)
6335 return ret;
6336 }
6337 return 0;
6338}
6339
6291static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode) 6340static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode)
6292{ 6341{
6293 u32 sid = current_sid(); 6342 u32 sid = current_sid();