Skip to content

Commit

Permalink
userns: Use kgids for sysctl_ping_group_range
Browse files Browse the repository at this point in the history
- Store sysctl_ping_group_range as a paire of kgid_t values
  instead of a pair of gid_t values.
- Move the kgid conversion work from ping_init_sock into ipv4_ping_group_range
- For invalid cases reset to the default disabled state.

With the kgid_t conversion made part of the original value sanitation
from userspace understand how the code will react becomes clearer
and it becomes possible to set the sysctl ping group range from
something other than the initial user namespace.

Cc: Vasiliy Kulikov <[email protected]>
Acked-by: David S. Miller <[email protected]>
Signed-off-by: Eric W. Biederman <[email protected]>
  • Loading branch information
ebiederm committed Aug 15, 2012
1 parent a7cb5a4 commit 7064d16
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 29 deletions.
3 changes: 2 additions & 1 deletion include/net/netns/ipv4.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef __NETNS_IPV4_H__
#define __NETNS_IPV4_H__

#include <linux/uidgid.h>
#include <net/inet_frag.h>

struct tcpm_hash_bucket;
Expand Down Expand Up @@ -62,7 +63,7 @@ struct netns_ipv4 {
int sysctl_icmp_ratemask;
int sysctl_icmp_errors_use_inbound_ifaddr;

unsigned int sysctl_ping_group_range[2];
kgid_t sysctl_ping_group_range[2];
long sysctl_tcp_mem[3];

atomic_t rt_genid;
Expand Down
1 change: 0 additions & 1 deletion init/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -948,7 +948,6 @@ config UIDGID_CONVERTED
depends on NETFILTER_XT_MATCH_RECENT = n
depends on NETFILTER_XT_TARGET_LOG = n
depends on NETFILTER_NETLINK_LOG = n
depends on INET = n
depends on IPV6 = n
depends on AF_RXRPC = n
depends on NET_KEY = n
Expand Down
18 changes: 6 additions & 12 deletions net/ipv4/ping.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,10 @@ static struct sock *ping_v4_lookup(struct net *net, __be32 saddr, __be32 daddr,
return sk;
}

static void inet_get_ping_group_range_net(struct net *net, gid_t *low,
gid_t *high)
static void inet_get_ping_group_range_net(struct net *net, kgid_t *low,
kgid_t *high)
{
gid_t *data = net->ipv4.sysctl_ping_group_range;
kgid_t *data = net->ipv4.sysctl_ping_group_range;
unsigned int seq;

do {
Expand All @@ -203,19 +203,13 @@ static void inet_get_ping_group_range_net(struct net *net, gid_t *low,
static int ping_init_sock(struct sock *sk)
{
struct net *net = sock_net(sk);
gid_t group = current_egid();
gid_t range[2];
kgid_t group = current_egid();
struct group_info *group_info = get_current_groups();
int i, j, count = group_info->ngroups;
kgid_t low, high;

inet_get_ping_group_range_net(net, range, range+1);
low = make_kgid(&init_user_ns, range[0]);
high = make_kgid(&init_user_ns, range[1]);
if (!gid_valid(low) || !gid_valid(high) || gid_lt(high, low))
return -EACCES;

if (range[0] <= group && group <= range[1])
inet_get_ping_group_range_net(net, &low, &high);
if (gid_lte(low, group) && gid_lte(group, high))
return 0;

for (i = 0; i < group_info->nblocks; i++) {
Expand Down
42 changes: 27 additions & 15 deletions net/ipv4/sysctl_net_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@ static int ipv4_local_port_range(ctl_table *table, int write,
}


static void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, gid_t *high)
static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low, kgid_t *high)
{
gid_t *data = table->data;
kgid_t *data = table->data;
unsigned int seq;
do {
seq = read_seqbegin(&sysctl_local_ports.lock);
Expand All @@ -89,12 +89,12 @@ static void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low,
}

/* Update system visible IP port range */
static void set_ping_group_range(struct ctl_table *table, gid_t range[2])
static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t high)
{
gid_t *data = table->data;
kgid_t *data = table->data;
write_seqlock(&sysctl_local_ports.lock);
data[0] = range[0];
data[1] = range[1];
data[0] = low;
data[1] = high;
write_sequnlock(&sysctl_local_ports.lock);
}

Expand All @@ -103,21 +103,33 @@ static int ipv4_ping_group_range(ctl_table *table, int write,
void __user *buffer,
size_t *lenp, loff_t *ppos)
{
struct user_namespace *user_ns = current_user_ns();
int ret;
gid_t range[2];
gid_t urange[2];
kgid_t low, high;
ctl_table tmp = {
.data = &range,
.maxlen = sizeof(range),
.data = &urange,
.maxlen = sizeof(urange),
.mode = table->mode,
.extra1 = &ip_ping_group_range_min,
.extra2 = &ip_ping_group_range_max,
};

inet_get_ping_group_range_table(table, range, range + 1);
inet_get_ping_group_range_table(table, &low, &high);
urange[0] = from_kgid_munged(user_ns, low);
urange[1] = from_kgid_munged(user_ns, high);
ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);

if (write && ret == 0)
set_ping_group_range(table, range);
if (write && ret == 0) {
low = make_kgid(user_ns, urange[0]);
high = make_kgid(user_ns, urange[1]);
if (!gid_valid(low) || !gid_valid(high) ||
(urange[1] < urange[0]) || gid_lt(high, low)) {
low = make_kgid(&init_user_ns, 1);
high = make_kgid(&init_user_ns, 0);
}
set_ping_group_range(table, low, high);
}

return ret;
}
Expand Down Expand Up @@ -786,7 +798,7 @@ static struct ctl_table ipv4_net_table[] = {
{
.procname = "ping_group_range",
.data = &init_net.ipv4.sysctl_ping_group_range,
.maxlen = sizeof(init_net.ipv4.sysctl_ping_group_range),
.maxlen = sizeof(gid_t)*2,
.mode = 0644,
.proc_handler = ipv4_ping_group_range,
},
Expand Down Expand Up @@ -830,8 +842,8 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
* Sane defaults - nobody may create ping sockets.
* Boot scripts should set this to distro-specific group.
*/
net->ipv4.sysctl_ping_group_range[0] = 1;
net->ipv4.sysctl_ping_group_range[1] = 0;
net->ipv4.sysctl_ping_group_range[0] = make_kgid(&init_user_ns, 1);
net->ipv4.sysctl_ping_group_range[1] = make_kgid(&init_user_ns, 0);

tcp_init_mem(net);

Expand Down

0 comments on commit 7064d16

Please sign in to comment.