Make the network stack usable by userns root
Subsystems (19)
cover Make the network stack usable by userns root
In a secondary user namespace the root user only has CAP_NET_ADMIN, CAP_NET_RAW and CAP_NET_BIND_SERVICE with respect to the secondary user namespace. The test "capable(CAP_NET_ADMIN)" tests for capabilities in the initial user namespace.
The following set of patches goes through the networking stack. First pushing the capable(CAP_NET_ADMIN) admin calls down farther in the stack so individual instances can be changed. Then where I have I it appears safe I have relaxed the permission checks.
The code is available in git from:git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git netns-v73
The netns-v73 branch is against v3.7-rc3 and merges cleanly with net-next.
In my user namespace tree I am working to allow unprivileged users to create user namespace, and to allow the user namespace root able to create network namespaces. Making these patches really about allowing unprivileged users able to use the networking stack (not that they will be able to talk to anyone).
David I have some small dependencies on the first two patches of this series in my later user namespace work. So after these changes have been reviewed if you can pull my netns-v73 branch (which is just these patches) into net-next that will help me avoid unnecessary conflicts.
Eric
Eric W. Biederman (16):
netns: Deduplicate and fix copy_net_ns when !CONFIG_NET_NS
userns: make each net (net_ns) belong to a user_ns
sysctl: Pass useful parameters to sysctl permissions
net: Don't export sysctls to unprivileged users
net: Push capable(CAP_NET_ADMIN) into the rtnl methods
net: Update the per network namespace sysctls to be available to the network namespace owner
net: Allow userns root to force the scm creds
net: Allow userns root control of the core of the network stack.
net: Allow userns root to control ipv4
net: Allow userns root to control ipv6
net: Allow userns root to control llc, netfilter, netlink, packet, and xfrm
net: Allow userns root to control the network bridge code.
net: Allow the userns root to control vlans.
net: Enable some sysctls that are safe for the userns root
net: Enable a userns root rtnl calls that are safe for unprivilged users
net: Make CAP_NET_BIND_SERVICE per user namespace
Zhao Hongjiang (1):
user_ns: get rid of duplicate code in net_ctl_permissions
fs/proc/proc_sysctl.c | 9 +++++---- include/linux/sysctl.h | 3 +-- include/net/net_namespace.h | 24 ++++++++++++++++-------- kernel/nsproxy.c | 2 +- net/8021q/vlan.c | 12 ++++++------ net/bridge/br_ioctl.c | 25 +++++++++++++------------ net/bridge/br_sysfs_br.c | 10 +++++----- net/bridge/br_sysfs_if.c | 2 +- net/can/gw.c | 6 ++++++ net/core/dev.c | 17 +++++++++++++---- net/core/ethtool.c | 2 +- net/core/neighbour.c | 4 ++++ net/core/net-sysfs.c | 15 ++++++++++----- net/core/net_namespace.c | 23 ++++++++++++----------- net/core/rtnetlink.c | 12 +++++++++++- net/core/scm.c | 6 +++--- net/core/sock.c | 7 ++++--- net/core/sysctl_net_core.c | 5 +++++ net/dcb/dcbnl.c | 3 +++ net/decnet/dn_dev.c | 6 ++++++ net/decnet/dn_fib.c | 6 ++++++ net/ipv4/af_inet.c | 9 ++++++--- net/ipv4/arp.c | 2 +- net/ipv4/devinet.c | 4 ++-- net/ipv4/fib_frontend.c | 2 +- net/ipv4/ip_fragment.c | 4 ++++ net/ipv4/ip_gre.c | 4 ++-- net/ipv4/ip_options.c | 6 +++--- net/ipv4/ip_sockglue.c | 5 +++-- net/ipv4/ip_vti.c | 4 ++-- net/ipv4/ipip.c | 4 ++-- net/ipv4/ipmr.c | 2 +- net/ipv4/netfilter/arp_tables.c | 8 ++++---- net/ipv4/netfilter/ip_tables.c | 8 ++++---- net/ipv4/route.c | 4 ++++ net/ipv4/sysctl_net_ipv4.c | 3 +++ net/ipv4/tcp.c | 2 +- net/ipv4/tcp_cong.c | 3 ++- net/ipv6/addrconf.c | 4 ++-- net/ipv6/af_inet6.c | 5 +++-- net/ipv6/anycast.c | 2 +- net/ipv6/datagram.c | 6 +++--- net/ipv6/ip6_flowlabel.c | 3 ++- net/ipv6/ip6_gre.c | 4 ++-- net/ipv6/ip6_tunnel.c | 4 ++-- net/ipv6/ip6mr.c | 2 +- net/ipv6/ipv6_sockglue.c | 7 ++++--- net/ipv6/netfilter/ip6_tables.c | 8 ++++---- net/ipv6/reassembly.c | 4 ++++ net/ipv6/route.c | 6 +++++- net/ipv6/sit.c | 8 ++++---- net/key/af_key.c | 2 +- net/llc/af_llc.c | 2 +- net/netfilter/ipset/ip_set_core.c | 2 +- net/netfilter/ipvs/ip_vs_ctl.c | 8 ++++++-- net/netfilter/ipvs/ip_vs_lblc.c | 7 ++++++- net/netfilter/ipvs/ip_vs_lblcr.c | 4 ++++ net/netfilter/nf_conntrack_acct.c | 4 ++++ net/netfilter/nf_conntrack_ecache.c | 4 ++++ net/netfilter/nf_conntrack_helper.c | 4 ++++ net/netfilter/nf_conntrack_proto_dccp.c | 8 ++++++-- net/netfilter/nf_conntrack_standalone.c | 4 ++++ net/netfilter/nf_conntrack_timestamp.c | 4 ++++ net/netfilter/nfnetlink.c | 2 +- net/netlink/af_netlink.c | 2 +- net/packet/af_packet.c | 2 +- net/phonet/pn_netlink.c | 6 ++++++ net/sched/act_api.c | 3 +++ net/sched/cls_api.c | 2 ++ net/sched/sch_api.c | 9 +++++++++ net/sctp/socket.c | 8 +++++--- net/sysctl_net.c | 15 ++++++++++++--- net/unix/sysctl_net_unix.c | 4 ++++ net/xfrm/xfrm_sysctl.c | 4 ++++ net/xfrm/xfrm_user.c | 2 +- 75 files changed, 308 insertions(+), 140 deletions(-)
A message that is not in the archive (sent off-list or not yet received): 87d2zd8zwn.fsf-aS9lmoZGLiVWk0Htik3J/[email protected]
PATCH 1/17 netns: Deduplicate and fix copy_net_ns when !CONFIG_NET_NS
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
The copy of copy_net_ns used when the network stack is not built is broken as it does not return -EINVAL when attempting to create a new network namespace. We don't even have a previous network namespace.
Since we need a copy of copy_net_ns in net/net_namespace.h that is available when the networking stack is not built at all move the correct version of copy_net_ns from net_namespace.c into net_namespace.h Leaving us with just 2 versions of copy_net_ns. One version for when we compile in network namespace suport and another stub for all other occasions.
--- include/net/net_namespace.h | 15 +++++++++------ net/core/net_namespace.c | 7 ------- 2 files changed, 9 insertions(+), 13 deletions(-)
include/net/net_namespace.h +9 -6
@@ -126,16 +126,19 @@ struct net {/* Init's network namespace */ extern struct net init_net; -#ifdef CONFIG_NET +#ifdef CONFIG_NET_NS extern struct net *copy_net_ns (unsigned long flags,struct net *net_ns); -#else /* CONFIG_NET */ -static inline struct net *copy_net_ns (unsigned long flags,struct net *net_ns) +#else /* CONFIG_NET_NS */ +#include <linux/sched.h> +#include <linux/nsproxy.h> +static inline struct net *copy_net_ns (unsigned long flags,struct net *old_net) { -/* There is nothing to copy so this is a noop */ -return net_ns; +if (flags &CLONE_NEWNET ) +return ERR_PTR (-EINVAL ); +return old_net; } -#endif /* CONFIG_NET */ +#endif /* CONFIG_NET_NS */ extern struct list_head net_namespace_list;
net/core/net_namespace.c +0 -7
@@ -347,13 +347,6 @@ struct net *get_net_ns_by_fd(int fd) }#else -struct net *copy_net_ns (unsigned long flags,struct net *old_net) -{ -if (flags &CLONE_NEWNET ) -return ERR_PTR (-EINVAL ); -return old_net; -} -struct net *get_net_ns_by_fd (int fd) {return ERR_PTR (-EINVAL );
Signature · 1 line
1.7.5.4
A message that is not in the archive (sent off-list or not yet received): 1353070992-5552-1-git-send-email-ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]
PATCH 2/17 userns: make each net (net_ns) belong to a user_ns
From: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
The user namespace which creates a new network namespace owns that namespace and all resources created in it. This way we can target capability checks for privileged operations against network resources to the user_ns which created the network namespace in which the resource lives. Privilege to the user namespace which owns the network namespace, or any parent user namespace thereof, provides the same privilege to the network resource.
This patch is reworked from a version originally by
Serge E. Hallyn <[email protected]>
--- include/net/net_namespace.h | 9 +++++++-- kernel/nsproxy.c | 2 +- net/core/net_namespace.c | 16 ++++++++++++---- 3 files changed, 20 insertions(+), 7 deletions(-)
include/net/net_namespace.h +7 -2
@@ -23,6 +23,7 @@#endif #include <net/netns/xfrm.h> +struct user_namespace ;struct proc_dir_entry ;struct net_device ;struct sock ;
@@ -53,6 +54,8 @@ struct net {struct list_head cleanup_list;/* namespaces on death row */ struct list_head exit_list;/* Use only net_mutex */ +struct user_namespace *user_ns;/* Owning user namespace */ +struct proc_dir_entry *proc_net;struct proc_dir_entry *proc_net_stat;
@@ -127,12 +130,14 @@ struct net {extern struct net init_net;#ifdef CONFIG_NET_NS -extern struct net *copy_net_ns (unsigned long flags,struct net *net_ns); +extern struct net *copy_net_ns (unsigned long flags, +struct user_namespace *user_ns,struct net *old_net);#else /* CONFIG_NET_NS */ #include <linux/sched.h> #include <linux/nsproxy.h> -static inline struct net *copy_net_ns (unsigned long flags,struct net *old_net) +static inline struct net *copy_net_ns (unsigned long flags, +struct user_namespace *user_ns,struct net *old_net) {if (flags &CLONE_NEWNET )return ERR_PTR (-EINVAL );
kernel/nsproxy.c +1 -1
@@ -90,7 +90,7 @@ static struct nsproxy *create_new_namespaces(unsigned long flags, goto out_pid; } - new_nsp->net_ns =copy_net_ns (flags, tsk->nsproxy->net_ns); + new_nsp->net_ns =copy_net_ns (flags,task_cred_xxx (tsk, user_ns), tsk->nsproxy->net_ns);if (IS_ERR (new_nsp->net_ns)) { err =PTR_ERR (new_nsp->net_ns); goto out_net;
net/core/net_namespace.c +12 -4
@@ -13,6 +13,7 @@#include <linux/proc_fs.h> #include <linux/file.h> #include <linux/export.h> +#include <linux/user_namespace.h> #include <net/net_namespace.h> #include <net/netns/generic.h>
@@ -145,7 +146,7 @@ static void ops_free_list(const struct pernet_operations *ops,/* * setup_net runs the initializers for the network namespace object. */ -static __net_init int setup_net (struct net *net) +static __net_init int setup_net (struct net *net,struct user_namespace *user_ns) {/* Must be called with net_mutex held */ const struct pernet_operations *ops, *saved_ops;
@@ -155,6 +156,7 @@ static __net_init int setup_net(struct net *net)atomic_set (&net->count,1 );atomic_set (&net->passive,1 ); net->dev_base_seq =1 ; + net->user_ns = user_ns;#ifdef NETNS_REFCNT_DEBUG atomic_set (&net->use_count,0 );
@@ -232,7 +234,8 @@ void net_drop_ns(void *p)net_free (ns); } -struct net *copy_net_ns (unsigned long flags,struct net *old_net) +struct net *copy_net_ns (unsigned long flags, +struct user_namespace *user_ns,struct net *old_net) {struct net *net;int rv;
@@ -243,8 +246,11 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net) net =net_alloc ();if (!net)return ERR_PTR (-ENOMEM ); + +get_user_ns (user_ns); +mutex_lock (&net_mutex); - rv =setup_net (net); + rv =setup_net (net, user_ns);if (rv ==0 ) {rtnl_lock ();list_add_tail_rcu (&net->list, &net_namespace_list);
@@ -252,6 +258,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net) }mutex_unlock (&net_mutex);if (rv <0 ) { +put_user_ns (user_ns);net_drop_ns (net);return ERR_PTR (rv); }
@@ -308,6 +315,7 @@ static void cleanup_net(struct work_struct *work)/* Finally it is safe to free my network namespace structure */ list_for_each_entry_safe (net, tmp, &net_exit_list, exit_list) {list_del_init (&net->exit_list); +put_user_ns (net->user_ns);net_drop_ns (net); } }
@@ -395,7 +403,7 @@ static int __init net_ns_init(void)rcu_assign_pointer (init_net.gen, ng);mutex_lock (&net_mutex); -if (setup_net (&init_net)) +if (setup_net (&init_net, &init_user_ns))panic ("Could not setup the initial network namespace" );rtnl_lock ();
Signature · 1 line
1.7.5.4
PATCH 3/17 sysctl: Pass useful parameters to sysctl permissions
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Current is implicitly avaiable so passing current->nsproxy isn't useful.
- The ctl_table_header is needed to find how the sysctl table is connected to the rest of sysctl.
- ctl_table_root is avaiable in the ctl_table_header so no need to it.
With these changes it becomes possible to write a version of net_sysctl_permission that takes into account the network namespace of the sysctl table, an important feature in extending the user namespace.
--- fs/proc/proc_sysctl.c | 9 +++++---- include/linux/sysctl.h | 3 +-- net/sysctl_net.c | 3 +-- 3 files changed, 7 insertions(+), 8 deletions(-)
fs/proc/proc_sysctl.c +5 -4
@@ -378,12 +378,13 @@ static int test_perm(int mode, int op)return -EACCES ; } -static int sysctl_perm (struct ctl_table_root *root,struct ctl_table *table,int op) +static int sysctl_perm (struct ctl_table_header *head,struct ctl_table *table,int op) { +struct ctl_table_root *root = head->root;int mode;if (root->permissions) - mode = root->permissions (root, current->nsproxy, table); + mode = root->permissions (head, table);else mode = table->mode;
@@ -491,7 +492,7 @@ static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,* and won't be until we finish. */ error = -EPERM ; -if (sysctl_perm (head->root, table, write ?MAY_WRITE :MAY_READ )) +if (sysctl_perm (head, table, write ?MAY_WRITE :MAY_READ )) goto out;/* if that can happen at all, it should be -EINVAL, not -EISDIR */
@@ -717,7 +718,7 @@ static int proc_sys_permission(struct inode *inode, int mask)if (!table)/* global root - r-xr-xr-x */ error = mask &MAY_WRITE ? -EACCES :0 ;else /* Use the permissions on the sysctl table entry */ - error =sysctl_perm (head->root, table, mask & ~MAY_NOT_BLOCK ); + error =sysctl_perm (head, table, mask & ~MAY_NOT_BLOCK );sysctl_head_finish (head);return error;
include/linux/sysctl.h +1 -2
@@ -158,8 +158,7 @@ struct ctl_table_root {struct ctl_table_set default_set;struct ctl_table_set *(*lookup)(struct ctl_table_root *root,struct nsproxy *namespaces); -int (*permissions)(struct ctl_table_root *root, -struct nsproxy *namespaces,struct ctl_table *table); +int (*permissions)(struct ctl_table_header *head,struct ctl_table *table); };/* struct ctl_path describes where in the hierarchy a table is added */
net/sysctl_net.c +1 -2
@@ -38,8 +38,7 @@ static int is_seen(struct ctl_table_set *set) }/* Return standard mode bits for table entry. */ -static int net_ctl_permissions (struct ctl_table_root *root, -struct nsproxy *nsproxy, +static int net_ctl_permissions (struct ctl_table_header *head,struct ctl_table *table) {/* Allow network administrator to have same access as root. */
Signature · 1 line
1.7.5.4
PATCH 4/17 net: Don't export sysctls to unprivileged users
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
In preparation for supporting the creation of network namespaces by unprivileged users, modify all of the per net sysctl exports and refuse to allow them to unprivileged users.
This makes it safe for unprivileged users in general to access per net sysctls, and allows sysctls to be exported to unprivileged users on an individual basis as they are deemed safe.
--- net/core/neighbour.c | 4 ++++ net/core/sysctl_net_core.c | 5 +++++ net/ipv4/devinet.c | 8 ++++++++ net/ipv4/ip_fragment.c | 4 ++++ net/ipv4/route.c | 4 ++++ net/ipv4/sysctl_net_ipv4.c | 3 +++ net/ipv6/addrconf.c | 4 ++++ net/ipv6/icmp.c | 7 ++++++- net/ipv6/reassembly.c | 4 ++++ net/ipv6/route.c | 4 ++++ net/ipv6/sysctl_net_ipv6.c | 4 ++++ net/netfilter/ipvs/ip_vs_ctl.c | 4 ++++ net/netfilter/ipvs/ip_vs_lblc.c | 7 ++++++- net/netfilter/ipvs/ip_vs_lblcr.c | 4 ++++ net/netfilter/nf_conntrack_acct.c | 4 ++++ net/netfilter/nf_conntrack_ecache.c | 4 ++++ net/netfilter/nf_conntrack_helper.c | 4 ++++ net/netfilter/nf_conntrack_proto_dccp.c | 8 ++++++-- net/netfilter/nf_conntrack_standalone.c | 4 ++++ net/netfilter/nf_conntrack_timestamp.c | 4 ++++ net/unix/sysctl_net_unix.c | 4 ++++ net/xfrm/xfrm_sysctl.c | 4 ++++ 22 files changed, 98 insertions(+), 4 deletions(-)
net/core/neighbour.c +4 -0
@@ -2987,6 +2987,10 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS ].extra1 = dev; } +/* Don't export sysctls to unprivileged users */ +if (neigh_parms_net (p)->user_ns != &init_user_ns) + t->neigh_vars[0 ].procname =NULL ; +snprintf (neigh_path,sizeof (neigh_path),"net/%s/neigh/%s" , p_name, dev_name_source); t->sysctl_header =
net/core/sysctl_net_core.c +5 -0
@@ -216,6 +216,11 @@ static __net_init int sysctl_core_net_init(struct net *net) goto err_dup; tbl[0 ].data = &net->core.sysctl_somaxconn; + +/* Don't export any sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) { + tbl[0 ].procname =NULL ; + } } net->core.sysctl_hdr =register_net_sysctl (net,"net/core" , tbl);
net/ipv4/devinet.c +8 -0
@@ -1637,6 +1637,10 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name, t->devinet_vars[i].extra2 = net; } +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + t->devinet_vars[0 ].procname =NULL ; +snprintf (path,sizeof (path),"net/ipv4/conf/%s" , dev_name); t->sysctl_header =register_net_sysctl (net, path, t->devinet_vars);
@@ -1722,6 +1726,10 @@ static __net_init int devinet_init_net(struct net *net) tbl[0 ].data = &all->data[IPV4_DEVCONF_FORWARDING -1 ]; tbl[0 ].extra1 = all; tbl[0 ].extra2 = net; + +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + tbl[0 ].procname =NULL ;#endif }
net/ipv4/ip_fragment.c +4 -0
@@ -802,6 +802,10 @@ static int __net_init ip4_frags_ns_ctl_register(struct net *net) table[0 ].data = &net->ipv4.frags.high_thresh; table[1 ].data = &net->ipv4.frags.low_thresh; table[2 ].data = &net->ipv4.frags.timeout; + +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + table[0 ].procname =NULL ; } hdr =register_net_sysctl (net,"net/ipv4" , table);
net/ipv4/route.c +4 -0
@@ -2493,6 +2493,10 @@ static __net_init int sysctl_route_net_init(struct net *net) tbl =kmemdup (tbl,sizeof (ipv4_route_flush_table),GFP_KERNEL );if (tbl ==NULL ) goto err_dup; + +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + tbl[0 ].procname =NULL ; } tbl[0 ].extra1 = net;
net/ipv4/sysctl_net_ipv4.c +3 -0
@@ -883,6 +883,9 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) table[6 ].data = &net->ipv4.sysctl_ping_group_range; +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + table[0 ].procname =NULL ; }/*
net/ipv6/addrconf.c +4 -0
@@ -4582,6 +4582,10 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name, t->addrconf_vars[i].extra2 = net; } +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + t->addrconf_vars[0 ].procname =NULL ; +snprintf (path,sizeof (path),"net/ipv6/conf/%s" , dev_name); t->sysctl_header =register_net_sysctl (net, path, t->addrconf_vars);
net/ipv6/icmp.c +6 -1
@@ -967,9 +967,14 @@ struct ctl_table * __net_init ipv6_icmp_sysctl_init(struct net *net)sizeof (ipv6_icmp_table_template), GFP_KERNEL); -if (table) +if (table) { table[0 ].data = &net->ipv6.sysctl.icmpv6_time; +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + table[0 ].procname =NULL ; + } + return table; }#endif
net/ipv6/reassembly.c +4 -0
@@ -616,6 +616,10 @@ static int __net_init ip6_frags_ns_sysctl_register(struct net *net) table[0 ].data = &net->ipv6.frags.high_thresh; table[1 ].data = &net->ipv6.frags.low_thresh; table[2 ].data = &net->ipv6.frags.timeout; + +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + table[0 ].procname =NULL ; } hdr =register_net_sysctl (net,"net/ipv6" , table);
net/ipv6/route.c +4 -0
@@ -2873,6 +2873,10 @@ struct ctl_table * __net_init ipv6_route_sysctl_init(struct net *net) table[7 ].data = &net->ipv6.sysctl.ip6_rt_mtu_expires; table[8 ].data = &net->ipv6.sysctl.ip6_rt_min_advmss; table[9 ].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; + +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + table[0 ].procname =NULL ; }return table;
net/ipv6/sysctl_net_ipv6.c +4 -0
@@ -52,6 +52,10 @@ static int __net_init ipv6_sysctl_net_init(struct net *net) goto out; ipv6_table[0 ].data = &net->ipv6.sysctl.bindv6only; +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + ipv6_table[0 ].procname =NULL ; + ipv6_route_table =ipv6_route_sysctl_init (net);if (!ipv6_route_table) goto out_ipv6_table;
net/netfilter/ipvs/ip_vs_ctl.c +4 -0
@@ -3699,6 +3699,10 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net) tbl =kmemdup (vs_vars,sizeof (vs_vars),GFP_KERNEL );if (tbl ==NULL )return -ENOMEM ; + +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + tbl[0 ].procname =NULL ; }else tbl = vs_vars;/* Initialize sysctl defaults */
net/netfilter/ipvs/ip_vs_lblc.c +6 -1
@@ -560,6 +560,11 @@ static int __net_init __ip_vs_lblc_init(struct net *net) GFP_KERNEL);if (ipvs->lblc_ctl_table ==NULL )return -ENOMEM ; + +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + ipvs->lblc_ctl_table[0 ].procname =NULL ; + }else ipvs->lblc_ctl_table = vs_vars_table; ipvs->sysctl_lblc_expiration =DEFAULT_EXPIRATION ;
@@ -569,7 +574,7 @@ static int __net_init __ip_vs_lblc_init(struct net *net)register_net_sysctl (net,"net/ipv4/vs" , ipvs->lblc_ctl_table);if (!ipvs->lblc_ctl_header) {if (!net_eq (net, &init_net)) -kfree (ipvs->lblc_ctl_table); +kfree (ipvs->lblc_ctl_table);\return -ENOMEM ; }
net/netfilter/ipvs/ip_vs_lblcr.c +4 -0
@@ -754,6 +754,10 @@ static int __net_init __ip_vs_lblcr_init(struct net *net) GFP_KERNEL);if (ipvs->lblcr_ctl_table ==NULL )return -ENOMEM ; + +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + ipvs->lblcr_ctl_table[0 ].procname =NULL ; }else ipvs->lblcr_ctl_table = vs_vars_table; ipvs->sysctl_lblcr_expiration =DEFAULT_EXPIRATION ;
net/netfilter/nf_conntrack_acct.c +4 -0
@@ -69,6 +69,10 @@ static int nf_conntrack_acct_init_sysctl(struct net *net) table[0 ].data = &net->ct.sysctl_acct; +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + table[0 ].procname =NULL ; + net->ct.acct_sysctl_header =register_net_sysctl (net,"net/netfilter" , table);if (!net->ct.acct_sysctl_header) {
net/netfilter/nf_conntrack_ecache.c +4 -0
@@ -196,6 +196,10 @@ static int nf_conntrack_event_init_sysctl(struct net *net) table[0 ].data = &net->ct.sysctl_events; table[1 ].data = &net->ct.sysctl_events_retry_timeout; +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + table[0 ].procname =NULL ; + net->ct.event_sysctl_header =register_net_sysctl (net,"net/netfilter" , table);if (!net->ct.event_sysctl_header) {
net/netfilter/nf_conntrack_helper.c +4 -0
@@ -64,6 +64,10 @@ static int nf_conntrack_helper_init_sysctl(struct net *net) table[0 ].data = &net->ct.sysctl_auto_assign_helper; +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + table[0 ].procname =NULL ; + net->ct.helper_sysctl_header =register_net_sysctl (net,"net/netfilter" , table);
net/netfilter/nf_conntrack_proto_dccp.c +6 -2
@@ -815,7 +815,7 @@ static struct ctl_table dccp_sysctl_table[] = { };#endif /* CONFIG_SYSCTL */ -static int dccp_kmemdup_sysctl_table (struct nf_proto_net *pn, +static int dccp_kmemdup_sysctl_table (struct net *net,struct nf_proto_net *pn,struct dccp_net *dn) {#ifdef CONFIG_SYSCTL
@@ -836,6 +836,10 @@ static int dccp_kmemdup_sysctl_table(struct nf_proto_net *pn, pn->ctl_table[5 ].data = &dn->dccp_timeout[CT_DCCP_CLOSING ]; pn->ctl_table[6 ].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT ]; pn->ctl_table[7 ].data = &dn->dccp_loose; + +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + pn->ctl_table[0 ].procname =NULL ;#endif return 0 ; }
@@ -857,7 +861,7 @@ static int dccp_init_net(struct net *net, u_int16_t proto) dn->dccp_timeout[CT_DCCP_TIMEWAIT ] =2 *DCCP_MSL ; } -return dccp_kmemdup_sysctl_table (pn, dn); +return dccp_kmemdup_sysctl_table (net, pn, dn); }static struct nf_conntrack_l4proto dccp_proto4__read_mostly = {
net/netfilter/nf_conntrack_standalone.c +4 -0
@@ -489,6 +489,10 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net) table[3 ].data = &net->ct.sysctl_checksum; table[4 ].data = &net->ct.sysctl_log_invalid; +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + table[0 ].procname =NULL ; + net->ct.sysctl_header =register_net_sysctl (net,"net/netfilter" , table);if (!net->ct.sysctl_header) goto out_unregister_netfilter;
net/netfilter/nf_conntrack_timestamp.c +4 -0
@@ -51,6 +51,10 @@ static int nf_conntrack_tstamp_init_sysctl(struct net *net) table[0 ].data = &net->ct.sysctl_tstamp; +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + table[0 ].procname =NULL ; + net->ct.tstamp_sysctl_header =register_net_sysctl (net,"net/netfilter" , table);if (!net->ct.tstamp_sysctl_header) {
net/unix/sysctl_net_unix.c +4 -0
@@ -34,6 +34,10 @@ int __net_init unix_sysctl_register(struct net *net)if (table ==NULL ) goto err_alloc; +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + table[0 ].procname =NULL ; + table[0 ].data = &net->unx.sysctl_max_dgram_qlen; net->unx.ctl =register_net_sysctl (net,"net/unix" , table);if (net->unx.ctl ==NULL )
net/xfrm/xfrm_sysctl.c +4 -0
@@ -54,6 +54,10 @@ int __net_init xfrm_sysctl_init(struct net *net) table[2 ].data = &net->xfrm.sysctl_larval_drop; table[3 ].data = &net->xfrm.sysctl_acq_expires; +/* Don't export sysctls to unprivileged users */ +if (net->user_ns != &init_user_ns) + table[0 ].procname =NULL ; + net->xfrm.sysctl_hdr =register_net_sysctl (net,"net/core" , table);if (!net->xfrm.sysctl_hdr) goto out_register;
Signature · 1 line
1.7.5.4
PATCH 5/17 net: Push capable(CAP_NET_ADMIN) into the rtnl methods
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- In rtnetlink_rcv_msg convert the capable(CAP_NET_ADMIN) check to ns_capable(net->user-ns, CAP_NET_ADMIN). Allowing unprivileged users to make netlink calls to modify their local network namespace.
- In the rtnetlink doit methods add capable(CAP_NET_ADMIN) so that calls that are not safe for unprivileged users are still protected.
Later patches will remove the extra capable calls from methods that are safe for unprivilged users.
--- net/bridge/br_netlink.c | 3 +++ net/can/gw.c | 6 ++++++ net/core/fib_rules.c | 6 ++++++ net/core/neighbour.c | 9 +++++++++ net/core/rtnetlink.c | 17 ++++++++++++++++- net/dcb/dcbnl.c | 3 +++ net/decnet/dn_dev.c | 6 ++++++ net/decnet/dn_fib.c | 6 ++++++ net/ipv4/devinet.c | 6 ++++++ net/ipv4/fib_frontend.c | 6 ++++++ net/ipv6/addrconf.c | 6 ++++++ net/ipv6/addrlabel.c | 3 +++ net/ipv6/route.c | 6 ++++++ net/phonet/pn_netlink.c | 6 ++++++ net/sched/act_api.c | 3 +++ net/sched/cls_api.c | 2 ++ net/sched/sch_api.c | 9 +++++++++ 17 files changed, 102 insertions(+), 1 deletions(-)
net/bridge/br_netlink.c +3 -0
@@ -153,6 +153,9 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct net_bridge_port *p;u8 new_state; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +if (nlmsg_len (nlh) <sizeof (*ifm))return -EINVAL ;
net/can/gw.c +6 -0
@@ -751,6 +751,9 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh,struct cgw_job *gwj;int err =0 ; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +if (nlmsg_len (nlh) <sizeof (*r))return -EINVAL ;
@@ -839,6 +842,9 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct can_can_gw ccgw;int err =0 ; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +if (nlmsg_len (nlh) <sizeof (*r))return -EINVAL ;
net/core/fib_rules.c +6 -0
@@ -275,6 +275,9 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)struct nlattr *tb[FRA_MAX +1 ];int err = -EINVAL , unresolved =0 ; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +if (nlh->nlmsg_len <nlmsg_msg_size (sizeof (*frh))) goto errout;
@@ -424,6 +427,9 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)struct nlattr *tb[FRA_MAX +1 ];int err = -EINVAL ; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +if (nlh->nlmsg_len <nlmsg_msg_size (sizeof (*frh))) goto errout;
net/core/neighbour.c +9 -0
@@ -1620,6 +1620,9 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct net_device *dev =NULL ;int err = -EINVAL ; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +ASSERT_RTNL ();if (nlmsg_len (nlh) <sizeof (*ndm)) goto out;
@@ -1684,6 +1687,9 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct net_device *dev =NULL ;int err; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +ASSERT_RTNL (); err =nlmsg_parse (nlh,sizeof (*ndm), tb,NDA_MAX ,NULL );if (err <0 )
@@ -1962,6 +1968,9 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct nlattr *tb[NDTA_MAX +1 ];int err; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; + err =nlmsg_parse (nlh,sizeof (*ndtmsg), tb,NDTA_MAX , nl_neightbl_policy);if (err <0 )
net/core/rtnetlink.c +16 -1
@@ -1547,6 +1547,9 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct nlattr *tb[IFLA_MAX +1 ];char ifname[IFNAMSIZ ]; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; + err =nlmsg_parse (nlh,sizeof (*ifm), tb,IFLA_MAX , ifla_policy);if (err <0 ) goto errout;
@@ -1590,6 +1593,9 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)int err;LIST_HEAD (list_kill); +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; + err =nlmsg_parse (nlh,sizeof (*ifm), tb,IFLA_MAX , ifla_policy);if (err <0 )return err;
@@ -1720,6 +1726,9 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct nlattr *linkinfo[IFLA_INFO_MAX +1 ];int err; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +#ifdef CONFIG_MODULES replay:#endif
@@ -2057,6 +2066,9 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)u8 *addr;int err; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; + err =nlmsg_parse (nlh,sizeof (*ndm), tb,NDA_MAX ,NULL );if (err <0 )return err;
@@ -2123,6 +2135,9 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)int err = -EINVAL ;__u8 *addr; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +if (nlmsg_len (nlh) <sizeof (*ndm))return -EINVAL ;
@@ -2282,7 +2297,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) sz_idx = type>>2 ; kind = type&3 ; -if (kind !=2 && !capable (CAP_NET_ADMIN )) +if (kind !=2 && !ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;if (kind ==2 && nlh->nlmsg_flags&NLM_F_DUMP ) {
net/dcb/dcbnl.c +3 -0
@@ -1662,6 +1662,9 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct nlmsghdr *reply_nlh =NULL ;const struct reply_func *fn; +if ((nlh->nlmsg_type ==RTM_SETDCB ) && !capable (CAP_NET_ADMIN )) +return -EPERM ; +if (!net_eq (net, &init_net))return -EINVAL ;
net/decnet/dn_dev.c +6 -0
@@ -573,6 +573,9 @@ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct dn_ifaddr __rcu **ifap;int err = -EINVAL ; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +if (!net_eq (net, &init_net)) goto errout;
@@ -614,6 +617,9 @@ static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct dn_ifaddr *ifa;int err; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +if (!net_eq (net, &init_net))return -EINVAL ;
net/decnet/dn_fib.c +6 -0
@@ -520,6 +520,9 @@ static int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *struct rtattr **rta = arg;struct rtmsg *r =NLMSG_DATA (nlh); +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +if (!net_eq (net, &init_net))return -EINVAL ;
@@ -540,6 +543,9 @@ static int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *struct rtattr **rta = arg;struct rtmsg *r =NLMSG_DATA (nlh); +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +if (!net_eq (net, &init_net))return -EINVAL ;
net/ipv4/devinet.c +6 -0
@@ -538,6 +538,9 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *argASSERT_RTNL (); +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; + err =nlmsg_parse (nlh,sizeof (*ifm), tb,IFA_MAX , ifa_ipv4_policy);if (err <0 ) goto errout;
@@ -645,6 +648,9 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *argASSERT_RTNL (); +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; + ifa =rtm_to_ifaddr (net, nlh);if (IS_ERR (ifa))return PTR_ERR (ifa);
net/ipv4/fib_frontend.c +6 -0
@@ -613,6 +613,9 @@ static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arstruct fib_table *tb;int err; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; + err =rtm_to_fib_config (net, skb, nlh, &cfg);if (err <0 ) goto errout;
@@ -635,6 +638,9 @@ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arstruct fib_table *tb;int err; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; + err =rtm_to_fib_config (net, skb, nlh, &cfg);if (err <0 ) goto errout;
net/ipv6/addrconf.c +6 -0
@@ -3369,6 +3369,9 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct in6_addr *pfx;int err; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; + err =nlmsg_parse (nlh,sizeof (*ifm), tb,IFA_MAX , ifa_ipv6_policy);if (err <0 )return err;
@@ -3439,6 +3442,9 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)u8 ifa_flags;int err; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; + err =nlmsg_parse (nlh,sizeof (*ifm), tb,IFA_MAX , ifa_ipv6_policy);if (err <0 )return err;
net/ipv6/addrlabel.c +3 -0
@@ -425,6 +425,9 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh,u32 label;int err =0 ; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; + err =nlmsg_parse (nlh,sizeof (*ifal), tb,IFAL_MAX , ifal_policy);if (err <0 )return err;
net/ipv6/route.c +6 -0
@@ -2336,6 +2336,9 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *astruct fib6_config cfg;int err; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; + err =rtm_to_fib6_config (skb, nlh, &cfg);if (err <0 )return err;
@@ -2348,6 +2351,9 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *astruct fib6_config cfg;int err; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; + err =rtm_to_fib6_config (skb, nlh, &cfg);if (err <0 )return err;
net/phonet/pn_netlink.c +6 -0
@@ -70,6 +70,9 @@ static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)int err;u8 pnaddr; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +if (!capable (CAP_SYS_ADMIN ))return -EPERM ;
@@ -230,6 +233,9 @@ static int route_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)int err;u8 dst; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +if (!capable (CAP_SYS_ADMIN ))return -EPERM ;
net/sched/act_api.c +3 -0
@@ -987,6 +987,9 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)u32 portid = skb ?NETLINK_CB (skb).portid :0 ;int ret =0 , ovr =0 ; +if ((n->nlmsg_type !=RTM_GETACTION ) && !capable (CAP_NET_ADMIN )) +return -EPERM ; + ret =nlmsg_parse (n,sizeof (struct tcamsg ), tca,TCA_ACT_MAX ,NULL );if (ret <0 )return ret;
net/sched/cls_api.c +2 -0
@@ -139,6 +139,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)int err;int tp_created =0 ; +if ((n->nlmsg_type !=RTM_GETTFILTER ) && !capable (CAP_NET_ADMIN )) +return -EPERM ; replay: t =nlmsg_data (n); protocol =TC_H_MIN (t->tcm_info);
net/sched/sch_api.c +9 -0
@@ -981,6 +981,9 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)struct Qdisc *p =NULL ;int err; +if ((n->nlmsg_type !=RTM_GETQDISC ) && !capable (CAP_NET_ADMIN )) +return -EPERM ; + dev =__dev_get_by_index (net, tcm->tcm_ifindex);if (!dev)return -ENODEV ;
@@ -1044,6 +1047,9 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)struct Qdisc *q, *p;int err; +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; + replay:/* Reinit, just in case something touches this. */ tcm =nlmsg_data (n);
@@ -1380,6 +1386,9 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)u32 qid =TC_H_MAJ (clid);int err; +if ((n->nlmsg_type !=RTM_GETTCLASS ) && !capable (CAP_NET_ADMIN )) +return -EPERM ; + dev =__dev_get_by_index (net, tcm->tcm_ifindex);if (!dev)return -ENODEV ;
Signature · 1 line
1.7.5.4
PATCH 6/17 net: Update the per network namespace sysctls to be available to the network namespace owner
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Allow anyone with CAP_NET_ADMIN rights in the user namespace of the the netowrk namespace to change sysctls.
- Allow anyone the uid of the user namespace root the same permissions over the network namespace sysctls as the global root.
- Allow anyone with gid of the user namespace root group the same permissions over the network namespace sysctl as the global root group.
--- net/sysctl_net.c | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-)
net/sysctl_net.c +11 -1
@@ -41,11 +41,21 @@ static int is_seen(struct ctl_table_set *set)static int net_ctl_permissions (struct ctl_table_header *head,struct ctl_table *table) { + struct net *net = container_of(head->set, struct net, sysctls); +kuid_t root_uid =make_kuid (net->user_ns,0 ); +kgid_t root_gid =make_kgid (net->user_ns,0 ); +/* Allow network administrator to have same access as root. */ -if (capable (CAP_NET_ADMIN )) { +if (ns_capable (net->user_ns,CAP_NET_ADMIN ) || +uid_eq (root_uid,current_uid ())) {int mode = (table->mode >>6 ) &7 ;return (mode <<6 ) | (mode <<3 ) | mode; } +/* Allow netns root group to have the same assess as the root group */ +if (gid_eq (root_gid,current_gid ())) { +int mode = (table->mode >>3 ) &7 ; +return (mode <<3 ) | (mode <<3 ) | mode; + }return table->mode; }
Signature · 1 line
1.7.5.4
PATCH 7/17 user_ns: get rid of duplicate code in net_ctl_permissions
In reply to a message not in the archiveFrom: Zhao Hongjiang <[email protected]>
Get rid of duplicate code in net_ctl_permissions and fix the comment.
--- net/sysctl_net.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
net/sysctl_net.c +2 -2
@@ -51,10 +51,10 @@ static int net_ctl_permissions(struct ctl_table_header *head,int mode = (table->mode >>6 ) &7 ;return (mode <<6 ) | (mode <<3 ) | mode; } -/* Allow netns root group to have the same assess as the root group */ +/* Allow netns root group to have the same access as the root group */ if (gid_eq (root_gid,current_gid ())) {int mode = (table->mode >>3 ) &7 ; -return (mode <<3 ) | (mode <<3 ) | mode; +return (mode <<3 ) | mode; }return table->mode; }
Signature · 1 line
1.7.5.4
PATCH 8/17 net: Allow userns root to force the scm creds
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
If the user calling sendmsg has the appropriate privieleges in their user namespace allow them to set the uid, gid, and pid in the SCM_CREDENTIALS control message to any valid value.
--- net/core/scm.c | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
net/core/scm.c +3 -3
@@ -51,11 +51,11 @@ static __inline__ int scm_check_creds(struct ucred *creds)if (!uid_valid (uid) || !gid_valid (gid))return -EINVAL ; -if ((creds->pid ==task_tgid_vnr (current) ||capable (CAP_SYS_ADMIN )) && +if ((creds->pid ==task_tgid_vnr (current) ||nsown_capable (CAP_SYS_ADMIN )) && ((uid_eq (uid, cred->uid) ||uid_eq (uid, cred->euid) || -uid_eq (uid, cred->suid)) ||capable (CAP_SETUID )) && +uid_eq (uid, cred->suid)) ||nsown_capable (CAP_SETUID )) && ((gid_eq (gid, cred->gid) ||gid_eq (gid, cred->egid) || -gid_eq (gid, cred->sgid)) ||capable (CAP_SETGID ))) { +gid_eq (gid, cred->sgid)) ||nsown_capable (CAP_SETGID ))) {return 0 ; }return -EPERM ;
Signature · 1 line
1.7.5.4
PATCH 9/17 net: Allow userns root control of the core of the network stack.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Allow an unpriviled user who has created a user namespace, and then created a network namespace to effectively use the new network namespace, by reducing capable(CAP_NET_ADMIN) and capable(CAP_NET_RAW) calls to be ns_capable(net->user_ns, CAP_NET_ADMIN), or capable(net->user_ns, CAP_NET_RAW) calls.
Settings that merely control a single network device are allowed. Either the network device is a logical network device where restrictions make no difference or the network device is hardware NIC that has been explicity moved from the initial network namespace.
In general policy and network stack state changes are allowed while resource control is left unchanged.
Allow ethtool ioctls.
Allow binding to network devices.
Allow setting the socket mark.
Allow setting the socket priority.
Allow setting the network device alias via sysfs. Allow setting the mtu via sysfs.
Allow changing the network device flags via sysfs. Allow setting the network device group via sysfs.
Allow the following network device ioctls.
SIOCGMIIPHY
SIOCGMIIREG
SIOCSIFNAME
SIOCSIFFLAGS
SIOCSIFMETRIC
SIOCSIFMTU
SIOCSIFHWADDR
SIOCSIFSLAVE
SIOCADDMULTI
SIOCDELMULTI
SIOCSIFHWBROADCAST
SIOCSMIIREG
SIOCBONDENSLAVE
SIOCBONDRELEASE
SIOCBONDSETHWADDR
SIOCBONDCHANGEACTIVE
SIOCBRADDIF
SIOCBRDELIF
SIOCSHWTSTAMP
--- net/core/dev.c | 17 +++++++++++++---- net/core/ethtool.c | 2 +- net/core/net-sysfs.c | 15 ++++++++++----- net/core/sock.c | 7 ++++--- 4 files changed, 28 insertions(+), 13 deletions(-)
net/core/dev.c +13 -4
@@ -5200,7 +5200,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)case SIOCGMIIPHY :case SIOCGMIIREG :case SIOCSIFNAME : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;dev_load (net, ifr.ifr_name);rtnl_lock ();
@@ -5221,16 +5221,25 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)* - require strict serialization. * - do not return a value */ +case SIOCSIFMAP : +case SIOCSIFTXQLEN : +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +/* fall through */ +/* +* These ioctl calls: +* - require local superuser power. +* - require strict serialization. +* - do not return a value +*/ case SIOCSIFFLAGS :case SIOCSIFMETRIC :case SIOCSIFMTU : -case SIOCSIFMAP :case SIOCSIFHWADDR :case SIOCSIFSLAVE :case SIOCADDMULTI :case SIOCDELMULTI :case SIOCSIFHWBROADCAST : -case SIOCSIFTXQLEN :case SIOCSMIIREG :case SIOCBONDENSLAVE :case SIOCBONDRELEASE :
@@ -5239,7 +5248,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)case SIOCBRADDIF :case SIOCBRDELIF :case SIOCSHWTSTAMP : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;/* fall through */ case SIOCBONDSLAVEINFOQUERY :
net/core/ethtool.c +1 -1
@@ -1460,7 +1460,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)case ETHTOOL_GEEE :break ;default : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ; }
net/core/net-sysfs.c +10 -5
@@ -73,11 +73,12 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len, int (*set)(struct net_device *, unsigned long)) { - struct net_device *net = to_net_dev(dev); + struct net_device *netdev = to_net_dev(dev); +struct net *net =dev_net (netdev);unsigned long new;int ret = -EINVAL ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ; ret =kstrtoul (buf,0 , &new);
@@ -87,8 +88,8 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,if (!rtnl_trylock ())return restart_syscall (); -if (dev_isalive (net)) { -if ((ret = (*set)(net, new)) ==0 ) +if (dev_isalive (netdev)) { +if ((ret = (*set)(netdev, new)) ==0 ) ret = len; }rtnl_unlock ();
@@ -264,6 +265,9 @@ static ssize_t store_tx_queue_len(struct device *dev,struct device_attribute *attr, const char *buf, size_t len) { + if (!capable(CAP_NET_ADMIN)) + return -EPERM; +return netdev_store (dev, attr, buf, len, change_tx_queue_len); }
@@ -271,10 +275,11 @@ static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) {struct net_device *netdev =to_net_dev (dev); +struct net *net =dev_net (netdev);size_t count = len;ssize_t ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;/* ignore trailing newline */
net/core/sock.c +4 -3
@@ -515,7 +515,7 @@ static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen)/* Sorry... */ ret = -EPERM ; -if (!capable (CAP_NET_RAW )) +if (!ns_capable (net->user_ns,CAP_NET_RAW )) goto out; ret = -EINVAL ;
@@ -696,7 +696,8 @@ set_rcvbuf:break ;case SO_PRIORITY : -if ((val >=0 && val <=6 ) ||capable (CAP_NET_ADMIN )) +if ((val >=0 && val <=6 ) || +ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN )) sk->sk_priority = val;else ret = -EPERM ;
@@ -813,7 +814,7 @@ set_rcvbuf:clear_bit (SOCK_PASSSEC , &sock->flags);break ;case SO_MARK : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN )) ret = -EPERM ;else sk->sk_mark = val;
Signature · 1 line
1.7.5.4
PATCH 10/17 net: Allow userns root to control ipv4
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Allow an unpriviled user who has created a user namespace, and then created a network namespace to effectively use the new network namespace, by reducing capable(CAP_NET_ADMIN) and capable(CAP_NET_RAW) calls to be ns_capable(net->user_ns, CAP_NET_ADMIN), or capable(net->user_ns, CAP_NET_RAW) calls.
Settings that merely control a single network device are allowed. Either the network device is a logical network device where restrictions make no difference or the network device is hardware NIC that has been explicity moved from the initial network namespace.
In general policy and network stack state changes are allowed while resource control is left unchanged.
Allow creating raw sockets.
Allow the SIOCSARP ioctl to control the arp cache.
Allow the SIOCSIFFLAG ioctl to allow setting network device flags. Allow the SIOCSIFADDR ioctl to allow setting a netdevice ipv4 address. Allow the SIOCSIFBRDADDR ioctl to allow setting a netdevice ipv4 broadcast address. Allow the SIOCSIFDSTADDR ioctl to allow setting a netdevice ipv4 destination address. Allow the SIOCSIFNETMASK ioctl to allow setting a netdevice ipv4 netmask. Allow the SIOCADDRT and SIOCDELRT ioctls to allow adding and deleting ipv4 routes.
Allow the SIOCADDTUNNEL, SIOCCHGTUNNEL and SIOCDELTUNNEL ioctls for adding, changing and deleting gre tunnels.
Allow the SIOCADDTUNNEL, SIOCCHGTUNNEL and SIOCDELTUNNEL ioctls for adding, changing and deleting ipip tunnels.
Allow the SIOCADDTUNNEL, SIOCCHGTUNNEL and SIOCDELTUNNEL ioctls for adding, changing and deleting ipsec virtual tunnel interfaces.
Allow setting the MRT_INIT, MRT_DONE, MRT_ADD_VIF, MRT_DEL_VIF, MRT_ADD_MFC, MRT_DEL_MFC, MRT_ASSERT, MRT_PIM, MRT_TABLE socket options on multicast routing sockets.
Allow setting and receiving IPOPT_CIPSO, IP_OPT_SEC, IP_OPT_SID and arbitrary ip options.
Allow setting IP_SEC_POLICY/IP_XFRM_POLICY ipv4 socket option. Allow setting the IP_TRANSPARENT ipv4 socket option. Allow setting the TCP_REPAIR socket option.
Allow setting the TCP_CONGESTION socket option.
--- net/ipv4/af_inet.c | 3 ++- net/ipv4/arp.c | 2 +- net/ipv4/devinet.c | 4 ++-- net/ipv4/fib_frontend.c | 2 +- net/ipv4/ip_gre.c | 4 ++-- net/ipv4/ip_options.c | 6 +++--- net/ipv4/ip_sockglue.c | 5 +++-- net/ipv4/ip_vti.c | 4 ++-- net/ipv4/ipip.c | 4 ++-- net/ipv4/ipmr.c | 2 +- net/ipv4/netfilter/arp_tables.c | 8 ++++---- net/ipv4/netfilter/ip_tables.c | 8 ++++---- net/ipv4/tcp.c | 2 +- net/ipv4/tcp_cong.c | 3 ++- 14 files changed, 30 insertions(+), 27 deletions(-)
net/ipv4/af_inet.c +2 -1
@@ -346,7 +346,8 @@ lookup_protocol: } err = -EPERM ; -if (sock->type ==SOCK_RAW && !kern && !capable (CAP_NET_RAW )) +if (sock->type ==SOCK_RAW && !kern && + !ns_capable (net->user_ns,CAP_NET_RAW )) goto out_rcu_unlock; err = -EAFNOSUPPORT ;
net/ipv4/arp.c +1 -1
@@ -1161,7 +1161,7 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)switch (cmd) {case SIOCDARP :case SIOCSARP : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;case SIOCGARP : err =copy_from_user (&r, arg,sizeof (struct arpreq ));
net/ipv4/devinet.c +2 -2
@@ -729,7 +729,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)case SIOCSIFFLAGS : ret = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) goto out;break ;case SIOCSIFADDR :/* Set interface address (and family) */
@@ -737,7 +737,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)case SIOCSIFDSTADDR :/* Set the destination address */ case SIOCSIFNETMASK :/* Set the netmask for the interface */ ret = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) goto out; ret = -EINVAL ;if (sin->sin_family !=AF_INET )
net/ipv4/fib_frontend.c +1 -1
@@ -488,7 +488,7 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)switch (cmd) {case SIOCADDRT :/* Add a route */ case SIOCDELRT :/* Delete a route */ -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;if (copy_from_user (&rt, arg,sizeof (rt)))
net/ipv4/ip_gre.c +2 -2
@@ -1082,7 +1082,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)case SIOCADDTUNNEL :case SIOCCHGTUNNEL : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) goto done; err = -EFAULT ;
@@ -1157,7 +1157,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)case SIOCDELTUNNEL : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) goto done;if (dev == ign->fb_tunnel_dev) {
net/ipv4/ip_options.c +3 -3
@@ -409,7 +409,7 @@ int ip_options_compile(struct net *net, optptr[2 ] +=8 ;break ;default : -if (!skb && !capable (CAP_NET_RAW )) { +if (!skb && !ns_capable (net->user_ns,CAP_NET_RAW )) { pp_ptr = optptr +3 ; goto error; }
@@ -445,7 +445,7 @@ int ip_options_compile(struct net *net, opt->router_alert = optptr - iph;break ;case IPOPT_CIPSO : -if ((!skb && !capable (CAP_NET_RAW )) || opt->cipso) { +if ((!skb && !ns_capable (net->user_ns,CAP_NET_RAW )) || opt->cipso) { pp_ptr = optptr; goto error; }
@@ -458,7 +458,7 @@ int ip_options_compile(struct net *net,case IPOPT_SEC :case IPOPT_SID :default : -if (!skb && !capable (CAP_NET_RAW )) { +if (!skb && !ns_capable (net->user_ns,CAP_NET_RAW )) { pp_ptr = optptr; goto error; }
net/ipv4/ip_sockglue.c +3 -2
@@ -980,13 +980,14 @@ mc_msf_out:case IP_IPSEC_POLICY :case IP_XFRM_POLICY : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))break ; err =xfrm_user_policy (sk, optname, optval, optlen);break ;case IP_TRANSPARENT : -if (!!val && !capable (CAP_NET_RAW ) && !capable (CAP_NET_ADMIN )) { +if (!!val && !ns_capable (sock_net (sk)->user_ns,CAP_NET_RAW ) && + !ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN )) { err = -EPERM ;break ; }
net/ipv4/ip_vti.c +2 -2
@@ -497,7 +497,7 @@ vti_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)case SIOCADDTUNNEL :case SIOCCHGTUNNEL : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) goto done; err = -EFAULT ;
@@ -562,7 +562,7 @@ vti_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)case SIOCDELTUNNEL : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) goto done;if (dev == ipn->fb_tunnel_dev) {
net/ipv4/ipip.c +2 -2
@@ -664,7 +664,7 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)case SIOCADDTUNNEL :case SIOCCHGTUNNEL : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) goto done; err = -EFAULT ;
@@ -724,7 +724,7 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)case SIOCDELTUNNEL : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) goto done;if (dev == ipn->fb_tunnel_dev) {
net/ipv4/ipmr.c +1 -1
@@ -1213,7 +1213,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsiif (optname !=MRT_INIT ) {if (sk !=rcu_access_pointer (mrt->mroute_sk) && - !capable (CAP_NET_ADMIN )) + !ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EACCES ; }
net/ipv4/netfilter/arp_tables.c +4 -4
@@ -1533,7 +1533,7 @@ static int compat_do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, {int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))return -EPERM ;switch (cmd) {
@@ -1677,7 +1677,7 @@ static int compat_do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, {int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))return -EPERM ;switch (cmd) {
@@ -1698,7 +1698,7 @@ static int do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned {int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))return -EPERM ;switch (cmd) {
@@ -1722,7 +1722,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len {int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))return -EPERM ;switch (cmd) {
net/ipv4/netfilter/ip_tables.c +4 -4
@@ -1846,7 +1846,7 @@ compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, {int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))return -EPERM ;switch (cmd) {
@@ -1961,7 +1961,7 @@ compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) {int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))return -EPERM ;switch (cmd) {
@@ -1983,7 +1983,7 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) {int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))return -EPERM ;switch (cmd) {
@@ -2008,7 +2008,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) {int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))return -EPERM ;switch (cmd) {
net/ipv4/tcp.c +1 -1
@@ -2303,7 +2303,7 @@ void tcp_sock_destruct(struct sock *sk)static inline bool tcp_can_repair_sock (const struct sock *sk) { -return capable (CAP_NET_ADMIN ) && +return ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ) && ((1 << sk->sk_state) & (TCPF_CLOSE |TCPF_ESTABLISHED )); }
net/ipv4/tcp_cong.c +2 -1
@@ -259,7 +259,8 @@ int tcp_set_congestion_control(struct sock *sk, const char *name)if (!ca) err = -ENOENT ; -else if (!((ca->flags &TCP_CONG_NON_RESTRICTED ) ||capable (CAP_NET_ADMIN ))) +else if (!((ca->flags &TCP_CONG_NON_RESTRICTED ) || +ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))) err = -EPERM ;else if (!try_module_get (ca->owner))
Signature · 1 line
1.7.5.4
PATCH 11/17 net: Allow userns root to control ipv6
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Allow an unpriviled user who has created a user namespace, and then created a network namespace to effectively use the new network namespace, by reducing capable(CAP_NET_ADMIN) and capable(CAP_NET_RAW) calls to be ns_capable(net->user_ns, CAP_NET_ADMIN), or capable(net->user_ns, CAP_NET_RAW) calls.
Settings that merely control a single network device are allowed. Either the network device is a logical network device where restrictions make no difference or the network device is hardware NIC that has been explicity moved from the initial network namespace.
In general policy and network stack state changes are allowed while resource control is left unchanged.
Allow the SIOCSIFADDR ioctl to add ipv6 addresses. Allow the SIOCDIFADDR ioctl to delete ipv6 addresses. Allow the SIOCADDRT ioctl to add ipv6 routes. Allow the SIOCDELRT ioctl to delete ipv6 routes.
Allow creation of ipv6 raw sockets.
Allow setting the IPV6_JOIN_ANYCAST socket option.
Allow setting the IPV6_FL_A_RENEW parameter of the IPV6_FLOWLABEL_MGR socket option.
Allow setting the IPV6_TRANSPARENT socket option. Allow setting the IPV6_HOPOPTS socket option. Allow setting the IPV6_RTHDRDSTOPTS socket option. Allow setting the IPV6_DSTOPTS socket option. Allow setting the IPV6_IPSEC_POLICY socket option. Allow setting the IPV6_XFRM_POLICY socket option.
Allow sending packets with the IPV6_2292HOPOPTS control message. Allow sending packets with the IPV6_2292DSTOPTS control message. Allow sending packets with the IPV6_RTHDRDSTOPTS control message.
Allow setting the multicast routing socket options on non multicast routing sockets.
Allow the SIOCADDTUNNEL, SIOCCHGTUNNEL, and SIOCDELTUNNEL ioctls for setting up, changing and deleting tunnels over ipv6.
Allow the SIOCADDTUNNEL, SIOCCHGTUNNEL, SIOCDELTUNNEL ioctls for setting up, changing and deleting ipv6 over ipv4 tunnels.
Allow the SIOCADDPRL, SIOCDELPRL, SIOCCHGPRL ioctls for adding, deleting, and changing the potential router list for ISATAP tunnels.
--- net/ipv6/addrconf.c | 4 ++-- net/ipv6/af_inet6.c | 3 ++- net/ipv6/anycast.c | 2 +- net/ipv6/datagram.c | 6 +++--- net/ipv6/ip6_flowlabel.c | 3 ++- net/ipv6/ip6_gre.c | 4 ++-- net/ipv6/ip6_tunnel.c | 4 ++-- net/ipv6/ip6mr.c | 2 +- net/ipv6/ipv6_sockglue.c | 7 ++++--- net/ipv6/netfilter/ip6_tables.c | 8 ++++---- net/ipv6/route.c | 2 +- net/ipv6/sit.c | 8 ++++---- 12 files changed, 28 insertions(+), 25 deletions(-)
net/ipv6/addrconf.c +2 -2
@@ -2268,7 +2268,7 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg)struct in6_ifreq ireq;int err; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;if (copy_from_user (&ireq, arg,sizeof (struct in6_ifreq )))
@@ -2287,7 +2287,7 @@ int addrconf_del_ifaddr(struct net *net, void __user *arg)struct in6_ifreq ireq;int err; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;if (copy_from_user (&ireq, arg,sizeof (struct in6_ifreq )))
net/ipv6/af_inet6.c +2 -1
@@ -160,7 +160,8 @@ lookup_protocol: } err = -EPERM ; -if (sock->type ==SOCK_RAW && !kern && !capable (CAP_NET_RAW )) +if (sock->type ==SOCK_RAW && !kern && + !ns_capable (net->user_ns,CAP_NET_RAW )) goto out_rcu_unlock; sock->ops = answer->ops;
net/ipv6/anycast.c +1 -1
@@ -64,7 +64,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)int ishost = !net->ipv6.devconf_all->forwarding;int err =0 ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;if (ipv6_addr_is_multicast (addr))return -EINVAL ;
net/ipv6/datagram.c +3 -3
@@ -701,7 +701,7 @@ int datagram_send_ctl(struct net *net, struct sock *sk, err = -EINVAL ; goto exit_f; } -if (!capable (CAP_NET_RAW )) { +if (!ns_capable (net->user_ns,CAP_NET_RAW )) { err = -EPERM ; goto exit_f; }
@@ -721,7 +721,7 @@ int datagram_send_ctl(struct net *net, struct sock *sk, err = -EINVAL ; goto exit_f; } -if (!capable (CAP_NET_RAW )) { +if (!ns_capable (net->user_ns,CAP_NET_RAW )) { err = -EPERM ; goto exit_f; }
@@ -746,7 +746,7 @@ int datagram_send_ctl(struct net *net, struct sock *sk, err = -EINVAL ; goto exit_f; } -if (!capable (CAP_NET_RAW )) { +if (!ns_capable (net->user_ns,CAP_NET_RAW )) { err = -EPERM ; goto exit_f; }
net/ipv6/ip6_flowlabel.c +2 -1
@@ -519,7 +519,8 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) }read_unlock_bh (&ip6_sk_fl_lock); -if (freq.flr_share ==IPV6_FL_S_NONE &&capable (CAP_NET_ADMIN )) { +if (freq.flr_share ==IPV6_FL_S_NONE && +ns_capable (net->user_ns,CAP_NET_ADMIN )) { fl =fl_lookup (net, freq.flr_label);if (fl) { err =fl6_renew (fl, freq.flr_linger, freq.flr_expires);
net/ipv6/ip6_gre.c +2 -2
@@ -1161,7 +1161,7 @@ static int ip6gre_tunnel_ioctl(struct net_device *dev,case SIOCADDTUNNEL :case SIOCCHGTUNNEL : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) goto done; err = -EFAULT ;
@@ -1209,7 +1209,7 @@ static int ip6gre_tunnel_ioctl(struct net_device *dev,case SIOCDELTUNNEL : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) goto done;if (dev == ign->fb_tunnel_dev) {
net/ipv6/ip6_tunnel.c +2 -2
@@ -1325,7 +1325,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)case SIOCADDTUNNEL :case SIOCCHGTUNNEL : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))break ; err = -EFAULT ;if (copy_from_user (&p, ifr->ifr_ifru.ifru_data,sizeof (p)))
@@ -1362,7 +1362,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)break ;case SIOCDELTUNNEL : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))break ;if (dev == ip6n->fb_tnl_dev) {
net/ipv6/ip6mr.c +1 -1
@@ -1583,7 +1583,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsreturn -ENOENT ;if (optname !=MRT6_INIT ) { -if (sk != mrt->mroute6_sk && !capable (CAP_NET_ADMIN )) +if (sk != mrt->mroute6_sk && !ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EACCES ; }
net/ipv6/ipv6_sockglue.c +4 -3
@@ -343,7 +343,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,break ;case IPV6_TRANSPARENT : -if (valbool && !capable (CAP_NET_ADMIN ) && !capable (CAP_NET_RAW )) { +if (valbool && !ns_capable (net->user_ns,CAP_NET_ADMIN ) && + !ns_capable (net->user_ns,CAP_NET_RAW )) { retv = -EPERM ;break ; }
@@ -381,7 +382,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,/* hop-by-hop / destination options are privileged option */ retv = -EPERM ; -if (optname !=IPV6_RTHDR && !capable (CAP_NET_RAW )) +if (optname !=IPV6_RTHDR && !ns_capable (net->user_ns,CAP_NET_RAW ))break ; opt = ipv6_renew_options(sk, np->opt, optname,
@@ -754,7 +755,7 @@ done:case IPV6_IPSEC_POLICY :case IPV6_XFRM_POLICY : retv = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))break ; retv =xfrm_user_policy (sk, optname, optval, optlen);break ;
net/ipv6/netfilter/ip6_tables.c +4 -4
@@ -1856,7 +1856,7 @@ compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, {int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))return -EPERM ;switch (cmd) {
@@ -1971,7 +1971,7 @@ compat_do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) {int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))return -EPERM ;switch (cmd) {
@@ -1993,7 +1993,7 @@ do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) {int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))return -EPERM ;switch (cmd) {
@@ -2018,7 +2018,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) {int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))return -EPERM ;switch (cmd) {
net/ipv6/route.c +1 -1
@@ -1987,7 +1987,7 @@ int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg)switch (cmd) {case SIOCADDRT :/* Add a route */ case SIOCDELRT :/* Delete a route */ -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ; err =copy_from_user (&rtmsg, arg,sizeof (struct in6_rtmsg ));
net/ipv6/sit.c +4 -4
@@ -966,7 +966,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)case SIOCADDTUNNEL :case SIOCCHGTUNNEL : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) goto done; err = -EFAULT ;
@@ -1025,7 +1025,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)case SIOCDELTUNNEL : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) goto done;if (dev == sitn->fb_tunnel_dev) {
@@ -1058,7 +1058,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)case SIOCDELPRL :case SIOCCHGPRL : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) goto done; err = -EINVAL ;if (dev == sitn->fb_tunnel_dev)
@@ -1087,7 +1087,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)case SIOCCHG6RD :case SIOCDEL6RD : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) goto done; err = -EFAULT ;
Signature · 1 line
1.7.5.4
PATCH 12/17 net: Allow userns root to control llc, netfilter, netlink, packet, and xfrm
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Allow an unpriviled user who has created a user namespace, and then created a network namespace to effectively use the new network namespace, by reducing capable(CAP_NET_ADMIN) and capable(CAP_NET_RAW) calls to be ns_capable(net->user_ns, CAP_NET_ADMIN), or capable(net->user_ns, CAP_NET_RAW) calls.
Allow creation of af_key sockets.
Allow creation of llc sockets.
Allow creation of af_packet sockets.
Allow sending xfrm netlink control messages.
Allow binding to netlink multicast groups.
Allow sending to netlink multicast groups.
Allow adding and dropping netlink multicast groups. Allow sending to all netlink multicast groups and port ids.
Allow reading the netfilter SO_IP_SET socket option. Allow sending netfilter netlink messages.
Allow setting and getting ip_vs netfilter socket options.
--- net/key/af_key.c | 2 +- net/llc/af_llc.c | 2 +- net/netfilter/ipset/ip_set_core.c | 2 +- net/netfilter/ipvs/ip_vs_ctl.c | 4 ++-- net/netfilter/nfnetlink.c | 2 +- net/netlink/af_netlink.c | 2 +- net/packet/af_packet.c | 2 +- net/xfrm/xfrm_user.c | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-)
net/key/af_key.c +1 -1
@@ -141,7 +141,7 @@ static int pfkey_create(struct net *net, struct socket *sock, int protocol,struct sock *sk;int err; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;if (sock->type !=SOCK_RAW )return -ESOCKTNOSUPPORT ;
net/llc/af_llc.c +1 -1
@@ -160,7 +160,7 @@ static int llc_ui_create(struct net *net, struct socket *sock, int protocol,struct sock *sk;int rc = -ESOCKTNOSUPPORT ; -if (!capable (CAP_NET_RAW )) +if (!ns_capable (net->user_ns,CAP_NET_RAW ))return -EPERM ;if (!net_eq (net, &init_net))
net/netfilter/ipset/ip_set_core.c +1 -1
@@ -1643,7 +1643,7 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)void *data;int copylen = *len, ret =0 ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))return -EPERM ;if (optval !=SO_IP_SET )return -EBADF ;
net/netfilter/ipvs/ip_vs_ctl.c +2 -2
@@ -2339,7 +2339,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)struct ip_vs_dest_user_kern udest;struct netns_ipvs *ipvs =net_ipvs (net); -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))return -EPERM ;if (cmd <IP_VS_BASE_CTL || cmd >IP_VS_SO_SET_MAX )
@@ -2632,7 +2632,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)struct netns_ipvs *ipvs =net_ipvs (net);BUG_ON (!net); -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN ))return -EPERM ;if (cmd <IP_VS_BASE_CTL || cmd >IP_VS_SO_GET_MAX )
net/netfilter/nfnetlink.c +1 -1
@@ -138,7 +138,7 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)const struct nfnetlink_subsystem *ss;int type, err; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;/* All the messages must at least contain nfgenmsg */
net/netlink/af_netlink.c +1 -1
@@ -612,7 +612,7 @@ retry:static inline int netlink_capable (const struct socket *sock,unsigned int flag) {return (nl_table[sock->sk->sk_protocol].flags & flag) || -capable (CAP_NET_ADMIN ); +ns_capable (sock_net (sock->sk)->user_ns,CAP_NET_ADMIN ); } static void
net/packet/af_packet.c +1 -1
@@ -2478,7 +2478,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,__be16 proto = (__force __be16 )protocol;/* weird, but documented */ int err; -if (!capable (CAP_NET_RAW )) +if (!ns_capable (net->user_ns,CAP_NET_RAW ))return -EPERM ;if (sock->type !=SOCK_DGRAM && sock->type !=SOCK_RAW && sock->type !=SOCK_PACKET )
net/xfrm/xfrm_user.c +1 -1
@@ -2349,7 +2349,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) link = &xfrm_dispatch[type];/* All operations require privileges, even GET */ -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ; if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) ||
Signature · 1 line
1.7.5.4
PATCH 13/17 net: Allow userns root to control the network bridge code.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Allow an unpriviled user who has created a user namespace, and then created a network namespace to effectively use the new network namespace, by reducing capable(CAP_NET_ADMIN) and capable(CAP_NET_RAW) calls to be ns_capable(net->user_ns, CAP_NET_ADMIN), or capable(net->user_ns, CAP_NET_RAW) calls.
Allow setting bridge paramters via sysfs.
Allow all of the bridge ioctls:BRCTL_ADD_IFBRCTL_DEL_IFBRCTL_SET_BRDIGE_FORWARD_DELAYBRCTL_SET_BRIDGE_HELLO_TIMEBRCTL_SET_BRIDGE_MAX_AGEBRCTL_SET_BRIDGE_AGING_TIMEBRCTL_SET_BRIDGE_STP_STATEBRCTL_SET_BRIDGE_PRIORITYBRCTL_SET_PORT_PRIORITYBRCTL_SET_PATH_COSTBRCTL_ADD_BRIDGEBRCTL_DEL_BRDIGE
--- net/bridge/br_ioctl.c | 25 +++++++++++++------------ net/bridge/br_sysfs_br.c | 10 +++++----- net/bridge/br_sysfs_if.c | 2 +- 3 files changed, 19 insertions(+), 18 deletions(-)
net/bridge/br_ioctl.c +13 -12
@@ -85,13 +85,14 @@ static int get_fdb_entries(struct net_bridge *br, void __user *userbuf,/* called with RTNL */ static int add_del_if (struct net_bridge *br,int ifindex,int isadd) { +struct net *net =dev_net (br->dev);struct net_device *dev;int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ; - dev =__dev_get_by_index (dev_net (br->dev), ifindex); + dev =__dev_get_by_index (net, ifindex);if (dev ==NULL )return -EINVAL ;
@@ -178,25 +179,25 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) }case BRCTL_SET_BRIDGE_FORWARD_DELAY : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;return br_set_forward_delay (br, args[1 ]);case BRCTL_SET_BRIDGE_HELLO_TIME : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;return br_set_hello_time (br, args[1 ]);case BRCTL_SET_BRIDGE_MAX_AGE : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;return br_set_max_age (br, args[1 ]);case BRCTL_SET_AGEING_TIME : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ; br->ageing_time =clock_t_to_jiffies (args[1 ]);
@@ -236,14 +237,14 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) }case BRCTL_SET_BRIDGE_STP_STATE : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;br_stp_set_enabled (br, args[1 ]);return 0 ;case BRCTL_SET_BRIDGE_PRIORITY : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;spin_lock_bh (&br->lock);
@@ -256,7 +257,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)struct net_bridge_port *p;int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;spin_lock_bh (&br->lock);
@@ -273,7 +274,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)struct net_bridge_port *p;int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;spin_lock_bh (&br->lock);
@@ -330,7 +331,7 @@ static int old_deviceless(struct net *net, void __user *uarg) {char buf[IFNAMSIZ ]; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;if (copy_from_user (buf, (void __user *)args[1 ],IFNAMSIZ ))
@@ -360,7 +361,7 @@ int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uar {char buf[IFNAMSIZ ]; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;if (copy_from_user (buf, uarg,IFNAMSIZ ))
net/bridge/br_sysfs_br.c +5 -5
@@ -36,7 +36,7 @@ static ssize_t store_bridge_parm(struct device *d,unsigned long val;int err; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (br->dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ; val =simple_strtoul (buf, &endp,0 );
@@ -132,7 +132,7 @@ static ssize_t store_stp_state(struct device *d,char *endp;unsigned long val; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (br->dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ; val =simple_strtoul (buf, &endp,0 );
@@ -165,7 +165,7 @@ static ssize_t store_group_fwd_mask(struct device *d,char *endp;unsigned long val; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (br->dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ; val =simple_strtoul (buf, &endp,0 );
@@ -300,7 +300,7 @@ static ssize_t store_group_addr(struct device *d,unsigned int new_addr[6 ];int i; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (br->dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ; if (sscanf(buf, "%x:%x:%x:%x:%x:%x",
@@ -337,7 +337,7 @@ static ssize_t store_flush(struct device *d, {struct net_bridge *br =to_bridge (d); -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (br->dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;br_fdb_flush (br);
net/bridge/br_sysfs_if.c +1 -1
@@ -209,7 +209,7 @@ static ssize_t brport_store(struct kobject * kobj,char *endp;unsigned long val; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (p->dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ; val =simple_strtoul (buf, &endp,0 );
Signature · 1 line
1.7.5.4
PATCH 14/17 net: Allow the userns root to control vlans.
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Allow an unpriviled user who has created a user namespace, and then created a network namespace to effectively use the new network namespace, by reducing capable(CAP_NET_ADMIN) and capable(CAP_NET_RAW) calls to be ns_capable(net->user_ns, CAP_NET_ADMIN), or capable(net->user_ns, CAP_NET_RAW) calls.
Allow the vlan ioctls:SET_VLAN_INGRESS_PRIORITY_CMDSET_VLAN_EGRESS_PRIORITY_CMDSET_VLAN_FLAG_CMDSET_VLAN_NAME_TYPE_CMDADD_VLAN_CMDDEL_VLAN_CMD
--- net/8021q/vlan.c | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-)
net/8021q/vlan.c +6 -6
@@ -529,7 +529,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)switch (args.cmd) {case SET_VLAN_INGRESS_PRIORITY_CMD : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))break ; vlan_dev_set_ingress_priority(dev, args.u.skb_priority,
@@ -539,7 +539,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)case SET_VLAN_EGRESS_PRIORITY_CMD : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))break ; err = vlan_dev_set_egress_priority(dev, args.u.skb_priority,
@@ -548,7 +548,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)case SET_VLAN_FLAG_CMD : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))break ; err = vlan_dev_change_flags(dev, args.vlan_qos ? args.u.flag : 0,
@@ -557,7 +557,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)case SET_VLAN_NAME_TYPE_CMD : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))break ;if ((args.u.name_type >=0 ) && (args.u.name_type <VLAN_NAME_TYPE_HIGHEST )) {
@@ -573,14 +573,14 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)case ADD_VLAN_CMD : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))break ; err =register_vlan_device (dev, args.u.VID);break ;case DEL_VLAN_CMD : err = -EPERM ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))break ;unregister_vlan_dev (dev,NULL ); err =0 ;
Signature · 1 line
1.7.5.4
PATCH 15/17 net: Enable some sysctls that are safe for the userns root
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Enable the per device ipv4 sysctls:
net/ipv4/conf/<if>/forwarding
net/ipv4/conf/<if>/mc_forwarding
net/ipv4/conf/<if>/accept_redirects
net/ipv4/conf/<if>/secure_redirects
net/ipv4/conf/<if>/shared_media
net/ipv4/conf/<if>/rp_filter
net/ipv4/conf/<if>/send_redirects
net/ipv4/conf/<if>/accept_source_route
net/ipv4/conf/<if>/accept_local
net/ipv4/conf/<if>/src_valid_mark
net/ipv4/conf/<if>/proxy_arp
net/ipv4/conf/<if>/medium_id
net/ipv4/conf/<if>/bootp_relay
net/ipv4/conf/<if>/log_martians
net/ipv4/conf/<if>/tag
net/ipv4/conf/<if>/arp_filter
net/ipv4/conf/<if>/arp_announce
net/ipv4/conf/<if>/arp_ignore
net/ipv4/conf/<if>/arp_accept
net/ipv4/conf/<if>/arp_notify
net/ipv4/conf/<if>/proxy_arp_pvlan
net/ipv4/conf/<if>/disable_xfrm
net/ipv4/conf/<if>/disable_policy
net/ipv4/conf/<if>/force_igmp_version
net/ipv4/conf/<if>/promote_secondaries
net/ipv4/conf/<if>/route_localnet
- Enable the global ipv4 sysctl:
net/ipv4/ip_forward
- Enable the per device ipv6 sysctls:
net/ipv6/conf/<if>/forwarding net/ipv6/conf/<if>/hop_limit net/ipv6/conf/<if>/mtu net/ipv6/conf/<if>/accept_ra net/ipv6/conf/<if>/accept_redirects net/ipv6/conf/<if>/autoconf net/ipv6/conf/<if>/dad_transmits net/ipv6/conf/<if>/router_solicitations net/ipv6/conf/<if>/router_solicitation_interval net/ipv6/conf/<if>/router_solicitation_delay net/ipv6/conf/<if>/force_mld_version net/ipv6/conf/<if>/use_tempaddr net/ipv6/conf/<if>/temp_valid_lft net/ipv6/conf/<if>/temp_prefered_lft net/ipv6/conf/<if>/regen_max_retry net/ipv6/conf/<if>/max_desync_factor net/ipv6/conf/<if>/max_addresses net/ipv6/conf/<if>/accept_ra_defrtr net/ipv6/conf/<if>/accept_ra_pinfo net/ipv6/conf/<if>/accept_ra_rtr_pref net/ipv6/conf/<if>/router_probe_interval net/ipv6/conf/<if>/accept_ra_rt_info_max_plen net/ipv6/conf/<if>/proxy_ndp net/ipv6/conf/<if>/accept_source_route net/ipv6/conf/<if>/optimistic_dad net/ipv6/conf/<if>/mc_forwarding net/ipv6/conf/<if>/disable_ipv6 net/ipv6/conf/<if>/accept_dad net/ipv6/conf/<if>/force_tllao
- Enable the global ipv6 sysctls:
net/ipv6/bindv6only
net/ipv6/icmp/ratelimit
--- net/ipv4/devinet.c | 8 -------- net/ipv6/addrconf.c | 4 ---- net/ipv6/icmp.c | 7 +------ net/ipv6/sysctl_net_ipv6.c | 4 ---- 4 files changed, 1 insertions(+), 22 deletions(-)
net/ipv4/devinet.c +0 -8
@@ -1643,10 +1643,6 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name, t->devinet_vars[i].extra2 = net; } -/* Don't export sysctls to unprivileged users */ -if (net->user_ns != &init_user_ns) - t->devinet_vars[0 ].procname =NULL ; -snprintf (path,sizeof (path),"net/ipv4/conf/%s" , dev_name); t->sysctl_header =register_net_sysctl (net, path, t->devinet_vars);
@@ -1732,10 +1728,6 @@ static __net_init int devinet_init_net(struct net *net) tbl[0 ].data = &all->data[IPV4_DEVCONF_FORWARDING -1 ]; tbl[0 ].extra1 = all; tbl[0 ].extra2 = net; - -/* Don't export sysctls to unprivileged users */ -if (net->user_ns != &init_user_ns) - tbl[0 ].procname =NULL ;#endif }
net/ipv6/addrconf.c +0 -4
@@ -4588,10 +4588,6 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name, t->addrconf_vars[i].extra2 = net; } -/* Don't export sysctls to unprivileged users */ -if (net->user_ns != &init_user_ns) - t->addrconf_vars[0 ].procname =NULL ; -snprintf (path,sizeof (path),"net/ipv6/conf/%s" , dev_name); t->sysctl_header =register_net_sysctl (net, path, t->addrconf_vars);
net/ipv6/icmp.c +1 -6
@@ -967,14 +967,9 @@ struct ctl_table * __net_init ipv6_icmp_sysctl_init(struct net *net)sizeof (ipv6_icmp_table_template), GFP_KERNEL); -if (table) { +if (table) table[0 ].data = &net->ipv6.sysctl.icmpv6_time; -/* Don't export sysctls to unprivileged users */ -if (net->user_ns != &init_user_ns) - table[0 ].procname =NULL ; - } - return table; }#endif
net/ipv6/sysctl_net_ipv6.c +0 -4
@@ -52,10 +52,6 @@ static int __net_init ipv6_sysctl_net_init(struct net *net) goto out; ipv6_table[0 ].data = &net->ipv6.sysctl.bindv6only; -/* Don't export sysctls to unprivileged users */ -if (net->user_ns != &init_user_ns) - ipv6_table[0 ].procname =NULL ; - ipv6_route_table =ipv6_route_sysctl_init (net);if (!ipv6_route_table) goto out_ipv6_table;
Signature · 1 line
1.7.5.4
PATCH 16/17 net: Enable a userns root rtnl calls that are safe for unprivilged users
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
- Only allow moving network devices to network namespaces you have CAP_NET_ADMIN privileges over.
- Enable creating/deleting/modifying interfaces
- Enable adding/deleting addresses
- Enable adding/setting/deleting neighbour entries
- Enable adding/removing routes
- Enable adding/removing fib rules
- Enable setting the forwarding state
- Enable adding/removing ipv6 address labels
- Enable setting bridge parameter
--- net/bridge/br_netlink.c | 3 --- net/core/fib_rules.c | 6 ------ net/core/neighbour.c | 9 --------- net/core/rtnetlink.c | 13 ++++--------- net/ipv4/devinet.c | 6 ------ net/ipv4/fib_frontend.c | 6 ------ net/ipv6/addrconf.c | 6 ------ net/ipv6/addrlabel.c | 3 --- net/ipv6/route.c | 6 ------ 9 files changed, 4 insertions(+), 54 deletions(-)
net/bridge/br_netlink.c +0 -3
@@ -153,9 +153,6 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct net_bridge_port *p;u8 new_state; -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; -if (nlmsg_len (nlh) <sizeof (*ifm))return -EINVAL ;
net/core/fib_rules.c +0 -6
@@ -275,9 +275,6 @@ static int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)struct nlattr *tb[FRA_MAX +1 ];int err = -EINVAL , unresolved =0 ; -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; -if (nlh->nlmsg_len <nlmsg_msg_size (sizeof (*frh))) goto errout;
@@ -427,9 +424,6 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)struct nlattr *tb[FRA_MAX +1 ];int err = -EINVAL ; -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; -if (nlh->nlmsg_len <nlmsg_msg_size (sizeof (*frh))) goto errout;
net/core/neighbour.c +0 -9
@@ -1620,9 +1620,6 @@ static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct net_device *dev =NULL ;int err = -EINVAL ; -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; -ASSERT_RTNL ();if (nlmsg_len (nlh) <sizeof (*ndm)) goto out;
@@ -1687,9 +1684,6 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct net_device *dev =NULL ;int err; -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; -ASSERT_RTNL (); err =nlmsg_parse (nlh,sizeof (*ndm), tb,NDA_MAX ,NULL );if (err <0 )
@@ -1968,9 +1962,6 @@ static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct nlattr *tb[NDTA_MAX +1 ];int err; -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; - err =nlmsg_parse (nlh,sizeof (*ndtmsg), tb,NDTA_MAX , nl_neightbl_policy);if (err <0 )
net/core/rtnetlink.c +4 -9
@@ -1316,6 +1316,10 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, err =PTR_ERR (net); goto errout; } +if (!ns_capable (net->user_ns,CAP_NET_ADMIN )) { + err = -EPERM ; + goto errout; + } err =dev_change_net_namespace (dev, net, ifname);put_net (net);if (err)
@@ -1547,9 +1551,6 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct nlattr *tb[IFLA_MAX +1 ];char ifname[IFNAMSIZ ]; -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; - err =nlmsg_parse (nlh,sizeof (*ifm), tb,IFLA_MAX , ifla_policy);if (err <0 ) goto errout;
@@ -1593,9 +1594,6 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)int err;LIST_HEAD (list_kill); -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; - err =nlmsg_parse (nlh,sizeof (*ifm), tb,IFLA_MAX , ifla_policy);if (err <0 )return err;
@@ -1726,9 +1724,6 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct nlattr *linkinfo[IFLA_INFO_MAX +1 ];int err; -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; -#ifdef CONFIG_MODULES replay:#endif
net/ipv4/devinet.c +0 -6
@@ -538,9 +538,6 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *argASSERT_RTNL (); -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; - err =nlmsg_parse (nlh,sizeof (*ifm), tb,IFA_MAX , ifa_ipv4_policy);if (err <0 ) goto errout;
@@ -648,9 +645,6 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *argASSERT_RTNL (); -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; - ifa =rtm_to_ifaddr (net, nlh);if (IS_ERR (ifa))return PTR_ERR (ifa);
net/ipv4/fib_frontend.c +0 -6
@@ -613,9 +613,6 @@ static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arstruct fib_table *tb;int err; -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; - err =rtm_to_fib_config (net, skb, nlh, &cfg);if (err <0 ) goto errout;
@@ -638,9 +635,6 @@ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *arstruct fib_table *tb;int err; -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; - err =rtm_to_fib_config (net, skb, nlh, &cfg);if (err <0 ) goto errout;
net/ipv6/addrconf.c +0 -6
@@ -3369,9 +3369,6 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)struct in6_addr *pfx;int err; -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; - err =nlmsg_parse (nlh,sizeof (*ifm), tb,IFA_MAX , ifa_ipv6_policy);if (err <0 )return err;
@@ -3442,9 +3439,6 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)u8 ifa_flags;int err; -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; - err =nlmsg_parse (nlh,sizeof (*ifm), tb,IFA_MAX , ifa_ipv6_policy);if (err <0 )return err;
net/ipv6/addrlabel.c +0 -3
@@ -425,9 +425,6 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh,u32 label;int err =0 ; -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; - err =nlmsg_parse (nlh,sizeof (*ifal), tb,IFAL_MAX , ifal_policy);if (err <0 )return err;
net/ipv6/route.c +0 -6
@@ -2336,9 +2336,6 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *astruct fib6_config cfg;int err; -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; - err =rtm_to_fib6_config (skb, nlh, &cfg);if (err <0 )return err;
@@ -2351,9 +2348,6 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *astruct fib6_config cfg;int err; -if (!capable (CAP_NET_ADMIN )) -return -EPERM ; - err =rtm_to_fib6_config (skb, nlh, &cfg);if (err <0 )return err;
Signature · 1 line
1.7.5.4
PATCH 17/17 net: Make CAP_NET_BIND_SERVICE per user namespace
In reply to a message not in the archiveFrom: "Eric W. Biederman" <ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]>
Allow privileged users in any user namespace to bind to privileged sockets in network namespaces they control.
--- net/ipv4/af_inet.c | 6 ++++-- net/ipv6/af_inet6.c | 2 +- net/sctp/socket.c | 8 +++++--- 3 files changed, 10 insertions(+), 6 deletions(-)
net/ipv4/af_inet.c +4 -2
@@ -474,6 +474,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;struct sock *sk = sock->sk;struct inet_sock *inet =inet_sk (sk); +struct net *net =sock_net (sk);unsigned short snum;int chk_addr_ret;int err;
@@ -497,7 +498,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) goto out; } - chk_addr_ret =inet_addr_type (sock_net (sk), addr->sin_addr.s_addr); + chk_addr_ret =inet_addr_type (net, addr->sin_addr.s_addr);/* Not specified by any standard per-se, however it breaks too * many applications when removed. It is unfortunate since
@@ -517,7 +518,8 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) snum =ntohs (addr->sin_port); err = -EACCES ; -if (snum && snum <PROT_SOCK && !capable (CAP_NET_BIND_SERVICE )) +if (snum && snum <PROT_SOCK && + !ns_capable (net->user_ns,CAP_NET_BIND_SERVICE )) goto out;/* We keep a pair of addresses. rcv_saddr is the one
net/ipv6/af_inet6.c +1 -1
@@ -283,7 +283,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)return -EINVAL ; snum =ntohs (addr->sin6_port); -if (snum && snum <PROT_SOCK && !capable (CAP_NET_BIND_SERVICE )) +if (snum && snum <PROT_SOCK && !ns_capable (net->user_ns,CAP_NET_BIND_SERVICE ))return -EACCES ;lock_sock (sk);
net/sctp/socket.c +5 -3
@@ -336,6 +336,7 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,/* Bind a local address either to an endpoint or to an association. */ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) { +struct net *net =sock_net (sk);struct sctp_sock *sp =sctp_sk (sk);struct sctp_endpoint *ep = sp->ep;struct sctp_bind_addr *bp = &ep->base.bind_addr;
@@ -379,7 +380,8 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) } } -if (snum && snum <PROT_SOCK && !capable (CAP_NET_BIND_SERVICE )) +if (snum && snum <PROT_SOCK && + !ns_capable (net->user_ns,CAP_NET_BIND_SERVICE ))return -EACCES ;/* See if the address matches any of the addresses we may have
@@ -1162,7 +1164,7 @@ static int __sctp_connect(struct sock* sk,* be permitted to open new associations. */ if (ep->base.bind_addr.port <PROT_SOCK && - !capable (CAP_NET_BIND_SERVICE )) { + !ns_capable (net->user_ns,CAP_NET_BIND_SERVICE )) { err = -EACCES ; goto out_free; }
@@ -1791,7 +1793,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,* associations. */ if (ep->base.bind_addr.port <PROT_SOCK && - !capable (CAP_NET_BIND_SERVICE )) { + !ns_capable (net->user_ns,CAP_NET_BIND_SERVICE )) { err = -EACCES ; goto out_unlock; }
Signature · 1 line
1.7.5.4
PATCH 2/17 userns: make each net (net_ns) belong to a user_ns
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
The user namespace which creates a new network namespace owns that namespace and all resources created in it. This way we can target capability checks for privileged operations against network resources to the user_ns which created the network namespace in which the resource lives. Privilege to the user namespace which owns the network namespace, or any parent user namespace thereof, provides the same privilege to the network resource.
This patch is reworked from a version originally by Serge E. Hallyn <[email protected]>
--- include/net/net_namespace.h | 9 +++++++-- kernel/nsproxy.c | 2 +- net/core/net_namespace.c | 16 ++++++++++++---- 3 files changed, 20 insertions(+), 7 deletions(-)
include/net/net_namespace.h +7 -2
@@ -23,6 +23,7 @@#endif #include <net/netns/xfrm.h> +struct user_namespace ;struct proc_dir_entry ;struct net_device ;struct sock ;
@@ -53,6 +54,8 @@ struct net {struct list_head cleanup_list;/* namespaces on death row */ struct list_head exit_list;/* Use only net_mutex */ +struct user_namespace *user_ns;/* Owning user namespace */ +struct proc_dir_entry *proc_net;struct proc_dir_entry *proc_net_stat;
@@ -127,12 +130,14 @@ struct net {extern struct net init_net;#ifdef CONFIG_NET_NS -extern struct net *copy_net_ns (unsigned long flags,struct net *net_ns); +extern struct net *copy_net_ns (unsigned long flags, +struct user_namespace *user_ns,struct net *old_net);#else /* CONFIG_NET_NS */ #include <linux/sched.h> #include <linux/nsproxy.h> -static inline struct net *copy_net_ns (unsigned long flags,struct net *old_net) +static inline struct net *copy_net_ns (unsigned long flags, +struct user_namespace *user_ns,struct net *old_net) {if (flags &CLONE_NEWNET )return ERR_PTR (-EINVAL );
kernel/nsproxy.c +1 -1
@@ -90,7 +90,7 @@ static struct nsproxy *create_new_namespaces(unsigned long flags, goto out_pid; } - new_nsp->net_ns =copy_net_ns (flags, tsk->nsproxy->net_ns); + new_nsp->net_ns =copy_net_ns (flags,task_cred_xxx (tsk, user_ns), tsk->nsproxy->net_ns);if (IS_ERR (new_nsp->net_ns)) { err =PTR_ERR (new_nsp->net_ns); goto out_net;
net/core/net_namespace.c +12 -4
@@ -13,6 +13,7 @@#include <linux/proc_fs.h> #include <linux/file.h> #include <linux/export.h> +#include <linux/user_namespace.h> #include <net/net_namespace.h> #include <net/netns/generic.h>
@@ -145,7 +146,7 @@ static void ops_free_list(const struct pernet_operations *ops,/* * setup_net runs the initializers for the network namespace object. */ -static __net_init int setup_net (struct net *net) +static __net_init int setup_net (struct net *net,struct user_namespace *user_ns) {/* Must be called with net_mutex held */ const struct pernet_operations *ops, *saved_ops;
@@ -155,6 +156,7 @@ static __net_init int setup_net(struct net *net)atomic_set (&net->count,1 );atomic_set (&net->passive,1 ); net->dev_base_seq =1 ; + net->user_ns = user_ns;#ifdef NETNS_REFCNT_DEBUG atomic_set (&net->use_count,0 );
@@ -232,7 +234,8 @@ void net_drop_ns(void *p)net_free (ns); } -struct net *copy_net_ns (unsigned long flags,struct net *old_net) +struct net *copy_net_ns (unsigned long flags, +struct user_namespace *user_ns,struct net *old_net) {struct net *net;int rv;
@@ -243,8 +246,11 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net) net =net_alloc ();if (!net)return ERR_PTR (-ENOMEM ); + +get_user_ns (user_ns); +mutex_lock (&net_mutex); - rv =setup_net (net); + rv =setup_net (net, user_ns);if (rv ==0 ) {rtnl_lock ();list_add_tail_rcu (&net->list, &net_namespace_list);
@@ -252,6 +258,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net) }mutex_unlock (&net_mutex);if (rv <0 ) { +put_user_ns (user_ns);net_drop_ns (net);return ERR_PTR (rv); }
@@ -308,6 +315,7 @@ static void cleanup_net(struct work_struct *work)/* Finally it is safe to free my network namespace structure */ list_for_each_entry_safe (net, tmp, &net_exit_list, exit_list) {list_del_init (&net->exit_list); +put_user_ns (net->user_ns);net_drop_ns (net); } }
@@ -395,7 +403,7 @@ static int __init net_ns_init(void)rcu_assign_pointer (init_net.gen, ng);mutex_lock (&net_mutex); -if (setup_net (&init_net)) +if (setup_net (&init_net, &init_user_ns))panic ("Could not setup the initial network namespace" );rtnl_lock ();
Signature · 1 line
1.7.5.4
PATCH 9/17 net: Allow userns root control of the core of the network stack.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Allow an unpriviled user who has created a user namespace, and then created a network namespace to effectively use the new network namespace, by reducing capable(CAP_NET_ADMIN) and capable(CAP_NET_RAW) calls to be ns_capable(net->user_ns, CAP_NET_ADMIN), or capable(net->user_ns, CAP_NET_RAW) calls.
Settings that merely control a single network device are allowed. Either the network device is a logical network device where restrictions make no difference or the network device is hardware NIC that has been explicity moved from the initial network namespace.
In general policy and network stack state changes are allowed while resource control is left unchanged.
Allow ethtool ioctls.
Allow binding to network devices.
Allow setting the socket mark.
Allow setting the socket priority.
Allow setting the network device alias via sysfs. Allow setting the mtu via sysfs.
Allow changing the network device flags via sysfs. Allow setting the network device group via sysfs.
Allow the following network device ioctls.
SIOCGMIIPHY
SIOCGMIIREG
SIOCSIFNAME
SIOCSIFFLAGS
SIOCSIFMETRIC
SIOCSIFMTU
SIOCSIFHWADDR
SIOCSIFSLAVE
SIOCADDMULTI
SIOCDELMULTI
SIOCSIFHWBROADCAST
SIOCSMIIREG
SIOCBONDENSLAVE
SIOCBONDRELEASE
SIOCBONDSETHWADDR
SIOCBONDCHANGEACTIVE
SIOCBRADDIF
SIOCBRDELIF
SIOCSHWTSTAMP
--- net/core/dev.c | 17 +++++++++++++---- net/core/ethtool.c | 2 +- net/core/net-sysfs.c | 15 ++++++++++----- net/core/sock.c | 7 ++++--- 4 files changed, 28 insertions(+), 13 deletions(-)
net/core/dev.c +13 -4
@@ -5200,7 +5200,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)case SIOCGMIIPHY :case SIOCGMIIREG :case SIOCSIFNAME : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;dev_load (net, ifr.ifr_name);rtnl_lock ();
@@ -5221,16 +5221,25 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)* - require strict serialization. * - do not return a value */ +case SIOCSIFMAP : +case SIOCSIFTXQLEN : +if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +/* fall through */ +/* +* These ioctl calls: +* - require local superuser power. +* - require strict serialization. +* - do not return a value +*/ case SIOCSIFFLAGS :case SIOCSIFMETRIC :case SIOCSIFMTU : -case SIOCSIFMAP :case SIOCSIFHWADDR :case SIOCSIFSLAVE :case SIOCADDMULTI :case SIOCDELMULTI :case SIOCSIFHWBROADCAST : -case SIOCSIFTXQLEN :case SIOCSMIIREG :case SIOCBONDENSLAVE :case SIOCBONDRELEASE :
@@ -5239,7 +5248,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)case SIOCBRADDIF :case SIOCBRDELIF :case SIOCSHWTSTAMP : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;/* fall through */ case SIOCBONDSLAVEINFOQUERY :
net/core/ethtool.c +1 -1
@@ -1460,7 +1460,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)case ETHTOOL_GEEE :break ;default : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ; }
net/core/net-sysfs.c +10 -5
@@ -73,11 +73,12 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len, int (*set)(struct net_device *, unsigned long)) { - struct net_device *net = to_net_dev(dev); + struct net_device *netdev = to_net_dev(dev); +struct net *net =dev_net (netdev);unsigned long new;int ret = -EINVAL ; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ; ret =kstrtoul (buf,0 , &new);
@@ -87,8 +88,8 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,if (!rtnl_trylock ())return restart_syscall (); -if (dev_isalive (net)) { -if ((ret = (*set)(net, new)) ==0 ) +if (dev_isalive (netdev)) { +if ((ret = (*set)(netdev, new)) ==0 ) ret = len; }rtnl_unlock ();
@@ -264,6 +265,9 @@ static ssize_t store_tx_queue_len(struct device *dev,struct device_attribute *attr, const char *buf, size_t len) { + if (!capable(CAP_NET_ADMIN)) + return -EPERM; +return netdev_store (dev, attr, buf, len, change_tx_queue_len); }
@@ -271,10 +275,11 @@ static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) {struct net_device *netdev =to_net_dev (dev); +struct net *net =dev_net (netdev);size_t count = len;ssize_t ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;/* ignore trailing newline */
net/core/sock.c +4 -3
@@ -515,7 +515,7 @@ static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen)/* Sorry... */ ret = -EPERM ; -if (!capable (CAP_NET_RAW )) +if (!ns_capable (net->user_ns,CAP_NET_RAW )) goto out; ret = -EINVAL ;
@@ -696,7 +696,8 @@ set_rcvbuf:break ;case SO_PRIORITY : -if ((val >=0 && val <=6 ) ||capable (CAP_NET_ADMIN )) +if ((val >=0 && val <=6 ) || +ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN )) sk->sk_priority = val;else ret = -EPERM ;
@@ -813,7 +814,7 @@ set_rcvbuf:clear_bit (SOCK_PASSSEC , &sock->flags);break ;case SO_MARK : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (sock_net (sk)->user_ns,CAP_NET_ADMIN )) ret = -EPERM ;else sk->sk_mark = val;
Signature · 1 line
1.7.5.4
A message that is not in the archive (sent off-list or not yet received): 1353070992-5552-9-git-send-email-ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected]
Re: [PATCH net-next 09/17] net: Allow userns root control of the core of the network stack.
net/core/net-sysfs.c static ssize_t store_tx_queue_len(struct device *dev, · line 271
Quoted 4 lines · Eric W. Biederman
net/core/net-sysfs.c +3
-0+if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +return netdev_store (dev, attr, buf, len, change_tx_queue_len);
You mean ns_capable here?
A message that is not in the archive (sent off-list or not yet received): [email protected]
Re: [PATCH net-next 09/17] net: Allow userns root control of the core of the network stack.
Quoted 7 lines · Glauber Costa
net/core/net-sysfs.c static ssize_t store_tx_queue_len(struct device *dev, · line 271
Quoted 4 lines · Eric W. Biederman
net/core/net-sysfs.c +3
-0+if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +return netdev_store (dev, attr, buf, len, change_tx_queue_len);You mean
ns_capablehere?
No. There I meant capable.
I deliberately call capable here because I don't understand what the tx_queue_len well enough to be certain it is safe to relax that check to be just ns_capable.
My get feel is that allowing an unprivileged user to be able to arbitrarily change the tx_queue_len on a networking device would be a nice way to allow queuing as many network packets as you would like with kernel memory and DOSing the machine.
So since with a quick read of the code I could not convince myself it was safe to allow unprivilged users to change tx_queue_len I left it protected by capable. While at the same time I relaxed the check in netdev_store to be ns_capable.
Eric
Re: [PATCH net-next 09/17] net: Allow userns root control of the core of the network stack.
In reply to Glauber CostaQuoted 7 lines · Glauber Costa
net/core/net-sysfs.c static ssize_t store_tx_queue_len(struct device *dev, · line 271
Quoted 4 lines · Eric W. Biederman
net/core/net-sysfs.c +3
-0+if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +return netdev_store (dev, attr, buf, len, change_tx_queue_len);You mean
ns_capablehere?
No. There I meant capable.
I deliberately call capable here because I don't understand what the tx_queue_len well enough to be certain it is safe to relax that check to be just ns_capable.
My get feel is that allowing an unprivileged user to be able to arbitrarily change the tx_queue_len on a networking device would be a nice way to allow queuing as many network packets as you would like with kernel memory and DOSing the machine.
So since with a quick read of the code I could not convince myself it was safe to allow unprivilged users to change tx_queue_len I left it protected by capable. While at the same time I relaxed the check in netdev_store to be ns_capable.
Eric
A message that is not in the archive (sent off-list or not yet received): 871uft8vpm.fsf-aS9lmoZGLiVWk0Htik3J/[email protected]
Re: [PATCH net-next 09/17] net: Allow userns root control of the core of the network stack.
Quoted 21 lines · Eric W. Biederman
Quoted 7 lines · Glauber Costa
net/core/net-sysfs.c static ssize_t store_tx_queue_len(struct device *dev, · line 271
Quoted 4 lines · Eric W. Biederman
net/core/net-sysfs.c +3
-0+if (!capable (CAP_NET_ADMIN )) +return -EPERM ; +return netdev_store (dev, attr, buf, len, change_tx_queue_len);You mean
ns_capablehere?No. There I meant capable.
I deliberately call capable here because I don't understand what the
tx_queue_lenwell enough to be certain it is safe to relax that check to be justns_capable.My get feel is that allowing an unprivileged user to be able to arbitrarily change the
tx_queue_lenon a networking device would be a nice way to allow queuing as many network packets as you would like with kernel memory and DOSing the machine.
Quoted 4 lines
So since with a quick read of the code I could not convince myself it was safe to allow unprivilged users to change
tx_queue_lenI left it protected by capable. While at the same time I relaxed the check innetdev_storeto bens_capable.
Tor the same reason you had better be very selective about which ethtool commands are allowed based on per-user_ns CAP_NET_ADMIN. Consider for a start:
ETHTOOL_SMSGLVL => fill up the system logETHTOOL_SEEPROM => brick the NICETHTOOL_FLASHDEV => brick the NIC; own the system if it's not using an IOMMU
Ben.
Signature · 3 lines
Ben Hutchings, Staff Engineer, Solarflare Not speaking for my employer; that's the marketing department's job. They asked us to note that Solarflare product names are trademarked.
A message that is not in the archive (sent off-list or not yet received): 1353112116.2743.79.camel-/[email protected]
Re: [PATCH net-next 09/17] net: Allow userns root control of the core of the network stack.
Quoted 27 lines · Ben Hutchings
Quoted 21 lines · Eric W. Biederman
Quoted 7 lines · Glauber Costa
Review
Quoted 4 lines · Eric W. Biederman
(quoted diff) +3
-0+ if (!capable(CAP_NET_ADMIN)) + return -EPERM; + return netdev_store(dev, attr, buf, len, change_tx_queue_len);You mean
ns_capablehere?No. There I meant capable.
I deliberately call capable here because I don't understand what the
tx_queue_lenwell enough to be certain it is safe to relax that check to be justns_capable.My get feel is that allowing an unprivileged user to be able to arbitrarily change the
tx_queue_lenon a networking device would be a nice way to allow queuing as many network packets as you would like with kernel memory and DOSing the machine.Quoted 4 lines
So since with a quick read of the code I could not convince myself it was safe to allow unprivilged users to change
tx_queue_lenI left it protected by capable. While at the same time I relaxed the check innetdev_storeto bens_capable.
Quoted 6 lines
Tor the same reason you had better be very selective about which ethtool commands are allowed based on per-user_ns
CAP_NET_ADMIN. Consider for a start:
ETHTOOL_SEEPROM=> brick the NICETHTOOL_FLASHDEV=> brick the NIC; own the system if it's not using an IOMMU
These are prevented by not having access to real hardware by default. A physical network interface must be moved into a network namespace for you to have access to it.
There are a handful of software network devices that are generally safe macvlan, veth, tun, ipip tunnels, etc. Using those network devices is very interesting and about as performant as you can get while still being safe.
A buffer overflow in an ethtool command looks as likely to me as being able to own the system by reflashing the NIC.
Access to a real physical NIC is an act of trust. Given the general linux policy that drivers are merged when they mostly work I don't currently know of any trust models between "I trust you with full access to this device" and "I don't trust you with direct access to this device" that I would feel confident giving to an untrusted user.
Which is a convoluted way of saying "ip link set eth0 netns bob" is the moral equivalent of "chown bob.bob /dev/eth0; chmod u+rwx /dev/eth0"
Quoted 1 line
ETHTOOL_SMSGLVL=> fill up the system log
That one might be worth doing something about, as there is non-local effect. Still I don't believe for any of the software based "safe" networking devices ETHTOOL_SMSGLVL has any effect, and being able to tweak the debug level could be important for debugging if you do have direct access to the NIC.
Eric
A message that is not in the archive (sent off-list or not yet received): 87lie13q18.fsf-aS9lmoZGLiVWk0Htik3J/[email protected]
Re: [PATCH net-next 09/17] net: Allow userns root control of the core of the network stack.
Quoted 33 lines · Eric W. Biederman
Quoted 31 lines · Ben Hutchings
Quoted 21 lines · Eric W. Biederman
Quoted 7 lines · Glauber Costa
Review
Quoted 4 lines · Eric W. Biederman
(quoted diff) +3
-0+ if (!capable(CAP_NET_ADMIN)) + return -EPERM; + return netdev_store(dev, attr, buf, len, change_tx_queue_len);You mean
ns_capablehere?No. There I meant capable.
I deliberately call capable here because I don't understand what the
tx_queue_lenwell enough to be certain it is safe to relax that check to be justns_capable.My get feel is that allowing an unprivileged user to be able to arbitrarily change the
tx_queue_lenon a networking device would be a nice way to allow queuing as many network packets as you would like with kernel memory and DOSing the machine.Quoted 4 lines
So since with a quick read of the code I could not convince myself it was safe to allow unprivilged users to change
tx_queue_lenI left it protected by capable. While at the same time I relaxed the check innetdev_storeto bens_capable.Tor the same reason you had better be very selective about which ethtool commands are allowed based on per-user_ns
CAP_NET_ADMIN. Consider for a start:
Quoted 6 lines
Quoted 2 lines
ETHTOOL_SEEPROM=> brick the NICETHTOOL_FLASHDEV=> brick the NIC; own the system if it's not using an IOMMUThese are prevented by not having access to real hardware by default. A physical network interface must be moved into a network namespace for you to have access to it.
Yes, I realise that. The question is whether you would expect anything in a container to be able to do those things, even with a physical net device assigned to it.
Actually we have the same issue without considering containers - should CAP_NET_ADMIN really give you low-level control over hardware just because it's networking hardware? I think some of these ethtool operations, and access to non-standard MDIO registers, should perhaps require an additional capability (CAP_SYS_ADMIN or CAP_SYS_RAWIO?).
Quoted 7 lines
There are a handful of software network devices that are generally safe macvlan, veth, tun, ipip tunnels, etc. Using those network devices is very interesting and about as performant as you can get while still being safe.
A buffer overflow in an ethtool command looks as likely to me as being able to own the system by reflashing the NIC.
Sure, if you can find one. But on many NICs the firmware can perform more or less arbitrary DMA *by design* (one reason for using IOMMUs), and the ability to update the firmware is not a bug to be fixed!
Quoted 5 lines
Access to a real physical NIC is an act of trust. Given the general linux policy that drivers are merged when they mostly work I don't currently know of any trust models between "I trust you with full access to this device" and "I don't trust you with direct access to this device" that I would feel confident giving to an untrusted user.
At the moment it's 'I trust you with full access to *all* network devices' (init ns CAP_NET_ADMIN), 'I trust you with some reconfiguration of these network devices' (other ns CAP_NET_ADMIN) and 'I don't trust you...'
You're expanding what other-ns-CAP_NET_ADMIN means, to 'I trust you with full access to these network devices'.
Quoted 2 lines
Which is a convoluted way of saying "ip link set eth0 netns bob" is the moral equivalent of "chown bob.bob
/dev/eth0; chmod u+rwx/dev/eth0"
[...]
And it's previously been decided that ownership of a block device still should *not* mean full control over it (see responses to CVE-2011-4127).
Ben.
Signature · 3 lines
Ben Hutchings, Staff Engineer, Solarflare Not speaking for my employer; that's the marketing department's job. They asked us to note that Solarflare product names are trademarked.
PATCH 13/17 net: Allow userns root to control the network bridge code.
In reply to Eric W. BiedermanFrom: "Eric W. Biederman" <[email protected]>
Allow an unpriviled user who has created a user namespace, and then created a network namespace to effectively use the new network namespace, by reducing capable(CAP_NET_ADMIN) and capable(CAP_NET_RAW) calls to be ns_capable(net->user_ns, CAP_NET_ADMIN), or capable(net->user_ns, CAP_NET_RAW) calls.
Allow setting bridge paramters via sysfs.
Allow all of the bridge ioctls:BRCTL_ADD_IFBRCTL_DEL_IFBRCTL_SET_BRDIGE_FORWARD_DELAYBRCTL_SET_BRIDGE_HELLO_TIMEBRCTL_SET_BRIDGE_MAX_AGEBRCTL_SET_BRIDGE_AGING_TIMEBRCTL_SET_BRIDGE_STP_STATEBRCTL_SET_BRIDGE_PRIORITYBRCTL_SET_PORT_PRIORITYBRCTL_SET_PATH_COSTBRCTL_ADD_BRIDGEBRCTL_DEL_BRDIGE
--- net/bridge/br_ioctl.c | 25 +++++++++++++------------ net/bridge/br_sysfs_br.c | 10 +++++----- net/bridge/br_sysfs_if.c | 2 +- 3 files changed, 19 insertions(+), 18 deletions(-)
net/bridge/br_ioctl.c +13 -12
@@ -85,13 +85,14 @@ static int get_fdb_entries(struct net_bridge *br, void __user *userbuf,/* called with RTNL */ static int add_del_if (struct net_bridge *br,int ifindex,int isadd) { +struct net *net =dev_net (br->dev);struct net_device *dev;int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ; - dev =__dev_get_by_index (dev_net (br->dev), ifindex); + dev =__dev_get_by_index (net, ifindex);if (dev ==NULL )return -EINVAL ;
@@ -178,25 +179,25 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) }case BRCTL_SET_BRIDGE_FORWARD_DELAY : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;return br_set_forward_delay (br, args[1 ]);case BRCTL_SET_BRIDGE_HELLO_TIME : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;return br_set_hello_time (br, args[1 ]);case BRCTL_SET_BRIDGE_MAX_AGE : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;return br_set_max_age (br, args[1 ]);case BRCTL_SET_AGEING_TIME : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ; br->ageing_time =clock_t_to_jiffies (args[1 ]);
@@ -236,14 +237,14 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) }case BRCTL_SET_BRIDGE_STP_STATE : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;br_stp_set_enabled (br, args[1 ]);return 0 ;case BRCTL_SET_BRIDGE_PRIORITY : -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;spin_lock_bh (&br->lock);
@@ -256,7 +257,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)struct net_bridge_port *p;int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;spin_lock_bh (&br->lock);
@@ -273,7 +274,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)struct net_bridge_port *p;int ret; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;spin_lock_bh (&br->lock);
@@ -330,7 +331,7 @@ static int old_deviceless(struct net *net, void __user *uarg) {char buf[IFNAMSIZ ]; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;if (copy_from_user (buf, (void __user *)args[1 ],IFNAMSIZ ))
@@ -360,7 +361,7 @@ int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uar {char buf[IFNAMSIZ ]; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (net->user_ns,CAP_NET_ADMIN ))return -EPERM ;if (copy_from_user (buf, uarg,IFNAMSIZ ))
net/bridge/br_sysfs_br.c +5 -5
@@ -36,7 +36,7 @@ static ssize_t store_bridge_parm(struct device *d,unsigned long val;int err; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (br->dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ; val =simple_strtoul (buf, &endp,0 );
@@ -132,7 +132,7 @@ static ssize_t store_stp_state(struct device *d,char *endp;unsigned long val; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (br->dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ; val =simple_strtoul (buf, &endp,0 );
@@ -165,7 +165,7 @@ static ssize_t store_group_fwd_mask(struct device *d,char *endp;unsigned long val; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (br->dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ; val =simple_strtoul (buf, &endp,0 );
@@ -300,7 +300,7 @@ static ssize_t store_group_addr(struct device *d,unsigned int new_addr[6 ];int i; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (br->dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ; if (sscanf(buf, "%x:%x:%x:%x:%x:%x",
@@ -337,7 +337,7 @@ static ssize_t store_flush(struct device *d, {struct net_bridge *br =to_bridge (d); -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (br->dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ;br_fdb_flush (br);
net/bridge/br_sysfs_if.c +1 -1
@@ -209,7 +209,7 @@ static ssize_t brport_store(struct kobject * kobj,char *endp;unsigned long val; -if (!capable (CAP_NET_ADMIN )) +if (!ns_capable (dev_net (p->dev)->user_ns,CAP_NET_ADMIN ))return -EPERM ; val =simple_strtoul (buf, &endp,0 );
Signature · 1 line
1.7.5.4
From: ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected] (Eric W. Biederman)
Date: Fri, 16 Nov 2012 05:01:44 -0800
Quoted 22 lines
In a secondary user namespace the root user only has
CAP_NET_ADMIN,CAP_NET_RAWandCAP_NET_BIND_SERVICEwith respect to the secondary user namespace. The test "capable(CAP_NET_ADMIN)" tests for capabilities in the initial user namespace.The following set of patches goes through the networking stack. First pushing the
capable(CAP_NET_ADMIN)admin calls down farther in the stack so individual instances can be changed. Then where I have I it appears safe I have relaxed the permission checks.The code is available in git from:
git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.gitnetns-v73The netns-v73 branch is against v3.7-rc3 and merges cleanly with net-next.
In my user namespace tree I am working to allow unprivileged users to create user namespace, and to allow the user namespace root able to create network namespaces. Making these patches really about allowing unprivileged users able to use the networking stack (not that they will be able to talk to anyone).
Quoted 4 lines
David I have some small dependencies on the first two patches of this series in my later user namespace work. So after these changes have been reviewed if you can pull my netns-v73 branch (which is just these patches) into net-next that will help me avoid unnecessary conflicts.
There were merge issues so I applied the patches and sorted the conflicts out one-by-one.
I hope this doesn't cause major problems.
David Miller
maintainerFrom: [email protected] (Eric W. Biederman)
Date: Fri, 16 Nov 2012 05:01:44 -0800
Quoted 22 lines
In a secondary user namespace the root user only has
CAP_NET_ADMIN,CAP_NET_RAWandCAP_NET_BIND_SERVICEwith respect to the secondary user namespace. The test "capable(CAP_NET_ADMIN)" tests for capabilities in the initial user namespace.The following set of patches goes through the networking stack. First pushing the
capable(CAP_NET_ADMIN)admin calls down farther in the stack so individual instances can be changed. Then where I have I it appears safe I have relaxed the permission checks.The code is available in git from:
git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.gitnetns-v73The netns-v73 branch is against v3.7-rc3 and merges cleanly with net-next.
In my user namespace tree I am working to allow unprivileged users to create user namespace, and to allow the user namespace root able to create network namespaces. Making these patches really about allowing unprivileged users able to use the networking stack (not that they will be able to talk to anyone).
Quoted 4 lines
David I have some small dependencies on the first two patches of this series in my later user namespace work. So after these changes have been reviewed if you can pull my netns-v73 branch (which is just these patches) into net-next that will help me avoid unnecessary conflicts.
There were merge issues so I applied the patches and sorted the conflicts out one-by-one.
I hope this doesn't cause major problems.
A message that is not in the archive (sent off-list or not yet received): 20121118.222601.1683927229305655885.davem-fT/PcQaiUtIeIZ0/[email protected]
Quoted 4 lines · David Miller
There were merge issues so I applied the patches and sorted the conflicts out one-by-one.
I hope this doesn't cause major problems.
Shucks, I had thought I had tested and verified there would not be merge issues. Oh well.
No major problems.
To keep it that way I am dropping all but the first two patches from my userns development tree. I have dependencies on the infrastructure bits.
A quick merge test reveals that your tree against my full development tree has two minor conflicts that are trivial to resolve. So I don't anticipate Linus will have any problems.
Eric
A message that is not in the archive (sent off-list or not yet received): 87haomkq7q.fsf-aS9lmoZGLiVWk0Htik3J/[email protected]
From: ebiederm-aS9lmoZGLiVWk0Htik3J/[email protected] (Eric W. Biederman)
Date: Sun, 18 Nov 2012 23:27:05 -0800
Quoted 2 lines
Shucks, I had thought I had tested and verified there would not be merge issues. Oh well.
After you had submitted, there were netlink changes, particularly in the bridging code.