From: serassio <> Date: Sun, 23 Sep 2007 15:18:08 +0000 (+0000) Subject: Forward port of latest tproxy changes from SQUID 2: X-Git-Tag: SQUID_3_0_RC1~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=329ce686ef29a0384b5b5ad3e39eef5023876e0d;p=thirdparty%2Fsquid.git Forward port of latest tproxy changes from SQUID 2: - 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. - Test for sys/capability.h linux include file to avoid failing on systems missing libcap --- diff --git a/configure b/configure index 27783d160a..028bbbaef9 100755 --- a/configure +++ b/configure @@ -23509,7 +23509,8 @@ for ac_header in \ nss_common.h \ nss.h \ db.h \ - db_185.h + db_185.h \ + sys/capability.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` diff --git a/configure.in b/configure.in index 43e7c7bea7..5001b8cbd1 100644 --- a/configure.in +++ b/configure.in @@ -1,7 +1,7 @@ dnl Configuration input file for Squid dnl -dnl $Id: configure.in,v 1.480 2007/09/20 11:07:53 amosjeffries Exp $ +dnl $Id: configure.in,v 1.481 2007/09/23 09:18:08 serassio Exp $ dnl dnl dnl @@ -11,7 +11,7 @@ AM_CONFIG_HEADER(include/autoconf.h) AC_CONFIG_AUX_DIR(cfgaux) AC_CONFIG_SRCDIR([src/main.cc]) AM_INIT_AUTOMAKE([tar-ustar]) -AC_REVISION($Revision: 1.480 $)dnl +AC_REVISION($Revision: 1.481 $)dnl AC_PREFIX_DEFAULT(/usr/local/squid) AM_MAINTAINER_MODE @@ -1916,7 +1916,8 @@ AC_CHECK_HEADERS( \ nss_common.h \ nss.h \ db.h \ - db_185.h + db_185.h \ + sys/capability.h ) AC_CHECK_HEADERS( diff --git a/include/autoconf.h.in b/include/autoconf.h.in index f6a9db42c5..60eda1ce8a 100644 --- a/include/autoconf.h.in +++ b/include/autoconf.h.in @@ -598,6 +598,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_BSWAP_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_CAPABILITY_H + /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_DIR_H diff --git a/src/client_side.cc b/src/client_side.cc index 7012871171..cfc7ad38d1 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1,6 +1,6 @@ /* - * $Id: client_side.cc,v 1.765 2007/09/03 03:13:52 hno Exp $ + * $Id: client_side.cc,v 1.766 2007/09/23 09:18:10 serassio Exp $ * * DEBUG: section 33 Client-side Routines * AUTHOR: Duane Wessels @@ -2175,7 +2175,7 @@ clientProcessRequest(ConnStateData::Pointer &conn, HttpParser *hp, ClientSocketC #if LINUX_TPROXY - request->flags.tproxy = conn->port->tproxy; + request->flags.tproxy = conn->port->tproxy && need_linux_tproxy; #endif if (internalCheck(request->urlpath.buf())) { diff --git a/src/tools.cc b/src/tools.cc index 9db8c89842..9f890a52c9 100644 --- a/src/tools.cc +++ b/src/tools.cc @@ -1,6 +1,6 @@ /* - * $Id: tools.cc,v 1.278 2007/08/24 18:05:28 hno Exp $ + * $Id: tools.cc,v 1.279 2007/09/23 09:18:10 serassio Exp $ * * DEBUG: section 21 Misc Functions * AUTHOR: Harvest Derived @@ -40,7 +40,8 @@ #include "wordlist.h" #include "SquidTime.h" -#if LINUX_TPROXY +#ifdef _SQUID_LINUX_ +#if HAVE_SYS_CAPABILITY_H #undef _POSIX_SOURCE /* Ugly glue to get around linux header madness colliding with glibc */ #define _LINUX_TYPES_H @@ -48,6 +49,7 @@ typedef uint32_t __u32; #include #endif +#endif #if HAVE_SYS_PRCTL_H #include @@ -70,6 +72,7 @@ static void mail_warranty(void); 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 */ @@ -389,11 +392,12 @@ death(int sig) if (Config.adminEmail) mail_warranty(); - puts(dead_msg()); + + puts(dead_msg()); } if (shutting_down) - exit(1); + exit(1); abort(); } @@ -731,27 +735,9 @@ leave_suid(void) debugs(50, 0, "ALERT: setuid: " << 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)); + restoreCapabilities(1); - 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 #if HAVE_PRCTL && defined(PR_SET_DUMPABLE) /* Set Linux DUMPABLE flag */ if (Config.coredump_dir && prctl(PR_SET_DUMPABLE, 1) != 0) @@ -790,20 +776,15 @@ no_suid(void) uid_t uid; leave_suid(); uid = geteuid(); - debugs(21, 3, "leave_suid: PID " << getpid() << " giving up root priveleges forever"); -#if HAVE_SETRESUID - - if (setresuid(uid, uid, uid) < 0) - debugs(50, 1, "no_suid: setresuid: " << xstrerror()); - -#else + debugs(21, 3, "no_suid: PID " << getpid() << " giving up root priveleges forever"); setuid(0); if (setuid(uid) < 0) debugs(50, 1, "no_suid: setuid: " << xstrerror()); -#endif + restoreCapabilities(0); + #if HAVE_PRCTL && defined(PR_SET_DUMPABLE) /* Set Linux DUMPABLE flag */ if (Config.coredump_dir && prctl(PR_SET_DUMPABLE, 1) != 0) @@ -1340,13 +1321,82 @@ strwordquote(MemBuf * mb, const char *str) void keepCapabilities(void) { +#if HAVE_PRCTL && defined(PR_SET_KEEPCAPS) && HAVE_SYS_CAPABILITY_H + + 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) debugs(1, 1, "Error - tproxy support requires capability setting which has failed. Continuing without tproxy support"); - } + + need_linux_tproxy = 0; + +#endif + } #endif } + +static void +restoreCapabilities(int keep) +{ +#if defined(_SQUID_LINUX_) && HAVE_SYS_CAPABILITY_H + 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) { + debugs(50, 1, "Can't get current capabilities"); + goto nocap; + } + + if (head->version != _LINUX_CAPABILITY_VERSION) { + debugs(50, 1, "Invalid capability version " << head->version << " (expected " << _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) + debugs(50, 1, "Error enabling needed capabilities. Will continue without tproxy support"); + + need_linux_tproxy = 0; + +#endif + + } + +nocap: + xfree(head); + xfree(cap); +#else +#if LINUX_TPROXY + + if (need_linux_tproxy) + debugs(50, 1, "Missing needed capability support. Will continue without tproxy support"); + + need_linux_tproxy = 0; + +#endif + +#endif +}