Commit 464dc801 authored by Eric W. Biederman's avatar Eric W. Biederman Committed by David S. Miller

net: Don't export sysctls to unprivileged users

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.
Signed-off-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 73f7ef43
...@@ -2987,6 +2987,10 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p, ...@@ -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; 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", snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
p_name, dev_name_source); p_name, dev_name_source);
t->sysctl_header = t->sysctl_header =
......
...@@ -216,6 +216,11 @@ static __net_init int sysctl_core_net_init(struct net *net) ...@@ -216,6 +216,11 @@ static __net_init int sysctl_core_net_init(struct net *net)
goto err_dup; goto err_dup;
tbl[0].data = &net->core.sysctl_somaxconn; 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->core.sysctl_hdr = register_net_sysctl(net, "net/core", tbl);
......
...@@ -1815,6 +1815,10 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name, ...@@ -1815,6 +1815,10 @@ static int __devinet_sysctl_register(struct net *net, char *dev_name,
t->devinet_vars[i].extra2 = net; 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); snprintf(path, sizeof(path), "net/ipv4/conf/%s", dev_name);
t->sysctl_header = register_net_sysctl(net, path, t->devinet_vars); t->sysctl_header = register_net_sysctl(net, path, t->devinet_vars);
...@@ -1900,6 +1904,10 @@ static __net_init int devinet_init_net(struct net *net) ...@@ -1900,6 +1904,10 @@ static __net_init int devinet_init_net(struct net *net)
tbl[0].data = &all->data[IPV4_DEVCONF_FORWARDING - 1]; tbl[0].data = &all->data[IPV4_DEVCONF_FORWARDING - 1];
tbl[0].extra1 = all; tbl[0].extra1 = all;
tbl[0].extra2 = net; tbl[0].extra2 = net;
/* Don't export sysctls to unprivileged users */
if (net->user_ns != &init_user_ns)
tbl[0].procname = NULL;
#endif #endif
} }
......
...@@ -802,6 +802,10 @@ static int __net_init ip4_frags_ns_ctl_register(struct net *net) ...@@ -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[0].data = &net->ipv4.frags.high_thresh;
table[1].data = &net->ipv4.frags.low_thresh; table[1].data = &net->ipv4.frags.low_thresh;
table[2].data = &net->ipv4.frags.timeout; 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); hdr = register_net_sysctl(net, "net/ipv4", table);
......
...@@ -2493,6 +2493,10 @@ static __net_init int sysctl_route_net_init(struct net *net) ...@@ -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); tbl = kmemdup(tbl, sizeof(ipv4_route_flush_table), GFP_KERNEL);
if (tbl == NULL) if (tbl == NULL)
goto err_dup; 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; tbl[0].extra1 = net;
......
...@@ -883,6 +883,9 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) ...@@ -883,6 +883,9 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
table[6].data = table[6].data =
&net->ipv4.sysctl_ping_group_range; &net->ipv4.sysctl_ping_group_range;
/* Don't export sysctls to unprivileged users */
if (net->user_ns != &init_user_ns)
table[0].procname = NULL;
} }
/* /*
......
...@@ -4735,6 +4735,10 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name, ...@@ -4735,6 +4735,10 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name,
t->addrconf_vars[i].extra2 = net; 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); snprintf(path, sizeof(path), "net/ipv6/conf/%s", dev_name);
t->sysctl_header = register_net_sysctl(net, path, t->addrconf_vars); t->sysctl_header = register_net_sysctl(net, path, t->addrconf_vars);
......
...@@ -967,9 +967,14 @@ struct ctl_table * __net_init ipv6_icmp_sysctl_init(struct net *net) ...@@ -967,9 +967,14 @@ struct ctl_table * __net_init ipv6_icmp_sysctl_init(struct net *net)
sizeof(ipv6_icmp_table_template), sizeof(ipv6_icmp_table_template),
GFP_KERNEL); GFP_KERNEL);
if (table) if (table) {
table[0].data = &net->ipv6.sysctl.icmpv6_time; 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; return table;
} }
#endif #endif
......
...@@ -616,6 +616,10 @@ static int __net_init ip6_frags_ns_sysctl_register(struct net *net) ...@@ -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[0].data = &net->ipv6.frags.high_thresh;
table[1].data = &net->ipv6.frags.low_thresh; table[1].data = &net->ipv6.frags.low_thresh;
table[2].data = &net->ipv6.frags.timeout; 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); hdr = register_net_sysctl(net, "net/ipv6", table);
......
...@@ -2989,6 +2989,10 @@ struct ctl_table * __net_init ipv6_route_sysctl_init(struct net *net) ...@@ -2989,6 +2989,10 @@ struct ctl_table * __net_init ipv6_route_sysctl_init(struct net *net)
table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires; table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires;
table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss; table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss;
table[9].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval; 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; return table;
......
...@@ -52,6 +52,10 @@ static int __net_init ipv6_sysctl_net_init(struct net *net) ...@@ -52,6 +52,10 @@ static int __net_init ipv6_sysctl_net_init(struct net *net)
goto out; goto out;
ipv6_table[0].data = &net->ipv6.sysctl.bindv6only; 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); ipv6_route_table = ipv6_route_sysctl_init(net);
if (!ipv6_route_table) if (!ipv6_route_table)
goto out_ipv6_table; goto out_ipv6_table;
......
...@@ -3699,6 +3699,10 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net) ...@@ -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); tbl = kmemdup(vs_vars, sizeof(vs_vars), GFP_KERNEL);
if (tbl == NULL) if (tbl == NULL)
return -ENOMEM; return -ENOMEM;
/* Don't export sysctls to unprivileged users */
if (net->user_ns != &init_user_ns)
tbl[0].procname = NULL;
} else } else
tbl = vs_vars; tbl = vs_vars;
/* Initialize sysctl defaults */ /* Initialize sysctl defaults */
......
...@@ -560,6 +560,11 @@ static int __net_init __ip_vs_lblc_init(struct net *net) ...@@ -560,6 +560,11 @@ static int __net_init __ip_vs_lblc_init(struct net *net)
GFP_KERNEL); GFP_KERNEL);
if (ipvs->lblc_ctl_table == NULL) if (ipvs->lblc_ctl_table == NULL)
return -ENOMEM; return -ENOMEM;
/* Don't export sysctls to unprivileged users */
if (net->user_ns != &init_user_ns)
ipvs->lblc_ctl_table[0].procname = NULL;
} else } else
ipvs->lblc_ctl_table = vs_vars_table; ipvs->lblc_ctl_table = vs_vars_table;
ipvs->sysctl_lblc_expiration = DEFAULT_EXPIRATION; ipvs->sysctl_lblc_expiration = DEFAULT_EXPIRATION;
...@@ -569,7 +574,7 @@ static int __net_init __ip_vs_lblc_init(struct net *net) ...@@ -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); register_net_sysctl(net, "net/ipv4/vs", ipvs->lblc_ctl_table);
if (!ipvs->lblc_ctl_header) { if (!ipvs->lblc_ctl_header) {
if (!net_eq(net, &init_net)) if (!net_eq(net, &init_net))
kfree(ipvs->lblc_ctl_table); kfree(ipvs->lblc_ctl_table);\
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -754,6 +754,10 @@ static int __net_init __ip_vs_lblcr_init(struct net *net) ...@@ -754,6 +754,10 @@ static int __net_init __ip_vs_lblcr_init(struct net *net)
GFP_KERNEL); GFP_KERNEL);
if (ipvs->lblcr_ctl_table == NULL) if (ipvs->lblcr_ctl_table == NULL)
return -ENOMEM; return -ENOMEM;
/* Don't export sysctls to unprivileged users */
if (net->user_ns != &init_user_ns)
ipvs->lblcr_ctl_table[0].procname = NULL;
} else } else
ipvs->lblcr_ctl_table = vs_vars_table; ipvs->lblcr_ctl_table = vs_vars_table;
ipvs->sysctl_lblcr_expiration = DEFAULT_EXPIRATION; ipvs->sysctl_lblcr_expiration = DEFAULT_EXPIRATION;
......
...@@ -69,6 +69,10 @@ static int nf_conntrack_acct_init_sysctl(struct net *net) ...@@ -69,6 +69,10 @@ static int nf_conntrack_acct_init_sysctl(struct net *net)
table[0].data = &net->ct.sysctl_acct; 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", net->ct.acct_sysctl_header = register_net_sysctl(net, "net/netfilter",
table); table);
if (!net->ct.acct_sysctl_header) { if (!net->ct.acct_sysctl_header) {
......
...@@ -196,6 +196,10 @@ static int nf_conntrack_event_init_sysctl(struct net *net) ...@@ -196,6 +196,10 @@ static int nf_conntrack_event_init_sysctl(struct net *net)
table[0].data = &net->ct.sysctl_events; table[0].data = &net->ct.sysctl_events;
table[1].data = &net->ct.sysctl_events_retry_timeout; 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 = net->ct.event_sysctl_header =
register_net_sysctl(net, "net/netfilter", table); register_net_sysctl(net, "net/netfilter", table);
if (!net->ct.event_sysctl_header) { if (!net->ct.event_sysctl_header) {
......
...@@ -64,6 +64,10 @@ static int nf_conntrack_helper_init_sysctl(struct net *net) ...@@ -64,6 +64,10 @@ static int nf_conntrack_helper_init_sysctl(struct net *net)
table[0].data = &net->ct.sysctl_auto_assign_helper; 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 = net->ct.helper_sysctl_header =
register_net_sysctl(net, "net/netfilter", table); register_net_sysctl(net, "net/netfilter", table);
......
...@@ -815,7 +815,7 @@ static struct ctl_table dccp_sysctl_table[] = { ...@@ -815,7 +815,7 @@ static struct ctl_table dccp_sysctl_table[] = {
}; };
#endif /* CONFIG_SYSCTL */ #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) struct dccp_net *dn)
{ {
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
...@@ -836,6 +836,10 @@ static int dccp_kmemdup_sysctl_table(struct nf_proto_net *pn, ...@@ -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[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING];
pn->ctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT]; pn->ctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT];
pn->ctl_table[7].data = &dn->dccp_loose; 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 #endif
return 0; return 0;
} }
...@@ -857,7 +861,7 @@ static int dccp_init_net(struct net *net, u_int16_t proto) ...@@ -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; 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 = { static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {
......
...@@ -489,6 +489,10 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net) ...@@ -489,6 +489,10 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
table[3].data = &net->ct.sysctl_checksum; table[3].data = &net->ct.sysctl_checksum;
table[4].data = &net->ct.sysctl_log_invalid; 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); net->ct.sysctl_header = register_net_sysctl(net, "net/netfilter", table);
if (!net->ct.sysctl_header) if (!net->ct.sysctl_header)
goto out_unregister_netfilter; goto out_unregister_netfilter;
......
...@@ -51,6 +51,10 @@ static int nf_conntrack_tstamp_init_sysctl(struct net *net) ...@@ -51,6 +51,10 @@ static int nf_conntrack_tstamp_init_sysctl(struct net *net)
table[0].data = &net->ct.sysctl_tstamp; 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", net->ct.tstamp_sysctl_header = register_net_sysctl(net, "net/netfilter",
table); table);
if (!net->ct.tstamp_sysctl_header) { if (!net->ct.tstamp_sysctl_header) {
......
...@@ -34,6 +34,10 @@ int __net_init unix_sysctl_register(struct net *net) ...@@ -34,6 +34,10 @@ int __net_init unix_sysctl_register(struct net *net)
if (table == NULL) if (table == NULL)
goto err_alloc; 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; table[0].data = &net->unx.sysctl_max_dgram_qlen;
net->unx.ctl = register_net_sysctl(net, "net/unix", table); net->unx.ctl = register_net_sysctl(net, "net/unix", table);
if (net->unx.ctl == NULL) if (net->unx.ctl == NULL)
......
...@@ -54,6 +54,10 @@ int __net_init xfrm_sysctl_init(struct net *net) ...@@ -54,6 +54,10 @@ int __net_init xfrm_sysctl_init(struct net *net)
table[2].data = &net->xfrm.sysctl_larval_drop; table[2].data = &net->xfrm.sysctl_larval_drop;
table[3].data = &net->xfrm.sysctl_acq_expires; 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); net->xfrm.sysctl_hdr = register_net_sysctl(net, "net/core", table);
if (!net->xfrm.sysctl_hdr) if (!net->xfrm.sysctl_hdr)
goto out_register; goto out_register;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment