2017-07-18 06:32:49

by Rob Landley

[permalink] [raw]
Subject: ping/icmp sockets: define "sane".

The title is from this comment in net/ipv4:

/*
* Sane defaults - nobody may create ping sockets.
* Boot scripts should set this to distro-specific group.
*/

So in 2011 you added ICMP sockets, but made it so nobody could use them
without root performing a magic incatation at boot time. From the original
commit message:

> socket(2) is restricted to the group range specified in
> "/proc/sys/net/ipv4/ping_group_range". It is "1 0" by default, meaning
> that nobody (not even root) may create ping sockets.

Why? What's the point of NOT letting root use this? So ping programs like
busybox's can't use the new api as a drop-in replacment for the old one
because even if they keep the suid bit on the command, it won't work?

I thought busybox was using it, but they ripped it back out in 2014:
https://git.busybox.net/busybox/commit/?id=f0058b1b1fe9

What is the point of creating a new api to do something root could
previously do in a safer way that doesn't require root access, and then
not even let root do it by default? What's the point? I thought commit
ba6b918ab234 removed this blockage, but instead it moved it to a
different file.

Is ping flood from icmp somehow more dangerous than UDP flood from an
arbitrary user? What's the issue reeuiring this elaborate infrastructure
to render your new api so useless busybox went BACK to the suid root
version, and the ping in ubuntu 14.04 is also suid root?

I ask because I'm finally getting around to implementing ping in toybox
and of course I was going to use the new API, and testing it on Ubuntu
didn't work, so I dug this mess up and boggled. Perhaps you could explain
it?

The Android guys say that yes they use this API, and make it available
to everybody, even from java:

http://lists.landley.net/pipermail/toybox-landley.net/2017-July/009101.html

The kernel patch to make it work is presumably just:

--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1712,12 +1712,8 @@ static __net_init int inet_init_net(struct net *net)
net->ipv4.ip_local_ports.range[1] = 60999;
seqlock_init(&net->ipv4.ping_group_range.lock);
- /*
- * Sane defaults - nobody may create ping sockets.
- * Boot scripts should set this to distro-specific group.
- */
- net->ipv4.ping_group_range.range[0] = make_kgid(&init_user_ns, 1);
- net->ipv4.ping_group_range.range[1] = make_kgid(&init_user_ns, 0);
+ net->ipv4.ping_group_range.range[0] = make_kgid(&init_user_ns, 0);
+ net->ipv4.ping_group_range.range[1] = make_kgid(&init_user_ns,
65535);
/* Default values for sysctl-controlled parameters.
* We set them here, in case sysctl is not compiled.

I'm tempted to put that diff into the toybox FAQ for people who want
to use toybox on vanilla linux. But first, I thought I'd ask for an
explanation of why it's explicitly, intentionally broken in the first
place? You made a "safer" API to not require root access, and then made
it so even root can't use it.

Why did you do that?

Rob