* shared.h (class pinfo): New members root' and rootlen'.
				
					
				
			* syscalls.cc (chroot): Set new root for process.
        * path.cc (getcwd_inner): Add parameter to force use of
        new root from chroot() call.
        (ischrootpath): New macro.
        (normalize_posix_path): Care for changed root dir.
        (normalize_win32_path): Ditto.
        (getcwd_inner): Ditto.
        (chdir): Eliminate trailing path component consisting
        entirely of dots.
        * fork.cc (fork): Copy pinfo members regarding chroot().
        * spawn.cc (_spawnve): Ditto.
        * dir.cc (opendir): Don't use computed win32 path if
        chroot() took place.
			
			
This commit is contained in:
		@@ -1,3 +1,20 @@
 | 
			
		||||
Wed Jul 19 22:11:00 2000  Corinna Vinschen <corinna@vinschen.de>
 | 
			
		||||
 | 
			
		||||
	* shared.h (class pinfo): New members `root' and `rootlen'.
 | 
			
		||||
	* syscalls.cc (chroot): Set new root for process.
 | 
			
		||||
	* path.cc (getcwd_inner): Add parameter to force use of
 | 
			
		||||
	new root from chroot() call.
 | 
			
		||||
	(ischrootpath): New macro.
 | 
			
		||||
	(normalize_posix_path): Care for changed root dir.
 | 
			
		||||
	(normalize_win32_path): Ditto.
 | 
			
		||||
	(getcwd_inner): Ditto.
 | 
			
		||||
	(chdir): Eliminate trailing path component consisting
 | 
			
		||||
	entirely of dots.
 | 
			
		||||
	* fork.cc (fork): Copy pinfo members regarding chroot().
 | 
			
		||||
	* spawn.cc (_spawnve): Ditto.
 | 
			
		||||
	* dir.cc (opendir): Don't use computed win32 path if
 | 
			
		||||
	chroot() took place.
 | 
			
		||||
 | 
			
		||||
Mon Jul 17 22:21:34 2000  Christopher Faylor <cgf@cygnus.com>
 | 
			
		||||
 | 
			
		||||
	* dll_init.cc (dll_list::alloc): Fix debugging output.
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,8 @@ opendir (const char *dirname)
 | 
			
		||||
      goto failed;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (stat (real_dirname.get_win32 (), &statbuf) == -1)
 | 
			
		||||
  if (stat (myself->rootlen ? dirname : real_dirname.get_win32 (),
 | 
			
		||||
            &statbuf) == -1)
 | 
			
		||||
    goto failed;
 | 
			
		||||
 | 
			
		||||
  if (!(statbuf.st_mode & S_IFDIR))
 | 
			
		||||
 
 | 
			
		||||
@@ -437,6 +437,8 @@ fork ()
 | 
			
		||||
      child->orig_gid = myself->orig_gid;
 | 
			
		||||
      child->real_uid = myself->real_uid;
 | 
			
		||||
      child->real_gid = myself->real_gid;
 | 
			
		||||
      memcpy (child->root, myself->root, MAX_PATH+1);
 | 
			
		||||
      child->rootlen = myself->rootlen;
 | 
			
		||||
      set_child_mmap_ptr (child);
 | 
			
		||||
 | 
			
		||||
      /* Wait for subproc to initialize itself. */
 | 
			
		||||
 
 | 
			
		||||
@@ -83,7 +83,7 @@ details. */
 | 
			
		||||
#include <winioctl.h>
 | 
			
		||||
 | 
			
		||||
static int normalize_win32_path (const char *cwd, const char *src, char *dst);
 | 
			
		||||
static char *getcwd_inner (char *buf, size_t ulen, int posix_p);
 | 
			
		||||
static char *getcwd_inner (char *buf, size_t ulen, int posix_p, int with_chroot);
 | 
			
		||||
static void slashify (const char *src, char *dst, int trailing_slash_p);
 | 
			
		||||
static void backslashify (const char *src, char *dst, int trailing_slash_p);
 | 
			
		||||
static int path_prefix_p_ (const char *path1, const char *path2, int len1);
 | 
			
		||||
@@ -152,6 +152,11 @@ static char *cwd_posix;
 | 
			
		||||
static unsigned long cwd_hash;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define ischrootpath(path) \
 | 
			
		||||
        (myself->rootlen && \
 | 
			
		||||
         strncasematch (myself->root, path, myself->rootlen) && \
 | 
			
		||||
         (path[myself->rootlen] == '/' || path[myself->rootlen] == '\0'))
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
path_prefix_p_ (const char *path1, const char *path2, int len1)
 | 
			
		||||
{
 | 
			
		||||
@@ -584,6 +589,11 @@ normalize_posix_path (const char *cwd, const char *src, char *dst)
 | 
			
		||||
  /* Two leading /'s?  If so, preserve them.  */
 | 
			
		||||
  else if (isslash (src[1]))
 | 
			
		||||
    {
 | 
			
		||||
      if (myself->rootlen)
 | 
			
		||||
        {
 | 
			
		||||
	  debug_printf ("ENOENT = normalize_posix_path (%s)", src);
 | 
			
		||||
	  return ENOENT;
 | 
			
		||||
        }
 | 
			
		||||
      *dst++ = '/';
 | 
			
		||||
      *dst++ = '/';
 | 
			
		||||
      src += 2;
 | 
			
		||||
@@ -594,6 +604,12 @@ normalize_posix_path (const char *cwd, const char *src, char *dst)
 | 
			
		||||
	  src = src_start + 1;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
  /* Exactly one leading slash. Absolute path. Check for chroot. */
 | 
			
		||||
  else if (myself->rootlen)
 | 
			
		||||
    {
 | 
			
		||||
      strcpy (dst, myself->root);
 | 
			
		||||
      dst += myself->rootlen;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  while (*src)
 | 
			
		||||
    {
 | 
			
		||||
@@ -620,8 +636,10 @@ normalize_posix_path (const char *cwd, const char *src, char *dst)
 | 
			
		||||
		{
 | 
			
		||||
		  if (src[2] && !isslash (src[2]))
 | 
			
		||||
		    break;
 | 
			
		||||
		  while (dst > dst_start && !isslash (*--dst))
 | 
			
		||||
		    continue;
 | 
			
		||||
                  if (!ischrootpath (dst_start) ||
 | 
			
		||||
                      dst - dst_start != (int) myself->rootlen)
 | 
			
		||||
                    while (dst > dst_start && !isslash (*--dst))
 | 
			
		||||
		      continue;
 | 
			
		||||
		  src++;
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
@@ -644,12 +662,12 @@ normalize_posix_path (const char *cwd, const char *src, char *dst)
 | 
			
		||||
 | 
			
		||||
   The result is 0 for success, or an errno error value.
 | 
			
		||||
   FIXME: A lot of this should be mergeable with the POSIX critter.  */
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
normalize_win32_path (const char *cwd, const char *src, char *dst)
 | 
			
		||||
{
 | 
			
		||||
  const char *src_start = src;
 | 
			
		||||
  char *dst_start = dst;
 | 
			
		||||
  char *dst_root_start = dst;
 | 
			
		||||
 | 
			
		||||
  if (!SLASH_P (src[0]) && strchr (src, ':') == NULL)
 | 
			
		||||
    {
 | 
			
		||||
@@ -666,9 +684,25 @@ normalize_win32_path (const char *cwd, const char *src, char *dst)
 | 
			
		||||
  /* Two leading \'s?  If so, preserve them.  */
 | 
			
		||||
  else if (SLASH_P (src[0]) && SLASH_P (src[1]))
 | 
			
		||||
    {
 | 
			
		||||
      if (myself->rootlen)
 | 
			
		||||
        {
 | 
			
		||||
	  debug_printf ("ENOENT = normalize_win32_path (%s)", src);
 | 
			
		||||
	  return ENOENT;
 | 
			
		||||
        }
 | 
			
		||||
      *dst++ = '\\';
 | 
			
		||||
      ++src;
 | 
			
		||||
    }
 | 
			
		||||
  /* If absolute path, care for chroot. */
 | 
			
		||||
  else if (SLASH_P (src[0]) && !SLASH_P (src[1]) && myself->rootlen)
 | 
			
		||||
    {
 | 
			
		||||
      strcpy (dst, myself->root);
 | 
			
		||||
      char *c;
 | 
			
		||||
      while ((c = strchr (dst, '/')) != NULL)
 | 
			
		||||
        *c = '\\';
 | 
			
		||||
      dst += myself->rootlen;
 | 
			
		||||
      dst_root_start = dst;
 | 
			
		||||
      *dst++ = '\\';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  while (*src)
 | 
			
		||||
    {
 | 
			
		||||
@@ -689,10 +723,10 @@ normalize_win32_path (const char *cwd, const char *src, char *dst)
 | 
			
		||||
	       && (SLASH_P (src[2]) || src[2] == 0))
 | 
			
		||||
	{
 | 
			
		||||
	  /* Back up over /, but not if it's the first one.  */
 | 
			
		||||
	  if (dst > dst_start + 1)
 | 
			
		||||
	  if (dst > dst_root_start + 1)
 | 
			
		||||
	    dst--;
 | 
			
		||||
	  /* Now back up to the next /.  */
 | 
			
		||||
	  while (dst > dst_start + 1 && dst[-1] != '\\' && dst[-2] != ':')
 | 
			
		||||
	  while (dst > dst_root_start + 1 && dst[-1] != '\\' && dst[-2] != ':')
 | 
			
		||||
	    dst--;
 | 
			
		||||
	  src += 2;
 | 
			
		||||
	  if (SLASH_P (*src))
 | 
			
		||||
@@ -908,7 +942,7 @@ mount_info::conv_to_win32_path (const char *src_path, char *win32_path,
 | 
			
		||||
  char pathbuf[MAX_PATH];
 | 
			
		||||
 | 
			
		||||
  char cwd[MAX_PATH];
 | 
			
		||||
  getcwd_inner (cwd, MAX_PATH, TRUE); /* FIXME: check rc */
 | 
			
		||||
  getcwd_inner (cwd, MAX_PATH, TRUE, 0); /* FIXME: check rc */
 | 
			
		||||
 | 
			
		||||
  /* Determine where the destination should be placed. */
 | 
			
		||||
  if (full_win32_path != NULL)
 | 
			
		||||
@@ -932,6 +966,22 @@ mount_info::conv_to_win32_path (const char *src_path, char *win32_path,
 | 
			
		||||
	}
 | 
			
		||||
      isrelpath = !isabspath (src_path);
 | 
			
		||||
      *flags = set_flags_from_win32_path (dst);
 | 
			
		||||
      if (myself->rootlen && dst[0] && dst[1] == ':')
 | 
			
		||||
        {
 | 
			
		||||
          char posix_path[MAX_PATH + 1];
 | 
			
		||||
 | 
			
		||||
          rc = cygwin_shared->mount.conv_to_posix_path (dst, posix_path, 0);
 | 
			
		||||
          if (rc)
 | 
			
		||||
            {
 | 
			
		||||
              debug_printf ("conv_to_posix_path failed, rc %d", rc);
 | 
			
		||||
              return rc;
 | 
			
		||||
            }
 | 
			
		||||
          if (!ischrootpath (posix_path))
 | 
			
		||||
            {
 | 
			
		||||
              debug_printf ("ischrootpath failed");
 | 
			
		||||
              return ENOENT;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
      goto fillin;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1161,7 +1211,7 @@ mount_info::conv_to_posix_path (const char *src_path, char *posix_path,
 | 
			
		||||
 | 
			
		||||
  /* No need to fetch cwd if path is absolute. */
 | 
			
		||||
  if (relative_path_p)
 | 
			
		||||
    getcwd_inner (cwd, MAX_PATH, 0); /* FIXME: check rc */
 | 
			
		||||
    getcwd_inner (cwd, MAX_PATH, 0, 0); /* FIXME: check rc */
 | 
			
		||||
  else
 | 
			
		||||
    strcpy (cwd, "/"); /* some innocuous value */
 | 
			
		||||
 | 
			
		||||
@@ -2345,7 +2395,7 @@ get_cwd_win32 ()
 | 
			
		||||
/* getcwd */
 | 
			
		||||
 | 
			
		||||
char *
 | 
			
		||||
getcwd_inner (char *buf, size_t ulen, int posix_p)
 | 
			
		||||
getcwd_inner (char *buf, size_t ulen, int posix_p, int with_chroot)
 | 
			
		||||
{
 | 
			
		||||
  char *resbuf = NULL;
 | 
			
		||||
  size_t len = ulen;
 | 
			
		||||
@@ -2369,8 +2419,16 @@ getcwd_inner (char *buf, size_t ulen, int posix_p)
 | 
			
		||||
    }
 | 
			
		||||
  else if (cwd_posix != NULL)
 | 
			
		||||
    {
 | 
			
		||||
      debug_printf("myself->root: %s, cwd_posix: %s", myself->root, cwd_posix);
 | 
			
		||||
      if (strlen (cwd_posix) >= len)
 | 
			
		||||
	set_errno (ERANGE);
 | 
			
		||||
      else if (with_chroot && ischrootpath(cwd_posix))
 | 
			
		||||
        {
 | 
			
		||||
          strcpy (buf, cwd_posix + myself->rootlen);
 | 
			
		||||
          if (!buf[0])
 | 
			
		||||
            strcpy (buf, "/");
 | 
			
		||||
          resbuf = buf;
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
	{
 | 
			
		||||
	  strcpy (buf, cwd_posix);
 | 
			
		||||
@@ -2391,10 +2449,20 @@ getcwd_inner (char *buf, size_t ulen, int posix_p)
 | 
			
		||||
 | 
			
		||||
  size_t tlen = strlen (temp);
 | 
			
		||||
 | 
			
		||||
  if (with_chroot && ischrootpath (temp))
 | 
			
		||||
    tlen -= myself->rootlen;
 | 
			
		||||
 | 
			
		||||
  cwd_posix = (char *) realloc (
 | 
			
		||||
				  cwd_posix, tlen + 1);
 | 
			
		||||
  if (cwd_posix != NULL)
 | 
			
		||||
    strcpy (cwd_posix, temp);
 | 
			
		||||
    if (with_chroot && ischrootpath (temp))
 | 
			
		||||
      {
 | 
			
		||||
        strcpy (cwd_posix, temp + myself->rootlen);
 | 
			
		||||
        if (!buf[0])
 | 
			
		||||
          strcpy (buf, "/");
 | 
			
		||||
      }
 | 
			
		||||
    else
 | 
			
		||||
      strcpy (cwd_posix, temp);
 | 
			
		||||
 | 
			
		||||
  if (tlen >= ulen)
 | 
			
		||||
    {
 | 
			
		||||
@@ -2421,12 +2489,12 @@ getcwd (char *buf, size_t ulen)
 | 
			
		||||
  if (buf == NULL || ulen == 0)
 | 
			
		||||
    {
 | 
			
		||||
      buf = (char *) alloca (MAX_PATH);
 | 
			
		||||
      res = getcwd_inner (buf, MAX_PATH, 1);
 | 
			
		||||
      res = getcwd_inner (buf, MAX_PATH, 1, 1);
 | 
			
		||||
      res = strdup (buf);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      res = getcwd_inner (buf, ulen, 1);
 | 
			
		||||
      res = getcwd_inner (buf, ulen, 1, 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return res;
 | 
			
		||||
@@ -2477,6 +2545,13 @@ chdir (const char *dir)
 | 
			
		||||
 | 
			
		||||
      char pathbuf[MAX_PATH];
 | 
			
		||||
      (void) normalize_posix_path (cwd_posix, dir, pathbuf);
 | 
			
		||||
      /* Look for trailing path component consisting entirely of dots.  This
 | 
			
		||||
         is needed only in case of chdir since Windows simply ignores count
 | 
			
		||||
         of dots > 2 here instead of returning an error code.  Counts of dots
 | 
			
		||||
         <= 2 are already eliminated by normalize_posix_path. */
 | 
			
		||||
      char *last_slash = strrchr (pathbuf, '/');
 | 
			
		||||
      if (last_slash && strspn (last_slash + 1, ".") == strlen (last_slash + 1))
 | 
			
		||||
        *last_slash = '\0';
 | 
			
		||||
      free (cwd_posix);
 | 
			
		||||
      cwd_posix = strdup (pathbuf);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -102,6 +102,11 @@ class pinfo
 | 
			
		||||
  uid_t real_uid;        /* Remains intact on seteuid, replaced by setuid */
 | 
			
		||||
  gid_t real_gid;	 /* Ditto */
 | 
			
		||||
 | 
			
		||||
  /* Filled when chroot() is called by the process or one of it's parents.
 | 
			
		||||
     Saved without trailing backslash. */
 | 
			
		||||
  char root[MAX_PATH+1];
 | 
			
		||||
  size_t rootlen;
 | 
			
		||||
 | 
			
		||||
  /* Non-zero if process was stopped by a signal. */
 | 
			
		||||
  char stopsig;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -852,6 +852,8 @@ _spawnve (HANDLE hToken, int mode, const char *path, const char *const *argv,
 | 
			
		||||
          child->psid = child->sidbuf;
 | 
			
		||||
        memcpy (child->logsrv, myself->logsrv, MAX_HOST_NAME);
 | 
			
		||||
        memcpy (child->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
 | 
			
		||||
        memcpy (child->root, myself->root, MAX_PATH+1);
 | 
			
		||||
        child->rootlen = myself->rootlen;
 | 
			
		||||
	subproc_init ();
 | 
			
		||||
	ret = spawn_guts (hToken, path, argv, envp, child, mode);
 | 
			
		||||
	if (ret == -1)
 | 
			
		||||
 
 | 
			
		||||
@@ -1917,12 +1917,42 @@ setegid (gid_t gid)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* chroot: privileged Unix system call.  */
 | 
			
		||||
/* FIXME: Not privileged here. How should this be done? */
 | 
			
		||||
extern "C"
 | 
			
		||||
int
 | 
			
		||||
chroot (const char *)
 | 
			
		||||
chroot (const char *newroot)
 | 
			
		||||
{
 | 
			
		||||
  set_errno (ENOSYS);
 | 
			
		||||
  return -1;
 | 
			
		||||
  int ret = -1;
 | 
			
		||||
  path_conv path(newroot, PC_SYM_FOLLOW | PC_FULL);
 | 
			
		||||
  
 | 
			
		||||
  if (path.error)
 | 
			
		||||
    goto done;
 | 
			
		||||
  if (path.file_attributes () == (DWORD)-1)
 | 
			
		||||
    {
 | 
			
		||||
      set_errno (ENOENT);
 | 
			
		||||
      goto done;
 | 
			
		||||
    }
 | 
			
		||||
  if (!(path.file_attributes () & FILE_ATTRIBUTE_DIRECTORY))
 | 
			
		||||
    {
 | 
			
		||||
      set_errno (ENOTDIR);
 | 
			
		||||
      goto done;
 | 
			
		||||
    }
 | 
			
		||||
  ret = cygwin_shared->mount.conv_to_posix_path (path.get_win32 (),
 | 
			
		||||
                                                 myself->root, 0);
 | 
			
		||||
  if (ret)
 | 
			
		||||
    {
 | 
			
		||||
      set_errno (ret);
 | 
			
		||||
      goto done;
 | 
			
		||||
    }
 | 
			
		||||
  myself->rootlen = strlen (myself->root);
 | 
			
		||||
  if (myself->root[myself->rootlen - 1] == '/')
 | 
			
		||||
    myself->root[--myself->rootlen] = '\0';
 | 
			
		||||
  ret = 0;
 | 
			
		||||
 | 
			
		||||
done:
 | 
			
		||||
  syscall_printf ("%d = chroot (%s)", ret ? get_errno () : 0,
 | 
			
		||||
                                      newroot ? newroot : "NULL");
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user