Patch for chroot() in 2.5STABLE1

From: Andrew Rucker Jones <arjones@dont-contact.us>
Date: Thu, 03 Oct 2002 21:15:48 +0200

Hi everybody!
        Don't know if i managed to get subscribed to the list, but i'll try
posting. :)
        I find Squid's chroot() function lacking, so i recoded it. The patch is
attached.

Primary disadvantage of the old chroot() method: The configuration file
was parsed before doing a chroot(), so many files and directories had to
be mirrored both inside of the chroot() jail and outside. It is also
confusing to someone setting Squid up and writing the config file: You
never know if the path You are typing is relative to the chroot() jail
or not. Squid's method also doesn't follow the convention set by other
chroot()able software like BIND and Snort (not that it really has to,
but i think it would be nice).

Disadvantages of the new method (which uses a command line switch and
immediately performs the chroot):
- The -f switch will almost always have to be used. Not a problem,
because most people have a startup script.
- The -t switch always has to be used. Ditto about the script.
- More libraries are needed in the chroot() jail. Don't see this as a
problem, because if You go to the trouble to set it up to begin with, a
couple more libraries aren't going to hurt You.

Besides that, i fixed the spelling and grammar errors i ran across, and
i took out the part in the man page about reading the FAQ that comes
with the distribution, because the FAQ doesn't seem to come with the
distribution anymore (or i'm blind).

Two small points about the Squid Web pages:
http://www.squid-cache.org/Devel/ includes a reference to
squid-dev-request@squid-cache.org, but it needs to be
squid-dev-subscribe@squid-cache.org.
http://www.squid-cache.org/Devel/guidelines.html claims that indent
should be run with the options -npsl AND -psl. Somehow i doubt it,
unless i'm misreading the indent man page.

Finally, is there still interest in finding an SNMP maintainer? I would
be interested in being that person, but i make no promises yet. Just
seeing if there's still a need.

                        -&

-- 
GPG key / Schlüssel -- http://simultan.dyndns.org/~arjones/gpgkey.txt
Encrypt everything. / Alles verschlüsseln.

diff -Nur squid-2.5.STABLE1.orig/doc/squid.8 squid-2.5.STABLE1/doc/squid.8
--- squid-2.5.STABLE1.orig/doc/squid.8 Mon Dec 18 22:54:18 2000
+++ squid-2.5.STABLE1/doc/squid.8 Thu Oct 3 17:59:16 2002
@@ -10,6 +10,8 @@
 ] [
 .BI \-f " config-file"
 ] [
+.BI \-t " directory"
+] [
 \-[
 .B au
 ]
@@ -54,8 +56,7 @@
 on how to configure
 .B squid
 see the file
-.BI /etc/squid/squid.conf,
-the FAQ included with the distribution
+.BI /etc/squid/squid.conf
 and the documentation at the
 .B squid
 home page http://www.squid-cache.org
@@ -75,6 +76,8 @@
 (except -k parse) and exit.
 .IP -s
 Enable logging to syslog.
+.IP "-t directory"
+Perform a chroot() to the given directory immediately upon startup.
 .IP "-u port"
 Specify ICP port number (default: 3130), disable with 0.
 .IP -v
diff -Nur squid-2.5.STABLE1.orig/src/cf.data.pre squid-2.5.STABLE1/src/cf.data.pre
--- squid-2.5.STABLE1.orig/src/cf.data.pre Wed Sep 4 15:35:01 2002
+++ squid-2.5.STABLE1/src/cf.data.pre Tue Oct 1 21:24:10 2002
@@ -3680,18 +3680,6 @@
         time. By default it is set to 10% of the Cache Digest.
 DOC_END
 
-NAME: chroot
-TYPE: string
-LOC: Config.chroot_dir
-DEFAULT: none
-DOC_START
- Use this to have Squid do a chroot() while initializing. This
- also causes Squid to fully drop root privileges after
- initializing. This means, for example, that if you use a HTTP
- port less than 1024 and try to reconfigure, you will get an
- error.
-DOC_END
-
 NAME: client_persistent_connections
 TYPE: onoff
 LOC: Config.onoff.client_pconns
diff -Nur squid-2.5.STABLE1.orig/src/main.c squid-2.5.STABLE1/src/main.c
--- squid-2.5.STABLE1.orig/src/main.c Sun Jul 14 19:20:49 2002
+++ squid-2.5.STABLE1/src/main.c Thu Oct 3 19:21:00 2002
@@ -74,6 +74,7 @@
 static int checkRunningPid(void);
 
 static const char *squid_start_script = "squid_start";
+static char* chroot_dir = NULL;
 
 #if TEST_ACCESS
 #include "test_access.c"
@@ -93,6 +94,8 @@
         " Parse configuration file, then send signal to \n"
         " running copy (except -k parse) and exit.\n"
         " -s Enable logging to syslog.\n"
+ " -t directory\n"
+ " Perform an immediate chroot() to directory on startup\n"
         " -u port Specify ICP port number (default: %d), disable with 0.\n"
         " -v Print version.\n"
         " -z Create swap directories\n"
@@ -115,7 +118,7 @@
     extern char *optarg;
     int c;
 
- while ((c = getopt(argc, argv, "CDFNRSVYXa:d:f:hk:m::su:vz?")) != -1) {
+ while ((c = getopt(argc, argv, "CDFNRSVYXa:d:f:hk:m::st:u:vz?")) != -1) {
         switch (c) {
         case 'C':
             opt_catch_signals = 0;
@@ -213,6 +216,23 @@
             fatal("Logging to syslog not available on this platform");
             /* NOTREACHED */
 #endif
+ case 't':
+ if (*(argv[0]) != '(') {
+ if ((int) strlen(optarg) < 1)
+ usage();
+ chroot_dir = xstrdup(optarg);
+ if (chroot_dir[strlen(chroot_dir)-1] == '/')
+ chroot_dir[strlen(chroot_dir)-1] = '\0';
+ if (strstr(argv[0], chroot_dir) == argv[0])
+ argv[0] = xstrdup(&(argv[0][strlen(chroot_dir)]));
+ /* This needs to be immediate because EVERYTHING needs
+ * to be relative to the chroot_dir, especially the
+ * configuration file options. */
+ if (chroot(chroot_dir))
+ fatal("failed to chroot");
+ chdir("/");
+ }
+ break;
         case 'u':
             icpPortNumOverride = atoi(optarg);
             if (icpPortNumOverride < 0)
@@ -456,10 +476,6 @@
 static void
 mainInitialize(void)
 {
- /* chroot if configured to run inside chroot */
- if (Config.chroot_dir && chroot(Config.chroot_dir)) {
- fatal("failed to chroot");
- }
     if (opt_catch_signals) {
         squid_signal(SIGSEGV, death, SA_NODEFER | SA_RESETHAND);
         squid_signal(SIGBUS, death, SA_NODEFER | SA_RESETHAND);
@@ -543,7 +559,7 @@
         else
             debug(1, 1) ("ICP port disabled in httpd_accelerator mode\n");
     }
- if (Config.chroot_dir)
+ if (chroot_dir != NULL)
         no_suid();
     if (!configured_once)
         writePidFile(); /* write PID file */
@@ -648,7 +664,7 @@
         cbdataInit();
         eventInit(); /* eventInit() is required for config parsing */
         storeFsInit(); /* required for config parsing */
- authenticateSchemeInit(); /* required for config parsign */
+ authenticateSchemeInit(); /* required for config parsing */
         parse_err = parseConfigFile(ConfigFile);
 
         if (opt_parse_cfg_only)
@@ -668,18 +684,10 @@
 
     /* send signal to running copy and exit */
     if (opt_send_signal != -1) {
- /* chroot if configured to run inside chroot */
- if (Config.chroot_dir && chroot(Config.chroot_dir)) {
- fatal("failed to chroot");
- }
         sendSignal();
         /* NOTREACHED */
     }
     if (opt_create_swap_dirs) {
- /* chroot if configured to run inside chroot */
- if (Config.chroot_dir && chroot(Config.chroot_dir)) {
- fatal("failed to chroot");
- }
         setEffectiveUser();
         debug(0, 0) ("Creating Swap Directories\n");
         storeCreateSwapDirectories();
@@ -890,6 +898,9 @@
             /* child */
             openlog(appname, LOG_PID | LOG_NDELAY | LOG_CONS, LOG_LOCAL4);
             prog = xstrdup(argv[0]);
+ /* If we chroot()ed, then we allocated argv[0] with xstrdup(). */
+ if (chroot_dir != NULL)
+ xfree(argv[0]);
             argv[0] = xstrdup("(squid)");
             execvp(prog, argv);
             syslog(LOG_ALERT, "execvp failed: %s", xstrerror());
diff -Nur squid-2.5.STABLE1.orig/src/squid.h squid-2.5.STABLE1/src/squid.h
--- squid-2.5.STABLE1.orig/src/squid.h Sun May 19 16:35:04 2002
+++ squid-2.5.STABLE1/src/squid.h Thu Oct 3 18:06:27 2002
@@ -49,7 +49,7 @@
  * Cannot increase FD_SETSIZE on Linux, but we can increase __FD_SETSIZE
  * with glibc 2.2 (or later? remains to be seen). We do this by including
  * bits/types.h which defines __FD_SETSIZE first, then we redefine
- * __FD_SETSIZE. Ofcourse a user program may NEVER include bits/whatever.h
+ * __FD_SETSIZE. Of course a user program may NEVER include bits/whatever.h
  * directly, so this is a dirty hack!
  */
 #if defined(_SQUID_LINUX_)
diff -Nur squid-2.5.STABLE1.orig/src/structs.h squid-2.5.STABLE1/src/structs.h
--- squid-2.5.STABLE1.orig/src/structs.h Sun Sep 8 01:11:23 2002
+++ squid-2.5.STABLE1/src/structs.h Thu Oct 3 18:28:29 2002
@@ -661,7 +661,6 @@
 #endif
     header_mangler header_access[HDR_ENUM_END];
     char *coredump_dir;
- char *chroot_dir;
 #if USE_CACHE_DIGESTS
     struct {
         int bits_per_entry;
diff -Nur squid-2.5.STABLE1.orig/src/tools.c squid-2.5.STABLE1/src/tools.c
--- squid-2.5.STABLE1.orig/src/tools.c Sat Sep 7 17:13:05 2002
+++ squid-2.5.STABLE1/src/tools.c Tue Oct 1 21:17:12 2002
@@ -505,10 +505,10 @@
         debug(50, 1) ("safeunlink: Couldn't delete %s: %s\n", s, xstrerror());
 }
 
-/* leave a privilegied section. (Give up any privilegies)
- * Routines that need privilegies can rap themselves in enter_suid()
+/* leave a privileged section. (Give up any privileges)
+ * Routines that need privileges can wrap themselves in enter_suid()
  * and leave_suid()
- * To give upp all posibilites to gain privilegies use no_suid()
+ * To give up all possibilities to gain privileges use no_suid()
  */
 void
 leave_suid(void)
@@ -516,7 +516,7 @@
     debug(21, 3) ("leave_suid: PID %d called\n", (int) getpid());
     if (geteuid() != 0)
         return;
- /* Started as a root, check suid option */
+ /* Started as root, check suid option */
     if (Config.effectiveUser == NULL)
         return;
 #if HAVE_SETGROUPS
@@ -538,7 +538,7 @@
 #endif
 }
 
-/* Enter a privilegied section */
+/* Enter a privileged section */
 void
 enter_suid(void)
 {
@@ -550,8 +550,8 @@
 #endif
 }
 
-/* Give up the posibility to gain privilegies.
- * this should be used before starting a sub process
+/* Give up the possibility to gain privileges.
+ * This should be used before starting a subprocess.
  */
 void
 no_suid(void)
@@ -559,7 +559,7 @@
     uid_t uid;
     leave_suid();
     uid = geteuid();
- debug(21, 3) ("leave_suid: PID %d giving up root priveleges forever\n", (int) getpid());
+ debug(21, 3) ("leave_suid: PID %d giving up root privileges forever\n", (int) getpid());
 #if HAVE_SETRESUID
     if (setresuid(uid, uid, uid) < 0)
         debug(50, 1) ("no_suid: setresuid: %s\n", xstrerror());
Received on Thu Oct 03 2002 - 14:04:32 MDT

This archive was generated by hypermail pre-2.1.9 : Tue Dec 09 2003 - 16:16:52 MST