delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1999/02/28/14:57:52.1

Message-Id: <199902281957.TAA94214@out5.ibm.net>
From: "Mark E." <snowball3 AT usa DOT net>
To: djgpp-workers AT delorie DOT com
Date: Sun, 28 Feb 1999 14:57:56 -0500
MIME-Version: 1.0
Subject: chroot patches r3
X-mailer: Pegasus Mail for Win32 (v3.01d)
Reply-To: djgpp-workers AT delorie DOT com

Below are my latest patches to implement chroot. The implementation 
should be or very nearly be complete and correct. Included is a second 
try at documenting chroot.c and the first try at documenting fchroot.h.

So child programs will inherit a parent's root directory, I decided to use 
ROOT and CHROOT_UNIX. ROOT holds the root directory. 
CHROOT_UNIX holds whether or not chroot() has the Unix restrictions 
or not. If ROOT is defined, but not CHROOT_UNIX, then chroot defaults 
to Unix mode. SYSROOT is supported for backward compatibility with 
Bash as long as ROOT is not defined. If I has used SYSROOT, then 
chroot would have to default to the permissive behavior Bash expects. 
So to keep things consistent, I decided that it would be better to use 
ROOT instead of SYSROOT.

*** include/libc/root.h.orig	Sun Feb 28 14:25:36 1999
--- include/libc/root.h	Sun Feb 28 14:28:54 1999
***************
*** 0 ****
--- 1,16 ----
+ /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
+ #ifndef __djgpp_libc_root_h
+ #define __djgpp_libc_root_h
+ 
+ #define ROOT_ENV "ROOT"
+ #define CHROOT_ENV "CHROOT_UNIX"
+ 
+ extern char __djgpp_root[];
+ extern int __djgpp_root_len;
+ 
+ int chroot (const char *path);
+ 
+ char *__delete_root (char *path);
+ 
+ #endif
+ 
*** src/libc/compat/unistd/chroot.c.orig	Sun Feb 28 14:25:18 1999
--- src/libc/compat/unistd/chroot.c	Sun Feb 28 14:31:06 1999
***************
*** 0 ****
--- 1,133 ----
+ /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <limits.h>
+ #include <sys/stat.h>
+ #include <errno.h>
+ #include <stdlib.h>
+ #include <libc/bss.h>
+ #include <libc/root.h>
+ 
+ static int chroot_bss_count = -1;
+ 
+ unsigned int __chroot_flags = __CHROOT_UNIX_MODE_FLAG;
+ static unsigned int old_flags;
+ 
+ char __djgpp_root[PATH_MAX + 1] = { '\0' };
+ int __djgpp_root_len = 0;
+ 
+ 
+ int
+ chroot (const char *path)
+ {
+   char buf[PATH_MAX+1];
+   char *to = __djgpp_root;
+   char *from = buf;
+   int unix_emu;
+   int path_len;
+ 
+   if ((path_len = strlen(path)) > PATH_MAX)
+   {
+     errno = ENAMETOOLONG;
+     return -1;
+   }
+ 
+   if (chroot_bss_count != __bss_count)
+   {
+     chroot_bss_count = __bss_count;
+     old_flags = ~0;
+   }
+ 
+   unix_emu = __chroot_flags & __CHROOT_UNIX_MODE_FLAG;
+ 
+   /* When not emulating the Unix behavior of chroot,
+      allow a null root to delete the root path. */
+   if (path == NULL || *path == '\0')
+   {
+     if (unix_emu)
+     {
+       errno = ENOENT;
+       return -1;
+     }
+     __djgpp_root[0] = '\0';
+     __djgpp_root_len = 0;
+     setenv(ROOT_ENV, __djgpp_root, 1);
+     return 0;
+   }
+ 
+   _fixpath(path, buf);
+ 
+   if (unix_emu)
+   {
+     /* If a root path already exists, then the path
+        returned from _fixpath should be relative to
+        the existing root path. If not, then reject the path. */
+     if (__djgpp_root_len > 0 && *buf != '/')
+     {
+       errno = EACCES;
+       return -1;
+     }
+   }
+ 
+   /* Make sure the path is valid before
+      making it the new root path. */
+   if (access(buf, D_OK) < 0)
+     return -1;
+ 
+   /* Copy in the new root path. */
+   if (*buf != '/')
+     __djgpp_root_len = 0;
+   else  /* Append to the current root path. */
+     to = __djgpp_root + __djgpp_root_len;
+ 
+   while (*from)
+   {
+     *to = *from;
+     ++to;
+     ++from;
+     ++__djgpp_root_len;
+   }
+ 
+   /* Set up environmental variables to be used so child programs
+      created with DJGPP will inherit the root path and mode.
+      __CHROOT_NO_SETENV_FLAG is set at startup to avoid
+      wasting time setting the same environmental variables
+      that resulted in chroot being called in the first place. */
+   if (!(__chroot_flags & __CHROOT_NO_SETENV_FLAG))
+     setenv(ROOT_ENV, __djgpp_root, 1);
+ 
+   if (old_flags != __chroot_flags)
+   {
+     if (!(__chroot_flags & __CHROOT_NO_SETENV_FLAG))
+       setenv(CHROOT_ENV, (unix_emu ? "Y" : "N"), 1);
+     old_flags = __chroot_flags;
+   }
+ 
+   return 0;
+ }
+ 
+ 
+ /* Delete the root path from an input path.
+    The input path is assumed to have already been canonicalized. */
+ 
+ char *
+ __delete_root (char *path)
+ {
+   if (__djgpp_root_len > 0 && path[0] != '/')
+   {
+     if (strnicmp (path, __djgpp_root, __djgpp_root_len) == 0
+         && (path[__djgpp_root_len] == '/' || path[__djgpp_root_len] == 
'\0'))
+     {
+ 		  if (path[__djgpp_root_len] == '/')
+         strcpy (path, path + __djgpp_root_len);
+       else
+       {
+ 			  /* path is equal to the root path. */
+ 			  path[0] = '/';
+ 				path[1] = '\0';
+       }
+     }
+   }
+   return path;
+ }
+ 
*** src/libc/compat/unistd/fchroot.c.orig	Sun Feb 28 14:25:24 1999
--- src/libc/compat/unistd/fchroot.c	Sun Feb 28 14:31:28 1999
***************
*** 0 ****
--- 1,24 ----
+ /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
+ #include <unistd.h>
+ #include <errno.h>
+ #include <libc/root.h>
+ 
+ int
+ fchroot (int fd)
+ {
+   unsigned int flags = __chroot_flags;
+ 
+   if (fd < 0)
+   {
+     errno = EINVAL;
+     return -1;
+   }
+ 
+   /* Use &= in case more flags are ever added. */
+   __chroot_flags &= ~__CHROOT_UNIX_MODE_FLAG;
+   chroot (NULL);
+   __chroot_flags = flags;
+ 
+   return 0;
+ }
+ 
*** src/libc/compat/unistd/chroot.txh.orig	Sun Feb 28 14:25:02 1999
--- src/libc/compat/unistd/chroot.txh	Sat Feb 27 18:01:34 1999
***************
*** 0 ****
--- 1,51 ----
+ @node chroot, file system
+ @subheading Syntax
+ 
+ @example
+ #include <unistd.h>
+ 
+ extern unsigned int __chroot_flags;
+ 
+ int chroot(const char *new_root_directory);
+ @end example
+ 
+ @subheading Description
+ 
+ Causes @var{new_root_directory} to become the root directory, or 
starting point, for path name searches beginning with '/' or '\'. The 
current working directory is unaffected.
+ 
de{chroot} is set to not emulate Unix, no restrictions are enforced on 
what directory can be the root directory just as long as it exists.
+ 
{ROOT} is not set, but @var{SYSROOT} is, then @var{SYSROOT} is 
used to set the root directory, and @code{chroot} is set to permissive 
mode, and @var{CHROOT_UNIX} is ignored.
+ 
+ The global variable @var{__chroot_flags} can be set to include the
+ following values to control the operation of @code{chroot}:
+ 
+ @table @code
+ 
+ @item __CHROOT_UNIX_MODE_FLAG
+ 
+ If set, emulate the behavior of Unix implementations of 
@code{chroot} with its directory restrictions. If not set, allow any 
directory that exists.
+ 
+ @item __CHROOT_NO_SETENV_FLAG
+ 
+ If set, @code{chroot} will not update the environment variables 
@var{ROOT} and @var{CHROOT_UNIX}. This flag is used during 
startup to prevent @code{chroot} from wasting time setting the same 
variables that caused @code{chroot} to be called in the first place.
+ 
+ @end table
+ 
+ @subheading Return Value
+ 
+ Zero if successful, else nonzero and @var{errno} set if error.
+ 
+ @subheading Portability
+ 
+ @port-note The variable @var{__chroot_flags} is DJGPP specific.
+ @portability !ansi, !posix
+ 
+ @subheading Example
+ 
+ @example
+ chroot("c:/djgpp");
+ if (access("/bin/gcc.exe", R_OK) < 0)
+   fprintf(stderr, "gcc.exe not found");  
+ @end example
+ 
*** src/libc/dos/io/putpath.c.orig	Thu Oct 29 05:24:44 1998
--- src/libc/dos/io/putpath.c	Thu Feb 25 14:02:32 1999
***************
*** 3,8 ****
--- 3,9 ----
  #include <libc/stubs.h>
  #include <libc/dosio.h>
  #include <libc/farptrgs.h>
+ #include <libc/root.h>
  #include <go32.h>
  #include <stdlib.h>
  #include <string.h>
***************
*** 49,54 ****
--- 50,66 ----
      }
      else if (p[5])
        path = p + 5;
+   }
+ /* If the path is absolute and a root path is set,
+    then add the root path to the output. */
+   else if (path[0] == '/' && __djgpp_root_len > 0 )
+   {
+     char *root = __djgpp_root;
+     for ( ; *root; root++)
+     {
+       _farnspokeb (o++, *root);
+       space -= 1;
+     }
    }
  
    /* collapse multiple slashes to a single slash */
*** src/libc/posix/sys/stat/fixpath.c.orig	Sun Dec 13 08:09:46 1998
--- src/libc/posix/sys/stat/fixpath.c	Thu Feb 25 14:01:42 1999
***************
*** 13,18 ****
--- 13,19 ----
  #include <crt0.h>		/* For crt0 flags */
  #include <sys/stat.h>
  #include <libc/dosio.h>
+ #include <libc/root.h>
  
  static unsigned use_lfn;
  
***************
*** 73,78 ****
--- 74,80 ----
     5. Removing ".." entries in the path (and the directory above them)
     6. Adding a drive specification if one wasn't there
     7. Converting all slashes to '/'
+    8. Remove the portion of the path matching the root path
   */
  void
  _fixpath(const char *in, char *out)
***************
*** 227,232 ****
--- 229,240 ----
      }
      else if (*op == '\0')
        break;
+   }
+ 
+   /* Remove the portion of the path matching the root path */
+   if (__djgpp_root_len > 0 && out[0] != '/')
+   {
+     __delete_root(out);
    }
  }
  
*** src/libc/crt0/c1root.c.orig	Sun Feb 28 14:08:22 1999
--- src/libc/crt0/c1root.c	Sat Feb 27 17:58:08 1999
***************
*** 0 ****
--- 1,53 ----
+ #include <libc/root.h>
+ #include <stdlib.h>
+ #include <unistd.h>
+ 
+ /* Here is we check for three environmental variables
+    that may result in a call to chroot():
+    ROOT        - the root path. Can be set manually or by chroot().
+    CHROOT_UNIX - Y if chroot is to emulate the restrictive
+                  behavior of the Unix implementations.
+                  Any other value to select the non-restrictive
+                  behavior implemented by Bash 1.147.
+    SYSROOT     - Bash 1.147 sets this variable to the directory to
+                  use when searching for path names beginning
+                  with '/' or '\'. If ROOT is set, this variable
+                  is ignored. If ROOT is not set and SYSROOT does
+                  contain a path, then chroot() emulates the
+                  non-restrictive behavior of Bash 1.147 regardless
+                  of the value of CHROOT_UNIX. This variable is checked
+                  to maintain backward compatibility with Bash 1.147.
+                  Someday, this variable will be completely ignored
+                  once a DJGPP port of Bash 2 has been released
+                  and is in wide use. */
+ 
+ void
+ __crt0_setup_chroot()
+ {
+   char *root = getenv(ROOT_ENV);
+   char *sysroot = (root ? NULL : getenv("SYSROOT"));
+   char *unix_mode = (!sysroot ? getenv(CHROOT_ENV) : NULL);
+   int ret_code;
+ 
+   if (unix_mode)
+   {
+     if (*unix_mode == 'Y' || *unix_mode == 'y')
+       __chroot_flags = __CHROOT_UNIX_MODE_FLAG;
+     else
+       __chroot_flags &= ~__CHROOT_UNIX_MODE_FLAG;
+   }
+   else if (sysroot)
+     __chroot_flags &= ~__CHROOT_UNIX_MODE_FLAG;
+ 
+   if (sysroot)
+     root = sysroot;
+ 
+   if (root)
+   {
+     __chroot_flags |= __CHROOT_NO_SETENV_FLAG;
+     /* What should happen when chroot fails? */
+     ret_code = chroot(root);
+     __chroot_flags &= ~__CHROOT_NO_SETENV_FLAG;
+   }
+ }
+ 
*** src/libc/posix/unistd/getcwd.c.orig	Sat Aug 31 18:09:32 1996
--- src/libc/posix/unistd/getcwd.c	Sun Feb 28 14:41:40 1999
***************
*** 13,18 ****
--- 13,19 ----
  #include <crt0.h>
  #include <libc/farptrgs.h>
  #include <libc/dosio.h>
+ #include <libc/root.h>
  
  char *
  __getcwd(char *buf, size_t size)
***************
*** 107,112 ****
--- 108,119 ----
    __dpmi_int(0x21, &r);
  
    buf[0] = r.h.al + (r.h.al < 26 ? 'a' : 'A');
+ 
+   /* See if we need to strip the root path set by chroot */
+   if (__djgpp_root_len > '\0')
+   {
+ 	  __delete_root(buf);
+   }
  
    return buf;
  }

--- 
Mark Elbrecht
snowball3 AT usa DOT net http://members.xoom.com/snowball3/

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019