summaryrefslogtreecommitdiffstats
path: root/net/ipv4/ping.c
diff options
context:
space:
mode:
authorEric W. Biederman2012-05-24 18:34:21 +0200
committerEric W. Biederman2012-08-15 06:49:10 +0200
commit7064d16e162adf8199f0288b694e6af823ed5431 (patch)
tree02563996ee28d686b1cb9a16ba389b382aa6bb4f /net/ipv4/ping.c
parentuserns: Print out socket uids in a user namespace aware fashion. (diff)
downloadkernel-qcow2-linux-7064d16e162adf8199f0288b694e6af823ed5431.tar.gz
kernel-qcow2-linux-7064d16e162adf8199f0288b694e6af823ed5431.tar.xz
kernel-qcow2-linux-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.c18
1 files changed, 6 insertions, 12 deletions
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index bee5eeb676f8..8f3d05424a3e 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++) {