diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2012-05-24 10:34:21 -0600 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2012-08-14 21:49:10 -0700 |
commit | 7064d16e162adf8199f0288b694e6af823ed5431 (patch) | |
tree | 02563996ee28d686b1cb9a16ba389b382aa6bb4f /net/ipv4/ping.c | |
parent | a7cb5a49bf64ba64864ae16a6be028f8b0d3cc06 (diff) | |
download | linux-3.10-7064d16e162adf8199f0288b694e6af823ed5431.tar.gz linux-3.10-7064d16e162adf8199f0288b694e6af823ed5431.tar.bz2 linux-3.10-7064d16e162adf8199f0288b694e6af823ed5431.zip |
userns: Use kgids for sysctl_ping_group_range
- 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 <segoon@openwall.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Diffstat (limited to 'net/ipv4/ping.c')
-rw-r--r-- | net/ipv4/ping.c | 18 |
1 files changed, 6 insertions, 12 deletions
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index bee5eeb676f..8f3d05424a3 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -185,10 +185,10 @@ exit: 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 { @@ -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++) { |