How does macOS allow Standard users to ping
I've got a pretty deep question here that I hope someone can answer. In macOS, regular users can ping as well as root. Normally, root access is required to open the raw socket necessary to run ping. I've noticed on Linux that this usually accomplished by adding extended attributes to the ping program file to allow root-level access for opening raw sockets (in the past, this was done by just setting the setuid bit on the ping program, allowing it to do anything in its programming as root).
I've looked at /sbin/ping on macOS (High Sierra, specifically), and no such attributes are set, and neither is setuid. So what is macOS doing to allow Standard (non-root) users to ping? Are they sending ICMP packets over TCP or UDP? If so (or if there's another mechanism I'm just missing entirely), can you point me to some docs? Any help would be appreciated.
Let's take a look at the source code for Apple's ping
implementation. Notably, we see this:
if (getuid())
s = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
else
s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
sockerrno = errno;
getuid
returns 0 if root. So this code is saying, "open the socket in DGRAM (datagram mode) if we are not root. If we are root, open as raw".
So a raw socket is only used when you are root. An IMCP ping packet is a standard DGRAM packet and does not require raw sockets.
However, there are some flags that can be passed to ping
that do require root, and for those you will get an "Operation Not Permitted". For example:
>ping -f
ping: -f flag: Operation not permitted
When run as root, I do not get the operation not permitted. So Apple's implementation will let you do standard ping operations which does not require root, but require you to run as root for certain flags and operations.
Depending on if you are root, it may set some additional socket options:
if (uid == 0)
(void)setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&hold,
sizeof(hold));