diff options
| -rw-r--r-- | include/linux/bpf.h | 10 | ||||
| -rw-r--r-- | kernel/bpf/inode.c | 40 | ||||
| -rw-r--r-- | kernel/bpf/syscall.c | 2 | ||||
| -rw-r--r-- | net/netfilter/xt_bpf.c | 14 |
4 files changed, 52 insertions, 14 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h index e55e4255a210..b63a592ad29d 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h | |||
| @@ -419,6 +419,8 @@ static inline int bpf_map_attr_numa_node(const union bpf_attr *attr) | |||
| 419 | attr->numa_node : NUMA_NO_NODE; | 419 | attr->numa_node : NUMA_NO_NODE; |
| 420 | } | 420 | } |
| 421 | 421 | ||
| 422 | struct bpf_prog *bpf_prog_get_type_path(const char *name, enum bpf_prog_type type); | ||
| 423 | |||
| 422 | #else /* !CONFIG_BPF_SYSCALL */ | 424 | #else /* !CONFIG_BPF_SYSCALL */ |
| 423 | static inline struct bpf_prog *bpf_prog_get(u32 ufd) | 425 | static inline struct bpf_prog *bpf_prog_get(u32 ufd) |
| 424 | { | 426 | { |
| @@ -506,6 +508,12 @@ static inline int cpu_map_enqueue(struct bpf_cpu_map_entry *rcpu, | |||
| 506 | { | 508 | { |
| 507 | return 0; | 509 | return 0; |
| 508 | } | 510 | } |
| 511 | |||
| 512 | static inline struct bpf_prog *bpf_prog_get_type_path(const char *name, | ||
| 513 | enum bpf_prog_type type) | ||
| 514 | { | ||
| 515 | return ERR_PTR(-EOPNOTSUPP); | ||
| 516 | } | ||
| 509 | #endif /* CONFIG_BPF_SYSCALL */ | 517 | #endif /* CONFIG_BPF_SYSCALL */ |
| 510 | 518 | ||
| 511 | static inline struct bpf_prog *bpf_prog_get_type(u32 ufd, | 519 | static inline struct bpf_prog *bpf_prog_get_type(u32 ufd, |
| @@ -514,6 +522,8 @@ static inline struct bpf_prog *bpf_prog_get_type(u32 ufd, | |||
| 514 | return bpf_prog_get_type_dev(ufd, type, false); | 522 | return bpf_prog_get_type_dev(ufd, type, false); |
| 515 | } | 523 | } |
| 516 | 524 | ||
| 525 | bool bpf_prog_get_ok(struct bpf_prog *, enum bpf_prog_type *, bool); | ||
| 526 | |||
| 517 | int bpf_prog_offload_compile(struct bpf_prog *prog); | 527 | int bpf_prog_offload_compile(struct bpf_prog *prog); |
| 518 | void bpf_prog_offload_destroy(struct bpf_prog *prog); | 528 | void bpf_prog_offload_destroy(struct bpf_prog *prog); |
| 519 | 529 | ||
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c index 01aaef1a77c5..5bb5e49ef4c3 100644 --- a/kernel/bpf/inode.c +++ b/kernel/bpf/inode.c | |||
| @@ -368,7 +368,45 @@ out: | |||
| 368 | putname(pname); | 368 | putname(pname); |
| 369 | return ret; | 369 | return ret; |
| 370 | } | 370 | } |
| 371 | EXPORT_SYMBOL_GPL(bpf_obj_get_user); | 371 | |
| 372 | static struct bpf_prog *__get_prog_inode(struct inode *inode, enum bpf_prog_type type) | ||
| 373 | { | ||
| 374 | struct bpf_prog *prog; | ||
| 375 | int ret = inode_permission(inode, MAY_READ | MAY_WRITE); | ||
| 376 | if (ret) | ||
| 377 | return ERR_PTR(ret); | ||
| 378 | |||
| 379 | if (inode->i_op == &bpf_map_iops) | ||
| 380 | return ERR_PTR(-EINVAL); | ||
| 381 | if (inode->i_op != &bpf_prog_iops) | ||
| 382 | return ERR_PTR(-EACCES); | ||
| 383 | |||
| 384 | prog = inode->i_private; | ||
| 385 | |||
| 386 | ret = security_bpf_prog(prog); | ||
| 387 | if (ret < 0) | ||
| 388 | return ERR_PTR(ret); | ||
| 389 | |||
| 390 | if (!bpf_prog_get_ok(prog, &type, false)) | ||
| 391 | return ERR_PTR(-EINVAL); | ||
| 392 | |||
| 393 | return bpf_prog_inc(prog); | ||
| 394 | } | ||
| 395 | |||
| 396 | struct bpf_prog *bpf_prog_get_type_path(const char *name, enum bpf_prog_type type) | ||
| 397 | { | ||
| 398 | struct bpf_prog *prog; | ||
| 399 | struct path path; | ||
| 400 | int ret = kern_path(name, LOOKUP_FOLLOW, &path); | ||
| 401 | if (ret) | ||
| 402 | return ERR_PTR(ret); | ||
| 403 | prog = __get_prog_inode(d_backing_inode(path.dentry), type); | ||
| 404 | if (!IS_ERR(prog)) | ||
| 405 | touch_atime(&path); | ||
| 406 | path_put(&path); | ||
| 407 | return prog; | ||
| 408 | } | ||
| 409 | EXPORT_SYMBOL(bpf_prog_get_type_path); | ||
| 372 | 410 | ||
| 373 | static void bpf_evict_inode(struct inode *inode) | 411 | static void bpf_evict_inode(struct inode *inode) |
| 374 | { | 412 | { |
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 2c4cfeaa8d5e..5cb783fc8224 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c | |||
| @@ -1057,7 +1057,7 @@ struct bpf_prog *bpf_prog_inc_not_zero(struct bpf_prog *prog) | |||
| 1057 | } | 1057 | } |
| 1058 | EXPORT_SYMBOL_GPL(bpf_prog_inc_not_zero); | 1058 | EXPORT_SYMBOL_GPL(bpf_prog_inc_not_zero); |
| 1059 | 1059 | ||
| 1060 | static bool bpf_prog_get_ok(struct bpf_prog *prog, | 1060 | bool bpf_prog_get_ok(struct bpf_prog *prog, |
| 1061 | enum bpf_prog_type *attach_type, bool attach_drv) | 1061 | enum bpf_prog_type *attach_type, bool attach_drv) |
| 1062 | { | 1062 | { |
| 1063 | /* not an attachment, just a refcount inc, always allow */ | 1063 | /* not an attachment, just a refcount inc, always allow */ |
diff --git a/net/netfilter/xt_bpf.c b/net/netfilter/xt_bpf.c index 041da0d9c06f..fa2ca0a13619 100644 --- a/net/netfilter/xt_bpf.c +++ b/net/netfilter/xt_bpf.c | |||
| @@ -52,18 +52,8 @@ static int __bpf_mt_check_fd(int fd, struct bpf_prog **ret) | |||
| 52 | 52 | ||
| 53 | static int __bpf_mt_check_path(const char *path, struct bpf_prog **ret) | 53 | static int __bpf_mt_check_path(const char *path, struct bpf_prog **ret) |
| 54 | { | 54 | { |
| 55 | mm_segment_t oldfs = get_fs(); | 55 | *ret = bpf_prog_get_type_path(path, BPF_PROG_TYPE_SOCKET_FILTER); |
| 56 | int retval, fd; | 56 | return PTR_ERR_OR_ZERO(*ret); |
| 57 | |||
| 58 | set_fs(KERNEL_DS); | ||
| 59 | fd = bpf_obj_get_user(path, 0); | ||
| 60 | set_fs(oldfs); | ||
| 61 | if (fd < 0) | ||
| 62 | return fd; | ||
| 63 | |||
| 64 | retval = __bpf_mt_check_fd(fd, ret); | ||
| 65 | sys_close(fd); | ||
| 66 | return retval; | ||
| 67 | } | 57 | } |
| 68 | 58 | ||
| 69 | static int bpf_mt_check(const struct xt_mtchk_param *par) | 59 | static int bpf_mt_check(const struct xt_mtchk_param *par) |
