From 435d5f4bb2ccba3b791d9ef61d2590e30b8e806e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 31 Oct 2014 22:56:04 -0400 Subject: common object embedded into various struct ....ns for now - just move corresponding ->proc_inum instances over there Acked-by: "Eric W. Biederman" Signed-off-by: Al Viro --- net/core/net_namespace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 7f15517..f2f756c 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -386,12 +386,12 @@ EXPORT_SYMBOL_GPL(get_net_ns_by_pid); static __net_init int net_ns_net_init(struct net *net) { - return proc_alloc_inum(&net->proc_inum); + return proc_alloc_inum(&net->ns.inum); } static __net_exit void net_ns_net_exit(struct net *net) { - proc_free_inum(net->proc_inum); + proc_free_inum(net->ns.inum); } static struct pernet_operations __net_initdata net_ns_ops = { @@ -664,7 +664,7 @@ static int netns_install(struct nsproxy *nsproxy, void *ns) static unsigned int netns_inum(void *ns) { struct net *net = ns; - return net->proc_inum; + return net->ns.inum; } const struct proc_ns_operations netns_operations = { -- cgit v1.1 From ff24870f46d51d79fc74a241fd7c12ccb933c69f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 1 Nov 2014 00:10:50 -0400 Subject: netns: switch ->get()/->put()/->install()/->inum() to working with &net->ns Signed-off-by: Al Viro --- net/core/net_namespace.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index f2f756c..97f4dc2 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -347,7 +347,7 @@ struct net *get_net_ns_by_fd(int fd) ei = get_proc_ns(file_inode(file)); if (ei->ns_ops == &netns_operations) - net = get_net(ei->ns); + net = get_net(container_of(ei->ns, struct net, ns)); else net = ERR_PTR(-EINVAL); @@ -640,17 +640,22 @@ static void *netns_get(struct task_struct *task) net = get_net(nsproxy->net_ns); task_unlock(task); - return net; + return net ? &net->ns : NULL; +} + +static inline struct net *to_net_ns(struct ns_common *ns) +{ + return container_of(ns, struct net, ns); } static void netns_put(void *ns) { - put_net(ns); + put_net(to_net_ns(ns)); } static int netns_install(struct nsproxy *nsproxy, void *ns) { - struct net *net = ns; + struct net *net = to_net_ns(ns); if (!ns_capable(net->user_ns, CAP_SYS_ADMIN) || !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) @@ -663,8 +668,7 @@ static int netns_install(struct nsproxy *nsproxy, void *ns) static unsigned int netns_inum(void *ns) { - struct net *net = ns; - return net->ns.inum; + return ((struct ns_common *)ns)->inum; } const struct proc_ns_operations netns_operations = { -- cgit v1.1 From 64964528b24ea390824f0e5ce9d34b8d39b28cde Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 1 Nov 2014 00:37:32 -0400 Subject: make proc_ns_operations work with struct ns_common * instead of void * We can do that now. And kill ->inum(), while we are at it - all instances are identical. Signed-off-by: Al Viro --- net/core/net_namespace.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 97f4dc2..2161f09 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -629,7 +629,7 @@ void unregister_pernet_device(struct pernet_operations *ops) EXPORT_SYMBOL_GPL(unregister_pernet_device); #ifdef CONFIG_NET_NS -static void *netns_get(struct task_struct *task) +static struct ns_common *netns_get(struct task_struct *task) { struct net *net = NULL; struct nsproxy *nsproxy; @@ -648,12 +648,12 @@ static inline struct net *to_net_ns(struct ns_common *ns) return container_of(ns, struct net, ns); } -static void netns_put(void *ns) +static void netns_put(struct ns_common *ns) { put_net(to_net_ns(ns)); } -static int netns_install(struct nsproxy *nsproxy, void *ns) +static int netns_install(struct nsproxy *nsproxy, struct ns_common *ns) { struct net *net = to_net_ns(ns); @@ -666,17 +666,11 @@ static int netns_install(struct nsproxy *nsproxy, void *ns) return 0; } -static unsigned int netns_inum(void *ns) -{ - return ((struct ns_common *)ns)->inum; -} - const struct proc_ns_operations netns_operations = { .name = "net", .type = CLONE_NEWNET, .get = netns_get, .put = netns_put, .install = netns_install, - .inum = netns_inum, }; #endif -- cgit v1.1 From 6344c433a452b1a05d03a61a6a85d89f793bb7b8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 1 Nov 2014 00:45:45 -0400 Subject: new helpers: ns_alloc_inum/ns_free_inum take struct ns_common *, for now simply wrappers around proc_{alloc,free}_inum() Signed-off-by: Al Viro --- net/core/net_namespace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 2161f09..da775f5 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -386,12 +386,12 @@ EXPORT_SYMBOL_GPL(get_net_ns_by_pid); static __net_init int net_ns_net_init(struct net *net) { - return proc_alloc_inum(&net->ns.inum); + return ns_alloc_inum(&net->ns); } static __net_exit void net_ns_net_exit(struct net *net) { - proc_free_inum(net->ns.inum); + ns_free_inum(&net->ns); } static struct pernet_operations __net_initdata net_ns_ops = { -- cgit v1.1 From 33c429405a2c8d9e42afb9fee88a63cfb2de1e98 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 1 Nov 2014 02:32:53 -0400 Subject: copy address of proc_ns_ops into ns_common Signed-off-by: Al Viro --- net/core/net_namespace.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index da775f5..4d4acaf 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -339,6 +339,7 @@ struct net *get_net_ns_by_fd(int fd) { struct proc_ns *ei; struct file *file; + struct ns_common *ns; struct net *net; file = proc_ns_fget(fd); @@ -346,8 +347,9 @@ struct net *get_net_ns_by_fd(int fd) return ERR_CAST(file); ei = get_proc_ns(file_inode(file)); - if (ei->ns_ops == &netns_operations) - net = get_net(container_of(ei->ns, struct net, ns)); + ns = ei->ns; + if (ns->ops == &netns_operations) + net = get_net(container_of(ns, struct net, ns)); else net = ERR_PTR(-EINVAL); @@ -386,6 +388,9 @@ EXPORT_SYMBOL_GPL(get_net_ns_by_pid); static __net_init int net_ns_net_init(struct net *net) { +#ifdef CONFIG_NET_NS + net->ns.ops = &netns_operations; +#endif return ns_alloc_inum(&net->ns); } -- cgit v1.1 From f77c80142e1afe6d5c16975ca5d7d1fc324b16f9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 1 Nov 2014 03:13:17 -0400 Subject: bury struct proc_ns in fs/proc a) make get_proc_ns() return a pointer to struct ns_common b) mirror ns_ops in dentry->d_fsdata of ns dentries, so that is_mnt_ns_file() could get away with fewer dereferences. That way struct proc_ns becomes invisible outside of fs/proc/*.c Signed-off-by: Al Viro --- net/core/net_namespace.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'net') diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 4d4acaf..ce780c7 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -337,7 +337,6 @@ EXPORT_SYMBOL_GPL(__put_net); struct net *get_net_ns_by_fd(int fd) { - struct proc_ns *ei; struct file *file; struct ns_common *ns; struct net *net; @@ -346,8 +345,7 @@ struct net *get_net_ns_by_fd(int fd) if (IS_ERR(file)) return ERR_CAST(file); - ei = get_proc_ns(file_inode(file)); - ns = ei->ns; + ns = get_proc_ns(file_inode(file)); if (ns->ops == &netns_operations) net = get_net(container_of(ns, struct net, ns)); else -- cgit v1.1 From bd9b51e79cb0b8bc00a7e0076a4a8963ca4a797c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 18 Nov 2014 23:38:21 -0500 Subject: make default ->i_fop have ->open() fail with ENXIO As it is, default ->i_fop has NULL ->open() (along with all other methods). The only case where it matters is reopening (via procfs symlink) a file that didn't get its ->f_op from ->i_fop - anything else will have ->i_fop assigned to something sane (default would fail on read/write/ioctl/etc.). Unfortunately, such case exists - alloc_file() users, especially anon_get_file() ones. There we have tons of opened files of very different kinds sharing the same inode. As the result, attempt to reopen those via procfs succeeds and you get a descriptor you can't do anything with. Moreover, in case of sockets we set ->i_fop that will only be used on such reopen attempts - and put a failing ->open() into it to make sure those do not succeed. It would be simpler to put such ->open() into default ->i_fop and leave it unchanged both for anon inode (as we do anyway) and for socket ones. Result: * everything going through do_dentry_open() works as it used to * sock_no_open() kludge is gone * attempts to reopen anon-inode files fail as they really ought to * ditto for aio_private_file() * ditto for perfmon - this one actually tried to imitate sock_no_open() trick, but failed to set ->i_fop, so in the current tree reopens succeed and yield completely useless descriptor. Intent clearly had been to fail with -ENXIO on such reopens; now it actually does. * everything else that used alloc_file() keeps working - it has ->i_fop set for its inodes anyway Signed-off-by: Al Viro --- net/Makefile | 2 -- net/nonet.c | 26 -------------------------- net/socket.c | 19 ------------------- 3 files changed, 47 deletions(-) delete mode 100644 net/nonet.c (limited to 'net') diff --git a/net/Makefile b/net/Makefile index 7ed1970..1f6c3e4 100644 --- a/net/Makefile +++ b/net/Makefile @@ -5,8 +5,6 @@ # Rewritten to use lists instead of if-statements. # -obj-y := nonet.o - obj-$(CONFIG_NET) := socket.o core/ tmp-$(CONFIG_COMPAT) := compat.o diff --git a/net/nonet.c b/net/nonet.c deleted file mode 100644 index b1a73fd..0000000 --- a/net/nonet.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * net/nonet.c - * - * Dummy functions to allow us to configure network support entirely - * out of the kernel. - * - * Distributed under the terms of the GNU GPL version 2. - * Copyright (c) Matthew Wilcox 2003 - */ - -#include -#include -#include -#include -#include - -static int sock_no_open(struct inode *irrelevant, struct file *dontcare) -{ - return -ENXIO; -} - -const struct file_operations bad_sock_fops = { - .owner = THIS_MODULE, - .open = sock_no_open, - .llseek = noop_llseek, -}; diff --git a/net/socket.c b/net/socket.c index fe20c31..850f6c3 100644 --- a/net/socket.c +++ b/net/socket.c @@ -113,7 +113,6 @@ unsigned int sysctl_net_busy_read __read_mostly; unsigned int sysctl_net_busy_poll __read_mostly; #endif -static int sock_no_open(struct inode *irrelevant, struct file *dontcare); static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos); static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov, @@ -151,7 +150,6 @@ static const struct file_operations socket_file_ops = { .compat_ioctl = compat_sock_ioctl, #endif .mmap = sock_mmap, - .open = sock_no_open, /* special open code to disallow open via /proc */ .release = sock_close, .fasync = sock_fasync, .sendpage = sock_sendpage, @@ -559,23 +557,6 @@ static struct socket *sock_alloc(void) return sock; } -/* - * In theory you can't get an open on this inode, but /proc provides - * a back door. Remember to keep it shut otherwise you'll let the - * creepy crawlies in. - */ - -static int sock_no_open(struct inode *irrelevant, struct file *dontcare) -{ - return -ENXIO; -} - -const struct file_operations bad_sock_fops = { - .owner = THIS_MODULE, - .open = sock_no_open, - .llseek = noop_llseek, -}; - /** * sock_release - close a socket * @sock: socket to close -- cgit v1.1