You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2011/04/25 21:29:02 UTC

svn commit: r1096571 - in /trafficserver/traffic/trunk: lib/ts/Makefile.am lib/ts/ink_cap.cc lib/ts/ink_cap.h proxy/Main.cc proxy/http/HttpSM.cc proxy/http/HttpTransact.cc

Author: amc
Date: Mon Apr 25 19:29:02 2011
New Revision: 1096571

URL: http://svn.apache.org/viewvc?rev=1096571&view=rev
Log:
TS-748

Added:
    trafficserver/traffic/trunk/lib/ts/ink_cap.cc
    trafficserver/traffic/trunk/lib/ts/ink_cap.h
Modified:
    trafficserver/traffic/trunk/lib/ts/Makefile.am
    trafficserver/traffic/trunk/proxy/Main.cc
    trafficserver/traffic/trunk/proxy/http/HttpSM.cc
    trafficserver/traffic/trunk/proxy/http/HttpTransact.cc

Modified: trafficserver/traffic/trunk/lib/ts/Makefile.am
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/lib/ts/Makefile.am?rev=1096571&r1=1096570&r2=1096571&view=diff
==============================================================================
--- trafficserver/traffic/trunk/lib/ts/Makefile.am (original)
+++ trafficserver/traffic/trunk/lib/ts/Makefile.am Mon Apr 25 19:29:02 2011
@@ -23,7 +23,7 @@ TESTS = $(check_PROGRAMS)
 lib_LTLIBRARIES = libtsutil.la
 
 libtsutil_la_LDFLAGS = -no-undefined -version-info @TS_LIBTOOL_VERSION@
-libtsutil_la_LIBADD = @LIBOBJS@ @LIBPCRE@ @LIBSSL@ @LIBTCL@ @LIBRESOLV@ @LIBRT@ @LIBICONV@ @LIBSOCKET@ @LIBNSL@ -lc
+libtsutil_la_LIBADD = @LIBOBJS@ @LIBPCRE@ @LIBSSL@ @LIBTCL@ @LIBRESOLV@ @LIBRT@ @LIBICONV@ @LIBSOCKET@ @LIBNSL@ @LIBCAP@ -lc
 
 libtsutil_la_SOURCES = \
   Allocator.cc \
@@ -53,6 +53,7 @@ libtsutil_la_SOURCES = \
   ink_base64.cc \
   ink_base64.h \
   ink_bool.h \
+  ink_cap.cc ink_cap.h \
   ink_code.cc \
   ink_code.h \
   ink_defs.cc \

Added: trafficserver/traffic/trunk/lib/ts/ink_cap.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/lib/ts/ink_cap.cc?rev=1096571&view=auto
==============================================================================
--- trafficserver/traffic/trunk/lib/ts/ink_cap.cc (added)
+++ trafficserver/traffic/trunk/lib/ts/ink_cap.cc Mon Apr 25 19:29:02 2011
@@ -0,0 +1,61 @@
+# include "ink_config.h"
+# include "Diags.h"
+# include "ink_cap.h"
+
+# if TS_USE_POSIX_CAP
+# include <sys/capability.h>
+# include <sys/prctl.h>
+# endif
+
+void
+DebugCapabilities(char const* tag) {
+  if (is_debug_tag_set(tag)) {
+# if TS_USE_POSIX_CAP
+    cap_t caps = cap_get_proc();
+    char* caps_text = cap_to_text(caps, 0);
+# endif
+
+    Debug(tag,
+      "uid=%u, gid=%u, euid=%u, egid=%u"
+# if TS_USE_POSIX_CAP
+      ", caps %s thread 0x%x",
+# endif
+      (unsigned)getuid(), (unsigned)getgid(),
+      (unsigned)geteuid(), (unsigned)getegid()
+# if TS_USE_POSIX_CAP
+      ,caps_text
+      ,pthread_self()
+# endif
+    );
+
+# if TS_USE_POSIX_CAP
+    cap_free(caps_text);
+    cap_free(caps);
+# endif
+  }
+}
+
+int
+PreserveCapabilities() {
+  return prctl(PR_SET_KEEPCAPS, 1);
+}
+
+// Adjust the capabilities to only those needed.
+int
+RestrictCapabilities() {
+  int zret = 0; // return value.
+#if TS_USE_POSIX_CAP
+  cap_t caps = cap_get_proc(); // Only way to initialize it AFAICT.
+  cap_clear(caps);
+  // Capabilities we need.
+  cap_value_t cap_list[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };
+  static int const CAP_COUNT = sizeof(cap_list)/sizeof(*cap_list);
+
+  cap_set_flag(caps, CAP_INHERITABLE, CAP_COUNT, cap_list, CAP_SET);
+  cap_set_flag(caps, CAP_PERMITTED, CAP_COUNT, cap_list, CAP_SET);
+  cap_set_flag(caps, CAP_EFFECTIVE, CAP_COUNT, cap_list, CAP_SET);
+  zret = cap_set_proc(caps);
+  cap_free(caps);
+#endif
+  return zret;
+}

Added: trafficserver/traffic/trunk/lib/ts/ink_cap.h
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/lib/ts/ink_cap.h?rev=1096571&view=auto
==============================================================================
--- trafficserver/traffic/trunk/lib/ts/ink_cap.h (added)
+++ trafficserver/traffic/trunk/lib/ts/ink_cap.h Mon Apr 25 19:29:02 2011
@@ -0,0 +1,39 @@
+/** @file
+
+  POSIX Capability related utilities.
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+ */
+
+#if !defined (_ink_cap_h_)
+#define _ink_cap_h_
+
+/// Generate a debug message with the current capabilities for the process.
+extern void DebugCapabilities(
+  char const* tag ///< Debug message tag.
+);
+/// Set capabilities to persist across change of user id.
+/// @return 0 on success, non-zero otherwise.
+extern int PreserveCapabilities();
+/// Initialize and restrict the capabilities of a thread.
+/// @return 0 on success, non-zero otherwise.
+extern int RestrictCapabilities();
+
+#endif

Modified: trafficserver/traffic/trunk/proxy/Main.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/Main.cc?rev=1096571&r1=1096570&r2=1096571&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/Main.cc (original)
+++ trafficserver/traffic/trunk/proxy/Main.cc Mon Apr 25 19:29:02 2011
@@ -47,10 +47,6 @@ extern "C" int plock(int);
 #include <mcheck.h>
 #endif
 
-#if TS_USE_POSIX_CAP
-#include <sys/capability.h>
-#endif
-
 #include "Main.h"
 #include "signals.h"
 #include "Error.h"
@@ -95,6 +91,8 @@ extern "C" int plock(int);
 
 #include "I_Tasks.h"
 
+#include <ts/ink_cap.h>
+
 #if TS_HAS_PROFILER
 #include <google/profiler.h>
 #endif
@@ -1061,23 +1059,6 @@ init_core_size()
   }
 }
 
-#if TS_USE_POSIX_CAP
-// Restore the effective capabilities that we need.
-int
-restoreCapabilities() {
-  int zret = 0; // return value.
-  cap_t cap_set = cap_get_proc(); // current capabilities
-  // Capabilities to restore.
-  cap_value_t cap_list[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };
-  static int const CAP_COUNT = sizeof(cap_list)/sizeof(*cap_list);
-
-  cap_set_flag(cap_set, CAP_EFFECTIVE, CAP_COUNT, cap_list, CAP_SET);
-  zret = cap_set_proc(cap_set);
-  cap_free(cap_set);
-  return zret;
-}
-#endif
-
 static void
 adjust_sys_settings(void)
 {
@@ -1110,9 +1091,6 @@ adjust_sys_settings(void)
 #endif
 
 #endif  // linux check
-#if TS_USE_POSIX_CAP
-  restoreCapabilities();
-#endif
 }
 
 struct ShowStats: public Continuation
@@ -1659,6 +1637,26 @@ main(int argc, char **argv)
   if (!num_task_threads)
     TS_ReadConfigInteger(num_task_threads, "proxy.config.task_threads");
 
+  // change the user of the process
+  // do this before we start threads so we control the user id of the
+  // threads (rather than have it change asynchronously during thread
+  // execution). We also need to do this before we fiddle with capabilities
+  // as those are thread local and if we change the user id it will
+  // modified the capabilities in other threads, breaking things.
+  const long max_login =  sysconf(_SC_LOGIN_NAME_MAX) <= 0 ? _POSIX_LOGIN_NAME_MAX :  sysconf(_SC_LOGIN_NAME_MAX);
+  char *user = (char *)xmalloc(max_login);
+  *user = '\0';
+  if ((TS_ReadConfigString(user, "proxy.config.admin.user_id",
+                           max_login) == REC_ERR_OKAY) &&
+                           user[0] != '\0' &&
+                           strcmp(user, "#-1")) {
+    PreserveCapabilities();
+    change_uid_gid(user);
+    RestrictCapabilities();
+    xfree(user);
+  }
+  DebugCapabilities("server");
+
   // This call is required for win_9xMe
   //without this this_ethread() is failing when
   //start_HttpProxyServer is called from main thread
@@ -1941,22 +1939,6 @@ main(int argc, char **argv)
     run_AutoStop();
   }
 
-  // change the user of the process
-  const long max_login =  sysconf(_SC_LOGIN_NAME_MAX) <= 0 ? _POSIX_LOGIN_NAME_MAX :  sysconf(_SC_LOGIN_NAME_MAX);
-  char *user = (char *)xmalloc(max_login);
-  *user = '\0';
-  if ((TS_ReadConfigString(user, "proxy.config.admin.user_id",
-                           max_login) == REC_ERR_OKAY) &&
-                           user[0] != '\0' &&
-                           strcmp(user, "#-1")) {
-    change_uid_gid(user);
-    xfree(user);
-  }
-  Debug("server",
-        "running as uid=%u, gid=%u, effective uid=%u, gid=%u",
-        (unsigned)getuid(), (unsigned)getgid(),
-        (unsigned)geteuid(), (unsigned)getegid());
-
   this_thread()->execute();
 }
 

Modified: trafficserver/traffic/trunk/proxy/http/HttpSM.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/http/HttpSM.cc?rev=1096571&r1=1096570&r2=1096571&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/http/HttpSM.cc (original)
+++ trafficserver/traffic/trunk/proxy/http/HttpSM.cc Mon Apr 25 19:29:02 2011
@@ -4396,17 +4396,15 @@ void
 HttpSM::mark_host_failure(HostDBInfo * info, time_t time_down)
 {
   if (info->app.http_data.last_failure == 0) {
-    int url_len;
-    char *url_str;
-
-    URL *url = t_state.hdr_info.client_request.url_get();
-    url_str = url->string_get(&t_state.arena, &url_len);
+    char *url_str = t_state.hdr_info.client_request.url_string_get(&t_state.arena, 0);
     Log::error("CONNECT: could not connect to %u.%u.%u.%u "
                "for '%s' (setting last failure time)",
                ((unsigned char *) &t_state.current.server->ip)[0],
                ((unsigned char *) &t_state.current.server->ip)[1],
                ((unsigned char *) &t_state.current.server->ip)[2],
-               ((unsigned char *) &t_state.current.server->ip)[3], url_str);
+               ((unsigned char *) &t_state.current.server->ip)[3],
+               url_str ? url_str : "<none>"
+    );
     if (url_str)
       t_state.arena.str_free(url_str);
   }

Modified: trafficserver/traffic/trunk/proxy/http/HttpTransact.cc
URL: http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/http/HttpTransact.cc?rev=1096571&r1=1096570&r2=1096571&view=diff
==============================================================================
--- trafficserver/traffic/trunk/proxy/http/HttpTransact.cc (original)
+++ trafficserver/traffic/trunk/proxy/http/HttpTransact.cc Mon Apr 25 19:29:02 2011
@@ -832,7 +832,6 @@ HttpTransact::EndRemapRequest(State* s)
   Debug("http_trans", "START HttpTransact::EndRemapRequest");
 
   HTTPHdr *incoming_request = &s->hdr_info.client_request;
-  //URL *url = incoming_request->url_get();
   int method = incoming_request->method_get_wksidx();
   int host_len;
   const char *host = incoming_request->host_get(&host_len);
@@ -955,12 +954,6 @@ done:
     TRANSACT_RETURN(PROXY_INTERNAL_CACHE_NOOP, NULL);
   }
 
-  if (s->reverse_proxy) {
-    Debug("url_rewrite", "s->reverse_proxy is true");
-  } else {
-    Debug("url_rewrite", "s->reverse_proxy is false");
-  }
-
   if (is_debug_tag_set("http_chdr_describe") || is_debug_tag_set("http_trans") || is_debug_tag_set("url_rewrite")) {
     Debug("http_trans", "After Remapping:");
     obj_describe(s->hdr_info.client_request.m_http, 1);
@@ -3769,8 +3762,7 @@ HttpTransact::retry_server_connection_no
   ink_debug_assert(s->current.attempts <= max_retries);
   ink_debug_assert(s->current.server->connect_failure != 0);
 
-  URL *url = s->hdr_info.client_request.url_get();
-  char *url_string = url->valid()? url->string_get(&s->arena) : NULL;
+  char *url_string = s->hdr_info.client_request.url_string_get(&s->arena) : NULL;
 
   Debug("http_trans", "[%d] failed to connect [%d] to %u.%u.%u.%u", s->current.attempts, conn_state,
         PRINT_IP(s->current.server->ip));



Re: svn commit: r1096571 - in /trafficserver/traffic/trunk: lib/ts/Makefile.am lib/ts/ink_cap.cc lib/ts/ink_cap.h proxy/Main.cc proxy/http/HttpSM.cc proxy/http/HttpTransact.cc

Posted by "Alan M. Carroll" <am...@network-geographics.com>.
No, CAP_NET_ADMIN is required to enable transparency on a socket. I think multicasting worked before this was added.

Tuesday, April 26, 2011, 6:15:49 PM, you wrote:


>> +  // Capabilities we need.
>> +  cap_value_t cap_list[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };

> I suppose we need cap_net_admin for multicasting between two cluster nodes?


Re: svn commit: r1096571 - in /trafficserver/traffic/trunk: lib/ts/Makefile.am lib/ts/ink_cap.cc lib/ts/ink_cap.h proxy/Main.cc proxy/http/HttpSM.cc proxy/http/HttpTransact.cc

Posted by "Alan M. Carroll" <am...@network-geographics.com>.
Tuesday, April 26, 2011, 5:45:46 PM, you wrote:
> So your code is (mostly) fine, except for the error reported:

> WARNING: Unable to access() local state directory '/usr/local/ats_218/var/trafficserver': 13, Permission denied
> [Apr 26 16:26:06.570] Server {1079999328} WARNING:  Please set 'proxy.config.local_state_dir' to allow statistics collection

> This either means we need to adapt the permissions in this directory,
> or we need to additionally give CAP_DAC_OVERRIDE.
> I'd rather not do the latter.

I don't see why. I've been trying to track this down and it makes no sense to me. I added a DebugCapabilities to the permission failure and it reports that the uid/guid is 0/0 and the euid/egid is 65534/65534 (nobody/nogroup), and the capabilities are as expected (CAP_NET_ADMIN and CAP_NET_BIND_SERVICE). The directory is 755, owned by nobody/nogroup. I don't see why permission is denied, unless it's because fsuid is still 0 (which would seem to be a kernel bug). Let me try working with that.


Re: svn commit: r1096571 - in /trafficserver/traffic/trunk: lib/ts/Makefile.am lib/ts/ink_cap.cc lib/ts/ink_cap.h proxy/Main.cc proxy/http/HttpSM.cc proxy/http/HttpTransact.cc

Posted by Igor Galić <i....@brainsware.org>.
> +  // Capabilities we need.
> +  cap_value_t cap_list[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };

I suppose we need cap_net_admin for multicasting between two cluster nodes?

i

-- 
Igor Galić

Tel: +43 (0) 664 886 22 883
Mail: i.galic@brainsware.org
URL: http://brainsware.org/

Re: svn commit: r1096571 - in /trafficserver/traffic/trunk: lib/ts/Makefile.am lib/ts/ink_cap.cc lib/ts/ink_cap.h proxy/Main.cc proxy/http/HttpSM.cc proxy/http/HttpTransact.cc

Posted by "Alan M. Carroll" <am...@network-geographics.com>.
I think it's a side effect. I wasn't sure if any one except my client was seeing the problem. I have a potential fix.

The problem is related to the particular OS. On FC it works. On (for instance) Debian this problem arises. The difference is that on the latter the server seems to start with a real uid of 0 and an effective uid of nobody. This causes the setuid calls in Main.cc to fail, but because that's been moved forward the logging fails (because the log isn't available yet). This cascades in to this problem but I still don't see why the permission is denied -- the effective user id the same as the owner of the directory.

However, when I put a tweak in to recover an effective uid of 0 and then the switch to a real and effective uid of nobody succeeds and then this permission check passes as well. Is Debian using the real user id to check file permission and not the effective user id?

I will provide a patch as soon as I can. I can't just commit the changes I did at the client because there's a lot of other carp from my experiments.

Wednesday, April 27, 2011, 3:10:26 AM, you wrote:

> I don't know if it's related to this change, but when running trunk, the
> startup script fails, running just traffic_manager shows this problem:

> [Apr 27 02:09:05.217] Server {47200722737184} NOTE: cache clustering disabled
> unable to access() log dir'/opt/ats/var/log/trafficserver': 13, Permission
> denied
> please set 'proxy.config.log.logfile_dir'


Re: svn commit: r1096571 - in /trafficserver/traffic/trunk: lib/ts/Makefile.am lib/ts/ink_cap.cc lib/ts/ink_cap.h proxy/Main.cc proxy/http/HttpSM.cc proxy/http/HttpTransact.cc

Posted by Leif Hedstrom <le...@ogre.com>.
I don't know if it's related to this change, but when running trunk, the
startup script fails, running just traffic_manager shows this problem:

[Apr 27 02:09:05.217] Server {47200722737184} NOTE: cache clustering disabled
unable to access() log dir'/opt/ats/var/log/trafficserver': 13, Permission
denied
please set 'proxy.config.log.logfile_dir'


I'm fairly certain this is a new problem, I've done this successfully in
the past.

Cheers,

-- leif



Re: svn commit: r1096571 - in /trafficserver/traffic/trunk: lib/ts/Makefile.am lib/ts/ink_cap.cc lib/ts/ink_cap.h proxy/Main.cc proxy/http/HttpSM.cc proxy/http/HttpTransact.cc

Posted by "Alan M. Carroll" <am...@network-geographics.com>.
Tuesday, April 26, 2011, 6:14:14 PM, you wrote:


> Now, while these things are named POSIX capabilities, they are
> they are about as far away from standardization as can be.

> We should use this chance to generalize the existing interface so that
> we can cater all (three, six, seventeen -- however many different interfaces pop up
> until the new - incompatible with everything existing POSIX 1003.1-2008 is adopted).

Yes, that's one of the reasons I moved the capability logic over to ink_cap rather than leaving it exposed in Main.cc. It also simplifies the #define carp - we just call it from Main.cc and make the functions empty if capabilities aren't enabled.


Re: svn commit: r1096571 - in /trafficserver/traffic/trunk: lib/ts/Makefile.am lib/ts/ink_cap.cc lib/ts/ink_cap.h proxy/Main.cc proxy/http/HttpSM.cc proxy/http/HttpTransact.cc

Posted by Igor Galić <i....@brainsware.org>.
Now, while these things are named POSIX capabilities, they are
they are about as far away from standardization as can be.

> > +# if TS_USE_POSIX_CAP

I know of 3 different implementations, none of which are compatible:

Linux: capabilities(7)
Solaris: privileges(5) -- while this offers much more fine-grained sets,
but we'll only need the equivalents of Linux Capabilities: BASIC + PRIV_NET_PRIVADDR
FreeBSD: posix1e(3) - capabilities are still being worked on and are in the begging stage of being merged to -CURRENT

We should use this chance to generalize the existing interface so that
we can cater all (three, six, seventeen -- however many different interfaces pop up
until the new - incompatible with everything existing POSIX 1003.1-2008 is adopted).
-- 
Igor Galić

Tel: +43 (0) 664 886 22 883
Mail: i.galic@brainsware.org
URL: http://brainsware.org/

Re: svn commit: r1096571 - in /trafficserver/traffic/trunk: lib/ts/Makefile.am lib/ts/ink_cap.cc lib/ts/ink_cap.h proxy/Main.cc proxy/http/HttpSM.cc proxy/http/HttpTransact.cc

Posted by Igor Galić <i....@brainsware.org>.

----- Original Message -----
> Author: amc
> Date: Mon Apr 25 19:29:02 2011
> New Revision: 1096571
> 
> URL: http://svn.apache.org/viewvc?rev=1096571&view=rev
> Log:
> TS-748
> 
> Added:
>     trafficserver/traffic/trunk/lib/ts/ink_cap.cc
>     trafficserver/traffic/trunk/lib/ts/ink_cap.h
> Modified:
>     trafficserver/traffic/trunk/lib/ts/Makefile.am
>     trafficserver/traffic/trunk/proxy/Main.cc
>     trafficserver/traffic/trunk/proxy/http/HttpSM.cc
>     trafficserver/traffic/trunk/proxy/http/HttpTransact.cc
> 
> Modified: trafficserver/traffic/trunk/lib/ts/Makefile.am
> URL:
> http://svn.apache.org/viewvc/trafficserver/traffic/trunk/lib/ts/Makefile.am?rev=1096571&r1=1096570&r2=1096571&view=diff
> ==============================================================================
> --- trafficserver/traffic/trunk/lib/ts/Makefile.am (original)
> +++ trafficserver/traffic/trunk/lib/ts/Makefile.am Mon Apr 25
> 19:29:02 2011
> @@ -23,7 +23,7 @@ TESTS = $(check_PROGRAMS)
>  lib_LTLIBRARIES = libtsutil.la
>  
>  libtsutil_la_LDFLAGS = -no-undefined -version-info
>  @TS_LIBTOOL_VERSION@
> -libtsutil_la_LIBADD = @LIBOBJS@ @LIBPCRE@ @LIBSSL@ @LIBTCL@
> @LIBRESOLV@ @LIBRT@ @LIBICONV@ @LIBSOCKET@ @LIBNSL@ -lc
> +libtsutil_la_LIBADD = @LIBOBJS@ @LIBPCRE@ @LIBSSL@ @LIBTCL@
> @LIBRESOLV@ @LIBRT@ @LIBICONV@ @LIBSOCKET@ @LIBNSL@ @LIBCAP@ -lc
>  
>  libtsutil_la_SOURCES = \
>    Allocator.cc \
> @@ -53,6 +53,7 @@ libtsutil_la_SOURCES = \
>    ink_base64.cc \
>    ink_base64.h \
>    ink_bool.h \
> +  ink_cap.cc ink_cap.h \
>    ink_code.cc \
>    ink_code.h \
>    ink_defs.cc \
> 
> Added: trafficserver/traffic/trunk/lib/ts/ink_cap.cc
> URL:
> http://svn.apache.org/viewvc/trafficserver/traffic/trunk/lib/ts/ink_cap.cc?rev=1096571&view=auto
> ==============================================================================
> --- trafficserver/traffic/trunk/lib/ts/ink_cap.cc (added)
> +++ trafficserver/traffic/trunk/lib/ts/ink_cap.cc Mon Apr 25 19:29:02
> 2011
> @@ -0,0 +1,61 @@
> +# include "ink_config.h"
> +# include "Diags.h"
> +# include "ink_cap.h"
> +
> +# if TS_USE_POSIX_CAP
> +# include <sys/capability.h>
> +# include <sys/prctl.h>
> +# endif
> +
> +void
> +DebugCapabilities(char const* tag) {
> +  if (is_debug_tag_set(tag)) {
> +# if TS_USE_POSIX_CAP
> +    cap_t caps = cap_get_proc();
> +    char* caps_text = cap_to_text(caps, 0);
> +# endif
> +
> +    Debug(tag,
> +      "uid=%u, gid=%u, euid=%u, egid=%u"
> +# if TS_USE_POSIX_CAP
> +      ", caps %s thread 0x%x",
> +# endif
> +      (unsigned)getuid(), (unsigned)getgid(),
> +      (unsigned)geteuid(), (unsigned)getegid()
> +# if TS_USE_POSIX_CAP
> +      ,caps_text
> +      ,pthread_self()
> +# endif
> +    );
> +
> +# if TS_USE_POSIX_CAP
> +    cap_free(caps_text);
> +    cap_free(caps);
> +# endif
> +  }
> +}
> +
> +int
> +PreserveCapabilities() {
> +  return prctl(PR_SET_KEEPCAPS, 1);
> +}
> +
> +// Adjust the capabilities to only those needed.
> +int
> +RestrictCapabilities() {
> +  int zret = 0; // return value.
> +#if TS_USE_POSIX_CAP
> +  cap_t caps = cap_get_proc(); // Only way to initialize it AFAICT.

No it's not, see below.

> +  cap_clear(caps);

vsftpd uses this only to check if capabilities are available:

  #else /* VSF_SYSDEP_HAVE_LIBCAP */
static int
do_checkcap(void)
{
  cap_t current_caps = cap_get_proc();
  cap_free(current_caps);
  if (current_caps != NULL)
  {
    return 1;
  }
  return 0;
}


> +  // Capabilities we need.
> +  cap_value_t cap_list[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };
> +  static int const CAP_COUNT = sizeof(cap_list)/sizeof(*cap_list);
> +
> +  cap_set_flag(caps, CAP_INHERITABLE, CAP_COUNT, cap_list, CAP_SET);
> +  cap_set_flag(caps, CAP_PERMITTED, CAP_COUNT, cap_list, CAP_SET);
> +  cap_set_flag(caps, CAP_EFFECTIVE, CAP_COUNT, cap_list, CAP_SET);
> +  zret = cap_set_proc(caps);
> +  cap_free(caps);

Then uses this to set the caps needed:

void
vsf_sysdep_adopt_capabilities(unsigned int caps)
{
  int retval;
  cap_value_t cap_value;
  cap_t adopt_caps = cap_init();
  if (caps & kCapabilityCAP_CHOWN)
  {
    cap_value = CAP_CHOWN;
    cap_set_flag(adopt_caps, CAP_EFFECTIVE, 1, &cap_value, CAP_SET);
    cap_set_flag(adopt_caps, CAP_PERMITTED, 1, &cap_value, CAP_SET);
  }
  if (caps & kCapabilityCAP_NET_BIND_SERVICE)
  {
    cap_value = CAP_NET_BIND_SERVICE;
    cap_set_flag(adopt_caps, CAP_EFFECTIVE, 1, &cap_value, CAP_SET);
    cap_set_flag(adopt_caps, CAP_PERMITTED, 1, &cap_value, CAP_SET);
  }
  retval = cap_set_proc(adopt_caps);
  if (retval != 0)
  {
    die("cap_set_proc");
  }
  cap_free(adopt_caps);
}


The only thing done differently is that it sets one CAP at a time.
Also it neglects to set the CAPs inheritable, because it's not needed
in this context it doesn't want its children to spawn daemons of their
own. So your code is (mostly) fine, except for the error reported:

WARNING: Unable to access() local state directory '/usr/local/ats_218/var/trafficserver': 13, Permission denied
[Apr 26 16:26:06.570] Server {1079999328} WARNING:  Please set 'proxy.config.local_state_dir' to allow statistics collection

This either means we need to adapt the permissions in this directory,
or we need to additionally give CAP_DAC_OVERRIDE.
I'd rather not do the latter.


> +#endif
> +  return zret;
> +}
> 
> Added: trafficserver/traffic/trunk/lib/ts/ink_cap.h
> URL:
> http://svn.apache.org/viewvc/trafficserver/traffic/trunk/lib/ts/ink_cap.h?rev=1096571&view=auto
> ==============================================================================
> --- trafficserver/traffic/trunk/lib/ts/ink_cap.h (added)
> +++ trafficserver/traffic/trunk/lib/ts/ink_cap.h Mon Apr 25 19:29:02
> 2011
> @@ -0,0 +1,39 @@
> +/** @file
> +
> +  POSIX Capability related utilities.
> +
> +  @section license License
> +
> +  Licensed to the Apache Software Foundation (ASF) under one
> +  or more contributor license agreements.  See the NOTICE file
> +  distributed with this work for additional information
> +  regarding copyright ownership.  The ASF licenses this file
> +  to you under the Apache License, Version 2.0 (the
> +  "License"); you may not use this file except in compliance
> +  with the License.  You may obtain a copy of the License at
> +
> +      http://www.apache.org/licenses/LICENSE-2.0
> +
> +  Unless required by applicable law or agreed to in writing,
> software
> +  distributed under the License is distributed on an "AS IS" BASIS,
> +  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> +  See the License for the specific language governing permissions
> and
> +  limitations under the License.
> +
> + */
> +
> +#if !defined (_ink_cap_h_)
> +#define _ink_cap_h_
> +
> +/// Generate a debug message with the current capabilities for the
> process.
> +extern void DebugCapabilities(
> +  char const* tag ///< Debug message tag.
> +);
> +/// Set capabilities to persist across change of user id.
> +/// @return 0 on success, non-zero otherwise.
> +extern int PreserveCapabilities();
> +/// Initialize and restrict the capabilities of a thread.
> +/// @return 0 on success, non-zero otherwise.
> +extern int RestrictCapabilities();
> +
> +#endif
> 
> Modified: trafficserver/traffic/trunk/proxy/Main.cc
> URL:
> http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/Main.cc?rev=1096571&r1=1096570&r2=1096571&view=diff
> ==============================================================================
> --- trafficserver/traffic/trunk/proxy/Main.cc (original)
> +++ trafficserver/traffic/trunk/proxy/Main.cc Mon Apr 25 19:29:02
> 2011
> @@ -47,10 +47,6 @@ extern "C" int plock(int);
>  #include <mcheck.h>
>  #endif
>  
> -#if TS_USE_POSIX_CAP
> -#include <sys/capability.h>
> -#endif
> -
>  #include "Main.h"
>  #include "signals.h"
>  #include "Error.h"
> @@ -95,6 +91,8 @@ extern "C" int plock(int);
>  
>  #include "I_Tasks.h"
>  
> +#include <ts/ink_cap.h>
> +
>  #if TS_HAS_PROFILER
>  #include <google/profiler.h>
>  #endif
> @@ -1061,23 +1059,6 @@ init_core_size()
>    }
>  }
>  
> -#if TS_USE_POSIX_CAP
> -// Restore the effective capabilities that we need.
> -int
> -restoreCapabilities() {
> -  int zret = 0; // return value.
> -  cap_t cap_set = cap_get_proc(); // current capabilities
> -  // Capabilities to restore.
> -  cap_value_t cap_list[] = { CAP_NET_ADMIN, CAP_NET_BIND_SERVICE };
> -  static int const CAP_COUNT = sizeof(cap_list)/sizeof(*cap_list);
> -
> -  cap_set_flag(cap_set, CAP_EFFECTIVE, CAP_COUNT, cap_list,
> CAP_SET);
> -  zret = cap_set_proc(cap_set);
> -  cap_free(cap_set);
> -  return zret;
> -}
> -#endif
> -
>  static void
>  adjust_sys_settings(void)
>  {
> @@ -1110,9 +1091,6 @@ adjust_sys_settings(void)
>  #endif
>  
>  #endif  // linux check
> -#if TS_USE_POSIX_CAP
> -  restoreCapabilities();
> -#endif
>  }
>  
>  struct ShowStats: public Continuation
> @@ -1659,6 +1637,26 @@ main(int argc, char **argv)
>    if (!num_task_threads)
>      TS_ReadConfigInteger(num_task_threads,
>      "proxy.config.task_threads");
>  
> +  // change the user of the process
> +  // do this before we start threads so we control the user id of
> the
> +  // threads (rather than have it change asynchronously during
> thread
> +  // execution). We also need to do this before we fiddle with
> capabilities
> +  // as those are thread local and if we change the user id it will
> +  // modified the capabilities in other threads, breaking things.
> +  const long max_login =  sysconf(_SC_LOGIN_NAME_MAX) <= 0 ?
> _POSIX_LOGIN_NAME_MAX :  sysconf(_SC_LOGIN_NAME_MAX);
> +  char *user = (char *)xmalloc(max_login);
> +  *user = '\0';
> +  if ((TS_ReadConfigString(user, "proxy.config.admin.user_id",
> +                           max_login) == REC_ERR_OKAY) &&
> +                           user[0] != '\0' &&
> +                           strcmp(user, "#-1")) {
> +    PreserveCapabilities();
> +    change_uid_gid(user);
> +    RestrictCapabilities();
> +    xfree(user);
> +  }
> +  DebugCapabilities("server");
> +
>    // This call is required for win_9xMe
>    //without this this_ethread() is failing when
>    //start_HttpProxyServer is called from main thread
> @@ -1941,22 +1939,6 @@ main(int argc, char **argv)
>      run_AutoStop();
>    }
>  
> -  // change the user of the process
> -  const long max_login =  sysconf(_SC_LOGIN_NAME_MAX) <= 0 ?
> _POSIX_LOGIN_NAME_MAX :  sysconf(_SC_LOGIN_NAME_MAX);
> -  char *user = (char *)xmalloc(max_login);
> -  *user = '\0';
> -  if ((TS_ReadConfigString(user, "proxy.config.admin.user_id",
> -                           max_login) == REC_ERR_OKAY) &&
> -                           user[0] != '\0' &&
> -                           strcmp(user, "#-1")) {
> -    change_uid_gid(user);
> -    xfree(user);
> -  }
> -  Debug("server",
> -        "running as uid=%u, gid=%u, effective uid=%u, gid=%u",
> -        (unsigned)getuid(), (unsigned)getgid(),
> -        (unsigned)geteuid(), (unsigned)getegid());
> -
>    this_thread()->execute();
>  }
>  
> 
> Modified: trafficserver/traffic/trunk/proxy/http/HttpSM.cc
> URL:
> http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/http/HttpSM.cc?rev=1096571&r1=1096570&r2=1096571&view=diff
> ==============================================================================
> --- trafficserver/traffic/trunk/proxy/http/HttpSM.cc (original)
> +++ trafficserver/traffic/trunk/proxy/http/HttpSM.cc Mon Apr 25
> 19:29:02 2011
> @@ -4396,17 +4396,15 @@ void
>  HttpSM::mark_host_failure(HostDBInfo * info, time_t time_down)
>  {
>    if (info->app.http_data.last_failure == 0) {
> -    int url_len;
> -    char *url_str;
> -
> -    URL *url = t_state.hdr_info.client_request.url_get();
> -    url_str = url->string_get(&t_state.arena, &url_len);
> +    char *url_str =
> t_state.hdr_info.client_request.url_string_get(&t_state.arena, 0);
>      Log::error("CONNECT: could not connect to %u.%u.%u.%u "
>                 "for '%s' (setting last failure time)",
>                 ((unsigned char *) &t_state.current.server->ip)[0],
>                 ((unsigned char *) &t_state.current.server->ip)[1],
>                 ((unsigned char *) &t_state.current.server->ip)[2],
> -               ((unsigned char *) &t_state.current.server->ip)[3],
> url_str);
> +               ((unsigned char *) &t_state.current.server->ip)[3],
> +               url_str ? url_str : "<none>"
> +    );
>      if (url_str)
>        t_state.arena.str_free(url_str);
>    }
> 
> Modified: trafficserver/traffic/trunk/proxy/http/HttpTransact.cc
> URL:
> http://svn.apache.org/viewvc/trafficserver/traffic/trunk/proxy/http/HttpTransact.cc?rev=1096571&r1=1096570&r2=1096571&view=diff
> ==============================================================================
> --- trafficserver/traffic/trunk/proxy/http/HttpTransact.cc (original)
> +++ trafficserver/traffic/trunk/proxy/http/HttpTransact.cc Mon Apr 25
> 19:29:02 2011
> @@ -832,7 +832,6 @@ HttpTransact::EndRemapRequest(State* s)
>    Debug("http_trans", "START HttpTransact::EndRemapRequest");
>  
>    HTTPHdr *incoming_request = &s->hdr_info.client_request;
> -  //URL *url = incoming_request->url_get();
>    int method = incoming_request->method_get_wksidx();
>    int host_len;
>    const char *host = incoming_request->host_get(&host_len);
> @@ -955,12 +954,6 @@ done:
>      TRANSACT_RETURN(PROXY_INTERNAL_CACHE_NOOP, NULL);
>    }
>  
> -  if (s->reverse_proxy) {
> -    Debug("url_rewrite", "s->reverse_proxy is true");
> -  } else {
> -    Debug("url_rewrite", "s->reverse_proxy is false");
> -  }
> -
>    if (is_debug_tag_set("http_chdr_describe") ||
>    is_debug_tag_set("http_trans") ||
>    is_debug_tag_set("url_rewrite")) {
>      Debug("http_trans", "After Remapping:");
>      obj_describe(s->hdr_info.client_request.m_http, 1);
> @@ -3769,8 +3762,7 @@ HttpTransact::retry_server_connection_no
>    ink_debug_assert(s->current.attempts <= max_retries);
>    ink_debug_assert(s->current.server->connect_failure != 0);
>  
> -  URL *url = s->hdr_info.client_request.url_get();
> -  char *url_string = url->valid()? url->string_get(&s->arena) :
> NULL;
> +  char *url_string =
> s->hdr_info.client_request.url_string_get(&s->arena) : NULL;
>  
>    Debug("http_trans", "[%d] failed to connect [%d] to %u.%u.%u.%u",
>    s->current.attempts, conn_state,
>          PRINT_IP(s->current.server->ip));
> 
> 
> 

-- 
Igor Galić

Tel: +43 (0) 664 886 22 883
Mail: i.galic@brainsware.org
URL: http://brainsware.org/