diff options
-rw-r--r-- | include/linux/bpf.h | 3 | ||||
-rw-r--r-- | kernel/bpf/syscall.c | 4 | ||||
-rw-r--r-- | security/selinux/hooks.c | 49 |
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 |
289 | DECLARE_PER_CPU(int, bpf_prog_active); | 289 | DECLARE_PER_CPU(int, bpf_prog_active); |
290 | 290 | ||
291 | extern const struct file_operations bpf_map_fops; | ||
292 | extern 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 | ||
318 | static const struct file_operations bpf_map_fops = { | 318 | const 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 | ||
978 | static const struct file_operations bpf_prog_fops = { | 978 | const 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 | ||
1819 | static 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 | */ | ||
6315 | static 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 | |||
6291 | static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode) | 6340 | static int selinux_bpf_map(struct bpf_map *map, fmode_t fmode) |
6292 | { | 6341 | { |
6293 | u32 sid = current_sid(); | 6342 | u32 sid = current_sid(); |