--------------------- PatchSet 11568 Date: 2007/08/15 01:54:56 Author: hno Branch: HEAD Tag: (none) Log: Cleanup linux capabilities for tproxy - Automatically disable tproxy if the needed capabilities could not be set - Keep the permitted set unless root privileges is completely dropped (chroot), as is normally done when not using capabilities. This fixes file permissions regarding the pid file. Members: src/client_side.c:1.731->1.732 src/tools.c:1.257->1.258 Index: squid/src/client_side.c =================================================================== RCS file: /cvsroot/squid/squid/src/client_side.c,v retrieving revision 1.731 retrieving revision 1.732 diff -u -r1.731 -r1.732 --- squid/src/client_side.c 15 Aug 2007 01:15:43 -0000 1.731 +++ squid/src/client_side.c 15 Aug 2007 01:54:56 -0000 1.732 @@ -1,6 +1,6 @@ /* - * $Id: client_side.c,v 1.731 2007/08/15 01:15:43 hno Exp $ + * $Id: client_side.c,v 1.732 2007/08/15 01:54:56 hno Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -3793,7 +3793,7 @@ if (conn->port->urlgroup) request->urlgroup = xstrdup(conn->port->urlgroup); #if LINUX_TPROXY - request->flags.tproxy = conn->port->tproxy; + request->flags.tproxy = conn->port->tproxy && need_linux_tproxy; #endif request->flags.accelerated = http->flags.accel; request->flags.transparent = http->flags.transparent; Index: squid/src/tools.c =================================================================== RCS file: /cvsroot/squid/squid/src/tools.c,v retrieving revision 1.257 retrieving revision 1.258 diff -u -r1.257 -r1.258 --- squid/src/tools.c 12 Aug 2007 10:30:58 -0000 1.257 +++ squid/src/tools.c 15 Aug 2007 01:54:56 -0000 1.258 @@ -1,6 +1,6 @@ /* - * $Id: tools.c,v 1.257 2007/08/12 10:30:58 serassio Exp $ + * $Id: tools.c,v 1.258 2007/08/15 01:54:56 hno Exp $ * * DEBUG: section 21 Misc Functions * AUTHOR: Harvest Derived @@ -40,7 +40,7 @@ #include "squid.h" -#if LINUX_TPROXY +#ifdef _SQUID_LINUX_ #undef _POSIX_SOURCE /* Ugly glue to get around linux header madness colliding with glibc */ #define _LINUX_TYPES_H @@ -70,6 +70,7 @@ extern void log_trace_done(); extern void log_trace_init(char *); #endif +static void restoreCapabilities(int keep); #ifdef _SQUID_LINUX_ /* Workaround for crappy glic header files */ @@ -633,23 +634,7 @@ if (setuid(Config2.effectiveUserID) < 0) debug(50, 0) ("ALERT: setuid: %s\n", xstrerror()); #endif -#if LINUX_TPROXY - if (need_linux_tproxy) { - cap_user_header_t head = (cap_user_header_t) xcalloc(1, sizeof(cap_user_header_t)); - cap_user_data_t cap = (cap_user_data_t) xcalloc(1, sizeof(cap_user_data_t)); - - head->version = _LINUX_CAPABILITY_VERSION; - head->pid = 0; - cap->inheritable = cap->permitted = cap->effective = (1 << CAP_NET_ADMIN) + (1 << CAP_NET_BIND_SERVICE) + (1 << CAP_NET_BROADCAST); - if (capset(head, cap) != 0) { - xfree(head); - xfree(cap); - fatal("Error giving up capabilities"); - } - xfree(head); - xfree(cap); - } -#endif + restoreCapabilities(1); /* Changing user ID usually blocks core dumps. Get them back! */ enableCoredumps(); } @@ -677,14 +662,10 @@ leave_suid(); uid = geteuid(); debug(21, 3) ("no_suid: PID %d giving up root priveleges forever\n", (int) getpid()); -#if HAVE_SETRESUID - if (setresuid(uid, uid, uid) < 0) - debug(50, 1) ("no_suid: setresuid: %s\n", xstrerror()); -#else setuid(0); if (setuid(uid) < 0) debug(50, 1) ("no_suid: setuid: %s\n", xstrerror()); -#endif + restoreCapabilities(0); enableCoredumps(); } @@ -1358,12 +1339,55 @@ void keepCapabilities(void) { +#if HAVE_PRCTL && defined(PR_SET_KEEPCAPS) + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { + /* Silent failure unless TPROXY is required. Maybe not started as root */ #if LINUX_TPROXY - if (need_linux_tproxy) { - if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { + if (need_linux_tproxy) debug(1, 1) ("Error - tproxy support requires capability setting which has failed. Continuing without tproxy support\n"); - } + need_linux_tproxy = 0; +#endif + } +#endif +} + +static void +restoreCapabilities(int keep) +{ +#ifdef _SQUID_LINUX_ + cap_user_header_t head = (cap_user_header_t) xcalloc(1, sizeof(cap_user_header_t)); + cap_user_data_t cap = (cap_user_data_t) xcalloc(1, sizeof(cap_user_data_t)); + + head->version = _LINUX_CAPABILITY_VERSION; + if (capget(head, cap) != 0) { + debug(50, 1) ("Can't get current capabilities\n"); + goto nocap; + } + if (head->version != _LINUX_CAPABILITY_VERSION) { + debug(50, 1) ("Invalid capability version %d (expected %d)\n", head->version, _LINUX_CAPABILITY_VERSION); + goto nocap; + } + head->pid = 0; + + cap->inheritable = 0; + cap->effective = (1 << CAP_NET_BIND_SERVICE); +#if LINUX_TPROXY + if (need_linux_tproxy) + cap->effective |= (1 << CAP_NET_ADMIN) | (1 << CAP_NET_BROADCAST); +#endif + if (!keep) + cap->permitted &= cap->effective; + if (capset(head, cap) != 0) { + /* Silent failure unless TPROXY is required */ +#if LINUX_TPROXY + if (need_linux_tproxy) + debug(50, 1) ("Error enabling needed capabilities. Will continue without tproxy support\n"); + need_linux_tproxy = 0; +#endif } + nocap: + xfree(head); + xfree(cap); #endif }