From olli@haluter.fromme.com  Fri Apr 20 16:11:54 2001
Return-Path: <olli@haluter.fromme.com>
Received: from haluter.fromme.com (haluter.fromme.com [212.66.1.135])
	by hub.freebsd.org (Postfix) with ESMTP id DD2B737B424
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 20 Apr 2001 16:11:53 -0700 (PDT)
	(envelope-from olli@haluter.fromme.com)
Received: (from root@localhost)
	by haluter.fromme.com (8.11.3/8.11.3) id f3KNBqh00491;
	Sat, 21 Apr 2001 01:11:52 +0200 (CEST)
	(envelope-from olli)
Message-Id: <200104202311.f3KNBqh00491@haluter.fromme.com>
Date: Sat, 21 Apr 2001 01:11:52 +0200 (CEST)
From: olli@fromme.com
Reply-To: olli@fromme.com
To: FreeBSD-gnats-submit@freebsd.org
Cc: olli@fromme.com
Subject: [PATCH] jail improvement
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         26740
>Category:       kern
>Synopsis:       [PATCH] jail improvement
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    rwatson
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Apr 20 16:20:02 PDT 2001
>Closed-Date:    Mon Mar 24 07:44:34 PST 2003
>Last-Modified:  Mon Mar 24 07:44:34 PST 2003
>Originator:     Oliver Fromme
>Release:        FreeBSD 4.3-RC2 alpha
>Organization:
fromme.com
>Environment:
System: FreeBSD haluter.fromme.com 4.3-RC2 FreeBSD 4.3-RC2 #8: Fri Apr 20 23:48:25 CEST 2001 olli@haluter.fromme.com:/sea/src/sys/compile/HALUTER alpha

>Description:

This patch adds a small feature to jails.

Processes within a jails cannot see things outside their
jail (files, processes, sockets) -- however, thay still
can see _all_ mountpoints.  This patch fixes that.  In
particular, it does two things:
-1-  Mounts which are outside of a jail are not returned
     to processes within that jail.
-2-  Mounts within a jail get their jail chroot prefix
     stripped off.  See example below.

The patch modifies statfs(), fstatfs() and getfsstat().

Without my patch, the output of "mount" within a jail on
my test machine looks like this:

   /dev/da0a on / (ufs, local, soft-updates)
   /dev/da0f on /sea (ufs, local, soft-updates)
   /dev/da0e on /var (ufs, local, soft-updates)
   procfs on /proc (procfs, local)
   /dev/vn0c on /usr (ufs, local, soft-updates)
   /dev/vn1c on /jail/olli (ufs, local, read-only)
   /dev/vn2c on /jail/olli (ufs, local, union, soft-updates)
   procfs on /jail/olli/proc (procfs, local)
   /dev/vn3c on /jail/olli/home (ufs, local, read-only)

With my patch, the output is this:

   /dev/vn1c on / (ufs, local, read-only)
   /dev/vn2c on / (ufs, local, union, soft-updates)
   procfs on /proc (procfs, local)
   /dev/vn3c on /home (ufs, local, read-only)

There's a small point to note:  If there aren't any mounts
within the jail, getfsstat() returns 0 (an empty list).
/bin/df handles this well, but /sbin/mount prints
,,error 0``.  I tend to think that that's a bug in
/sbin/mount.  I'll submit a fix if desired.

>How-To-Repeat:

Set up a jail environment somewhere, start the jail and
type "df" or "mount".  You'll see all mountpoints,
including those in other jails and those that aren't in
any jails.

>Fix:

NOTE:  This patch is against -stable.  Unfortunately, I
don't have a machine left for installing -current.
I've had a quick look at the relevant files in -current
in the CVS repository, and I _think_ it shouldn't be too
painful to apply the patch there (change p->pr_prison to
p->p_ucred->cr_prison etc.), but I can't test it myself
on -current.  (It's running perfectly fine on my -stable
box, of course.)


--- src/sys/sys/jail.h.orig	Wed Nov  1 18:58:06 2000
+++ src/sys/sys/jail.h	Sat Apr  7 21:00:39 2001
@@ -30,6 +30,17 @@
 MALLOC_DECLARE(M_PRISON);
 #endif
 
+
+#ifndef MNAMELEN
+/* This is taken from sys/mount.h. */
+#ifdef __i386__
+#define	MNAMELEN	80	/* length of buffer for returned name */
+#endif
+#ifdef __alpha__
+#define	MNAMELEN	72	/* length of buffer for returned name */
+#endif
+#endif
+
 /*
  * This structure describes a prison.  It is pointed to by all struct
  * proc's of the inmates.  pr_ref keeps track of them and is used to
@@ -39,6 +50,7 @@
 struct prison {
 	int		pr_ref;
 	char 		pr_host[MAXHOSTNAMELEN];
+	char		pr_path[MNAMELEN];
 	u_int32_t	pr_ip;
 	void		*pr_linux;
 };
--- src/sys/kern/kern_jail.c.orig	Wed Nov  1 18:58:06 2000
+++ src/sys/kern/kern_jail.c	Sat Apr  7 21:04:31 2001
@@ -69,6 +69,9 @@
 	error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0);
 	if (error) 
 		goto bail;
+	error = copyinstr(j.path, &pr->pr_path, sizeof pr->pr_path, 0);
+	if (error)
+		goto bail;
 	pr->pr_ip = j.ip_number;
 
 	ca.path = j.path;
--- src/sys/kern/vfs_syscalls.c.orig	Tue Mar 20 12:45:01 2001
+++ src/sys/kern/vfs_syscalls.c	Fri Apr 20 23:47:16 2001
@@ -59,6 +59,7 @@
 #include <sys/unistd.h>
 #include <sys/vnode.h>
 #include <sys/proc.h>
+#include <sys/jail.h>
 #include <sys/dirent.h>
 #include <sys/extattr.h>
 
@@ -72,6 +73,8 @@
 
 static int change_dir __P((struct nameidata *ndp, struct proc *p));
 static void checkdirs __P((struct vnode *olddp));
+static int check_prison_mount __P((struct proc *p, struct statfs *sp));
+static void trim_prison_mount __P((struct statfs *sp, int pripl));
 static int chroot_refuse_vdir_fds __P((struct filedesc *fdp));
 static int getutimes __P((const struct timeval *, struct timespec *));
 static int setfown __P((struct proc *, struct vnode *, uid_t, gid_t));
@@ -609,6 +612,62 @@
 }
 
 /*
+ * Check if we're imprisoned and whether the mountpoint
+ * is inside our prison.  Return values:
+ *    -1   if we're not supposed to see this mount.
+ *     0   if it's alright.
+ *    >0   strip that many characters from the beginning of
+ *         the path of the mountpoint.  E.g. if the mount
+ *         point is /foo/bar and the jail is chrooted at /foo,
+ *         4 is be returned, so only /bar will be left.
+ */
+static int
+check_prison_mount(p, sp)
+	struct proc *p;
+	struct statfs *sp;
+{
+	register char *prip;	/* prison path */
+	register int pripl;	/* prison path length */
+
+	if (!p->p_prison)
+		return (0);
+	prip = p->p_prison->pr_path;
+	pripl = strlen(prip);
+	if (pripl > 0 && prip[pripl - 1] == '/')
+		pripl--;	/* ignore trailing slash, if any */
+	/*
+	 * Note that it is not sufficient to check for the
+	 * first <pripl> characters to be the same.
+	 * We also have to make sure that the next character
+	 * in the mountpoint path is either '\0' or '/'.
+	 * Otherwise a jail in "/foo/bar" would be allowed
+	 * to see a mount at "/foo/barbara".
+	 */
+	if (strncmp(prip, sp->f_mntonname, pripl) != 0 ||
+	    (sp->f_mntonname[pripl] != '\0' && sp->f_mntonname[pripl] != '/'))
+		return (-1);	/* not our business */
+	return (pripl);
+}
+
+/*
+ * Remove the jail chroot path from the mountpoint,
+ * so that imprisoned users see everything relative
+ * to their jail chroot.
+ */
+static void
+trim_prison_mount(sp, pripl)
+	struct statfs *sp;
+	int pripl;	/* prison path length */
+{
+	strcpy(sp->f_mntonname, sp->f_mntonname + pripl);
+	/* If there's nothing left, this ought to be "/". */
+	if (sp->f_mntonname[0] == '\0') {
+		sp->f_mntonname[0] = '/';
+		sp->f_mntonname[1] = '\0';
+	}
+}
+
+/*
  * Get filesystem statistics.
  */
 #ifndef _SYS_SYSPROTO_H_
@@ -629,6 +688,8 @@
 	register struct mount *mp;
 	register struct statfs *sp;
 	int error;
+	int pripl;
+	int nonsu;
 	struct nameidata nd;
 	struct statfs sb;
 
@@ -639,13 +700,19 @@
 	sp = &mp->mnt_stat;
 	NDFREE(&nd, NDF_ONLY_PNBUF);
 	vrele(nd.ni_vp);
+	if ((pripl = check_prison_mount(p, sp)) < 0)
+		return (ENOENT);
 	error = VFS_STATFS(mp, sp, p);
 	if (error)
 		return (error);
 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
-	if (suser_xxx(p->p_ucred, 0, 0)) {
+	nonsu = suser_xxx(p->p_ucred, 0, 0);
+	if (nonsu || pripl) {
 		bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
-		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
+		if (nonsu)
+			sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
+		if (pripl)
+			trim_prison_mount(&sb, pripl);
 		sp = &sb;
 	}
 	return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
@@ -673,19 +740,27 @@
 	struct mount *mp;
 	register struct statfs *sp;
 	int error;
+	int pripl;
+	int nonsu;
 	struct statfs sb;
 
 	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 		return (error);
 	mp = ((struct vnode *)fp->f_data)->v_mount;
 	sp = &mp->mnt_stat;
+	if ((pripl = check_prison_mount(p, sp)) < 0)
+		return (ENOENT);
 	error = VFS_STATFS(mp, sp, p);
 	if (error)
 		return (error);
 	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
-	if (suser_xxx(p->p_ucred, 0, 0)) {
+	nonsu = suser_xxx(p->p_ucred, 0, 0);
+	if (nonsu || pripl) {
 		bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
-		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
+		if (nonsu)
+			sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
+		if (pripl)
+			trim_prison_mount(&sb, pripl);
 		sp = &sb;
 	}
 	return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
@@ -714,13 +789,16 @@
 	register struct statfs *sp;
 	caddr_t sfsp;
 	long count, maxcount, error;
+	int pripl;
+	struct statfs sb;
 
 	maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
 	sfsp = (caddr_t)SCARG(uap, buf);
 	count = 0;
 	simple_lock(&mountlist_slock);
 	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
-		if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
+		pripl = check_prison_mount(p, &mp->mnt_stat);
+		if (pripl < 0 || vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
 			nmp = TAILQ_NEXT(mp, mnt_list);
 			continue;
 		}
@@ -740,6 +818,11 @@
 				continue;
 			}
 			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
+			if (pripl) {
+				bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
+				trim_prison_mount(&sb, pripl);
+				sp = &sb;
+			}
 			error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
 			if (error) {
 				vfs_unbusy(mp, p);
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->rwatson 
Responsible-Changed-By: rwatson 
Responsible-Changed-When: Sun Apr 22 13:28:32 PDT 2001 
Responsible-Changed-Why:  
After a quick chat with Poul-Henning, we concluded I'd take ownership of 
this bug report/feature request.  However, we have some concerns about 
the effectiveness of the patch in slightly less usual file system namespaces 
(such as ones where mount within chroot occurs). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=26740 

From: Oliver Fromme <olli@fromme.com>
To: freebsd-gnats-submit@FreeBSD.org
Cc: olli@fromme.com
Subject: Re: kern/26740: [PATCH] jail improvement
Date: Wed, 27 Feb 2002 15:51:05 +0100 (CET)

 I have updated and improved the patch.
 The following is the complete patch for 4.5-RELEASE.
 
 --- src/sys/kern/kern_jail.c.orig	Mon Sep  3 10:17:12 2001
 +++ src/sys/kern/kern_jail.c	Wed Feb 27 15:40:43 2002
 @@ -69,6 +69,9 @@
  	error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0);
  	if (error) 
  		goto bail;
 +	error = copyinstr(j.path, &pr->pr_path, sizeof pr->pr_path, 0);
 +	if (error)
 +		goto bail;
  	pr->pr_ip = j.ip_number;
  
  	ca.path = j.path;
 --- src/sys/kern/vfs_syscalls.c.orig	Mon Jan  7 21:47:34 2002
 +++ src/sys/kern/vfs_syscalls.c	Wed Feb 27 13:21:06 2002
 @@ -59,6 +59,7 @@
  #include <sys/unistd.h>
  #include <sys/vnode.h>
  #include <sys/proc.h>
 +#include <sys/jail.h>
  #include <sys/dirent.h>
  #include <sys/extattr.h>
  
 @@ -72,6 +73,9 @@
  
  static int change_dir __P((struct nameidata *ndp, struct proc *p));
  static void checkdirs __P((struct vnode *olddp));
 +static int check_prison_mount __P((struct proc *p, struct statfs *sp,
 +    int specific));
 +static void trim_prison_mount __P((struct statfs *sp, int pripl));
  static int chroot_refuse_vdir_fds __P((struct filedesc *fdp));
  static int getutimes __P((const struct timeval *, struct timespec *));
  static int setfown __P((struct proc *, struct vnode *, uid_t, gid_t));
 @@ -356,7 +360,7 @@
  /*
   * Scan all active processes to see if any of them have a current
   * or root directory onto which the new filesystem has just been
 - * mounted. If so, replace them with the new mount point.
 + * mounted. If so, replace them with the new mountpoint.
   */
  static void
  checkdirs(olddp)
 @@ -611,6 +615,90 @@
  }
  
  /*
 + * Check if we're imprisoned and whether the mountpoint is inside of
 + * our prison.  Return values:
 + *    -1   if we're not supposed to see this mount.
 + *     0   if it's alright.
 + *    >0   strip that many characters from the beginning of the path of
 + *         the mountpoint.  E.g. if the mountpoint is /foo/bar and the
 + *         jail is chrooted at /foo, 4 is be returned, so only /bar
 + *         will be left.
 + *
 + * The "specific" flag indicates if the request has been issued for
 + * this specific filesystem (1), or if this is part of an enumeration
 + * of all filesystems (0).  In the former case, we allow it to be
 + * visible _IF_ it is a prefix of the jail chroot directory.  This
 + * makes "ls" etc. work if the mountpoint of the jail root is outside
 + * of the jail.  In the latter case, this filesystem is hidden.
 + * Example:  The jail chroot is /usr/jail (which is not a separate
 + * filesystem, but /usr is).  Ordinarily, "ls" within the jail would
 + * fail ("no such file or directory"), because it calls fstatfs() on
 + * the directory.  Similarly for "df ." etc.  Therefore, /usr must be
 + * visible within the jail for fstatfs() (it'll show up as "/" within
 + * the jail).
 + */
 +static int
 +check_prison_mount(p, sp, specific)
 +	struct proc *p;
 +	struct statfs *sp;
 +	int specific;
 +{
 +	register char *prip;	/* prison path */
 +	register int pripl;	/* prison path length */
 +
 +	/* short-cut:  no prison -> no restriction */
 +	if (!p->p_prison)
 +		return (0);
 +	prip = p->p_prison->pr_path;
 +	pripl = strlen(prip);
 +	if (pripl > 0 && prip[pripl - 1] == '/')
 +		pripl--;	/* ignore trailing slash, if any */
 +	/*
 +	 * First, if this is a specific filesystem request, check if
 +	 * the mountpoint is a prefix of the jail root.
 +	 * If it is, then strip the whole path, so it'll become "/".
 +	 * Otherwise continue with the normal (non-specific) check.
 +	 */
 +	if (specific) {
 +		int mntlen = strlen(sp->f_mntonname);
 +
 +		if (strncmp(prip, sp->f_mntonname, mntlen) == 0 &&
 +		    (prip[pripl] == '\0' || prip[pripl] == '/'))
 +			return mntlen;	/* strip all */
 +	}
 +	/*
 +	 * Note that it is not sufficient to check for the
 +	 * first <pripl> characters to be the same.
 +	 * We also have to make sure that the next character
 +	 * in the mountpoint path is either '\0' or '/'.
 +	 * Otherwise a jail in "/foo/bar" would be allowed
 +	 * to see a mount at "/foo/barbara".
 +	 */
 +	if (strncmp(prip, sp->f_mntonname, pripl) != 0 ||
 +	    (sp->f_mntonname[pripl] != '\0' && sp->f_mntonname[pripl] != '/'))
 +		return (-1);	/* not our business */
 +	return (pripl);
 +}
 +
 +/*
 + * Remove the jail chroot path from the mountpoint,
 + * so that imprisoned users see everything relative
 + * to their jail chroot.
 + */
 +static void
 +trim_prison_mount(sp, pripl)
 +	struct statfs *sp;
 +	int pripl;	/* prison path length */
 +{
 +	strcpy(sp->f_mntonname, sp->f_mntonname + pripl);
 +	/* If there's nothing left, this ought to be "/". */
 +	if (sp->f_mntonname[0] == '\0') {
 +		sp->f_mntonname[0] = '/';
 +		sp->f_mntonname[1] = '\0';
 +	}
 +}
 +
 +/*
   * Get filesystem statistics.
   */
  #ifndef _SYS_SYSPROTO_H_
 @@ -631,6 +719,8 @@
  	register struct mount *mp;
  	register struct statfs *sp;
  	int error;
 +	int pripl;
 +	int nonsu;
  	struct nameidata nd;
  	struct statfs sb;
  
 @@ -641,13 +731,19 @@
  	sp = &mp->mnt_stat;
  	NDFREE(&nd, NDF_ONLY_PNBUF);
  	vrele(nd.ni_vp);
 +	if ((pripl = check_prison_mount(p, sp, 1)) < 0)
 +		return (ENOENT);
  	error = VFS_STATFS(mp, sp, p);
  	if (error)
  		return (error);
  	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
 -	if (suser_xxx(p->p_ucred, 0, 0)) {
 +	nonsu = suser_xxx(p->p_ucred, 0, 0);
 +	if (nonsu || pripl) {
  		bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
 -		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
 +		if (nonsu)
 +			sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
 +		if (pripl)
 +			trim_prison_mount(&sb, pripl);
  		sp = &sb;
  	}
  	return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
 @@ -675,6 +771,8 @@
  	struct mount *mp;
  	register struct statfs *sp;
  	int error;
 +	int pripl;
 +	int nonsu;
  	struct statfs sb;
  
  	if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
 @@ -683,13 +781,19 @@
  	if (mp == NULL)
  		return (EBADF);
  	sp = &mp->mnt_stat;
 +	if ((pripl = check_prison_mount(p, sp, 1)) < 0)
 +		return (ENOENT);
  	error = VFS_STATFS(mp, sp, p);
  	if (error)
  		return (error);
  	sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
 -	if (suser_xxx(p->p_ucred, 0, 0)) {
 +	nonsu = suser_xxx(p->p_ucred, 0, 0);
 +	if (nonsu || pripl) {
  		bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
 -		sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
 +		if (nonsu)
 +			sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
 +		if (pripl)
 +			trim_prison_mount(&sb, pripl);
  		sp = &sb;
  	}
  	return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));
 @@ -718,13 +822,16 @@
  	register struct statfs *sp;
  	caddr_t sfsp;
  	long count, maxcount, error;
 +	int pripl;
 +	struct statfs sb;
  
  	maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
  	sfsp = (caddr_t)SCARG(uap, buf);
  	count = 0;
  	simple_lock(&mountlist_slock);
  	for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
 -		if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
 +		pripl = check_prison_mount(p, &mp->mnt_stat, 0);
 +		if (pripl < 0 || vfs_busy(mp, LK_NOWAIT, &mountlist_slock, p)) {
  			nmp = TAILQ_NEXT(mp, mnt_list);
  			continue;
  		}
 @@ -744,6 +851,11 @@
  				continue;
  			}
  			sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
 +			if (pripl) {
 +				bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
 +				trim_prison_mount(&sb, pripl);
 +				sp = &sb;
 +			}
  			error = copyout((caddr_t)sp, sfsp, sizeof(*sp));
  			if (error) {
  				vfs_unbusy(mp, p);
 --- src/sys/sys/jail.h.orig	Wed Nov  1 18:58:06 2000
 +++ src/sys/sys/jail.h	Wed Feb 27 15:40:17 2002
 @@ -30,6 +30,17 @@
  MALLOC_DECLARE(M_PRISON);
  #endif
  
 +
 +#ifndef MNAMELEN
 +/* This is taken from sys/mount.h. */
 +#ifdef __i386__
 +#define	MNAMELEN	80	/* length of buffer for returned name */
 +#endif
 +#ifdef __alpha__
 +#define	MNAMELEN	72	/* length of buffer for returned name */
 +#endif
 +#endif
 +
  /*
   * This structure describes a prison.  It is pointed to by all struct
   * proc's of the inmates.  pr_ref keeps track of them and is used to
 @@ -39,6 +50,7 @@
  struct prison {
  	int		pr_ref;
  	char 		pr_host[MAXHOSTNAMELEN];
 +	char		pr_path[MNAMELEN];
  	u_int32_t	pr_ip;
  	void		*pr_linux;
  };
 

From: Oliver Fromme <olli@fromme.com>
To: freebsd-gnats-submit@FreeBSD.org, olli@fromme.com
Cc:  
Subject: Re: kern/26740: [PATCH] jail improvement
Date: Tue, 28 Jan 2003 13:12:38 +0100 (CET)

 Hi,
 
 It is obvious that the patch in this PR will not be comitted.
 Therefore I suggest that this PR be closed.
 
 I have submitted a new patch:  PR kern/47586
 It fixes the shortcomings of the old patch in this PR (in
 particular, it scales much better, and also works fine in
 combined chroot/jail environments).
 
 -- 
 Oliver Fromme, Konrad-Celtis-Str. 72, 81369 Munich, Germany
 
 ``All that we see or seem is just a dream within a dream.''
 (E. A. Poe)
State-Changed-From-To: open->closed 
State-Changed-By: maxim 
State-Changed-When: Mon Mar 24 07:43:42 PST 2003 
State-Changed-Why:  
Closed at the submitter's request, obsoleted by kern/47586. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=26740 
>Unformatted:
