diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-06 20:13:21 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-06 20:13:21 -0500 |
commit | 75d4276e83a353d5e41da676f418d4a12f6f6e6c (patch) | |
tree | d3d9a43afa64f5d358b99b987b7ad8c0e2847dac | |
parent | 5b6c02f38315b720c593c6079364855d276886aa (diff) | |
parent | 040ee69226f8a96b7943645d68f41d5d44b5ff7d (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs fixes from Al Viro:
- untangle sys_close() abuses in xt_bpf
- deal with register_shrinker() failures in sget()
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
fix "netfilter: xt_bpf: Fix XT_BPF_MODE_FD_PINNED mode of 'xt_bpf_info_v1'"
sget(): handle failures of register_shrinker()
mm,vmscan: Make unregister_shrinker() no-op if register_shrinker() failed.
-rw-r--r-- | fs/super.c | 6 | ||||
-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-- | mm/vmscan.c | 3 | ||||
-rw-r--r-- | net/netfilter/xt_bpf.c | 14 |
6 files changed, 60 insertions, 15 deletions
diff --git a/fs/super.c b/fs/super.c index 7ff1349609e4..06bd25d90ba5 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -517,7 +517,11 @@ retry: | |||
517 | hlist_add_head(&s->s_instances, &type->fs_supers); | 517 | hlist_add_head(&s->s_instances, &type->fs_supers); |
518 | spin_unlock(&sb_lock); | 518 | spin_unlock(&sb_lock); |
519 | get_filesystem(type); | 519 | get_filesystem(type); |
520 | register_shrinker(&s->s_shrink); | 520 | err = register_shrinker(&s->s_shrink); |
521 | if (err) { | ||
522 | deactivate_locked_super(s); | ||
523 | s = ERR_PTR(err); | ||
524 | } | ||
521 | return s; | 525 | return s; |
522 | } | 526 | } |
523 | 527 | ||
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/mm/vmscan.c b/mm/vmscan.c index c02c850ea349..47d5ced51f2d 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -297,10 +297,13 @@ EXPORT_SYMBOL(register_shrinker); | |||
297 | */ | 297 | */ |
298 | void unregister_shrinker(struct shrinker *shrinker) | 298 | void unregister_shrinker(struct shrinker *shrinker) |
299 | { | 299 | { |
300 | if (!shrinker->nr_deferred) | ||
301 | return; | ||
300 | down_write(&shrinker_rwsem); | 302 | down_write(&shrinker_rwsem); |
301 | list_del(&shrinker->list); | 303 | list_del(&shrinker->list); |
302 | up_write(&shrinker_rwsem); | 304 | up_write(&shrinker_rwsem); |
303 | kfree(shrinker->nr_deferred); | 305 | kfree(shrinker->nr_deferred); |
306 | shrinker->nr_deferred = NULL; | ||
304 | } | 307 | } |
305 | EXPORT_SYMBOL(unregister_shrinker); | 308 | EXPORT_SYMBOL(unregister_shrinker); |
306 | 309 | ||
diff --git a/net/netfilter/xt_bpf.c b/net/netfilter/xt_bpf.c index 1f7fbd3c7e5a..06b090d8e901 100644 --- a/net/netfilter/xt_bpf.c +++ b/net/netfilter/xt_bpf.c | |||
@@ -55,21 +55,11 @@ static int __bpf_mt_check_fd(int fd, struct bpf_prog **ret) | |||
55 | 55 | ||
56 | static int __bpf_mt_check_path(const char *path, struct bpf_prog **ret) | 56 | static int __bpf_mt_check_path(const char *path, struct bpf_prog **ret) |
57 | { | 57 | { |
58 | mm_segment_t oldfs = get_fs(); | ||
59 | int retval, fd; | ||
60 | |||
61 | if (strnlen(path, XT_BPF_PATH_MAX) == XT_BPF_PATH_MAX) | 58 | if (strnlen(path, XT_BPF_PATH_MAX) == XT_BPF_PATH_MAX) |
62 | return -EINVAL; | 59 | return -EINVAL; |
63 | 60 | ||
64 | set_fs(KERNEL_DS); | 61 | *ret = bpf_prog_get_type_path(path, BPF_PROG_TYPE_SOCKET_FILTER); |
65 | fd = bpf_obj_get_user(path, 0); | 62 | return PTR_ERR_OR_ZERO(*ret); |
66 | set_fs(oldfs); | ||
67 | if (fd < 0) | ||
68 | return fd; | ||
69 | |||
70 | retval = __bpf_mt_check_fd(fd, ret); | ||
71 | sys_close(fd); | ||
72 | return retval; | ||
73 | } | 63 | } |
74 | 64 | ||
75 | static int bpf_mt_check(const struct xt_mtchk_param *par) | 65 | static int bpf_mt_check(const struct xt_mtchk_param *par) |