From 23c38c7353fbfc2e1458d0f94e4d49906d84e50b Mon Sep 17 00:00:00 2001 From: "Yuriy M. Kaminskiy" Date: Wed, 30 Mar 2016 05:56:38 +1300 Subject: [PATCH] pinger: drop capabilities on Linux On linux, it is possible to install pinger helper with only CAP_NET_RAW raised instead of full setuid-root: (setcap cap_net_raw+ep /path/to/pinger && chmod u-s /path/to/pinger) || : However, pinger only drops setuid/setgid, and won't drop capabilities after sockets are opened (when it is setuid-root, setuid(getuid()) also drops capabilities, no code changes necessary; however, if it is only setcap'ed, setuid() is no-op). Fix is minimally tested, seems to work fine with both/either `setcap` and `chmod u+s`; non-linux/non-libcap configurations should not be affected). * Also fixes errno debug outputs. --- src/icmp/pinger.cc | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/icmp/pinger.cc b/src/icmp/pinger.cc index f9d409c7df..f5ee11c55c 100644 --- a/src/icmp/pinger.cc +++ b/src/icmp/pinger.cc @@ -162,18 +162,46 @@ main(int argc, char *argv[]) max_fd = max(max_fd, squid_link); if (setgid(getgid()) < 0) { - debugs(42, DBG_CRITICAL, "FATAL: pinger: setgid(" << getgid() << ") failed: " << xstrerror()); + int xerrno = errno; + debugs(42, DBG_CRITICAL, "FATAL: pinger: setgid(" << getgid() << ") failed: " << xstrerr(xerrno)); icmp4.Close(); icmp6.Close(); exit (1); } if (setuid(getuid()) < 0) { - debugs(42, DBG_CRITICAL, "FATAL: pinger: setuid(" << getuid() << ") failed: " << xstrerror()); + int xerrno = errno; + debugs(42, DBG_CRITICAL, "FATAL: pinger: setuid(" << getuid() << ") failed: " << xstrerr(xerrno)); icmp4.Close(); icmp6.Close(); exit (1); } +#if USE_LIBCAP + // Drop remaining capabilities (if installed as non-setuid setcap cap_net_raw=ep). + // If pinger binary was installed setuid root, setuid() above already dropped all + // capabilities, and this is no-op. + cap_t caps; + caps = cap_init(); + if (!caps) { + int xerrno = errno; + debugs(42, DBG_CRITICAL, "FATAL: pinger: cap_init() failed: " << xstrerr(xerrno)); + icmp4.Close(); + icmp6.Close(); + exit (1); + } else { + if (cap_set_proc(caps) != 0) { + int xerrno = errno; + // cap_set_proc(cap_init()) is expected to never fail + debugs(42, DBG_CRITICAL, "FATAL: pinger: cap_set_proc(none) failed: " << xstrerr(xerrno)); + cap_free(caps); + icmp4.Close(); + icmp6.Close(); + exit (1); + } + cap_free(caps); + } +#endif + last_check_time = squid_curtime; for (;;) { @@ -192,7 +220,8 @@ main(int argc, char *argv[]) getCurrentTime(); if (x < 0) { - debugs(42, DBG_CRITICAL, HERE << " FATAL Shutdown. select()==" << x << ", ERR: " << xstrerror()); + int xerrno = errno; + debugs(42, DBG_CRITICAL, HERE << " FATAL Shutdown. select()==" << x << ", ERR: " << xstrerr(xerrno)); control.Close(); exit(1); } -- 2.47.2