Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 22 Apr 2002 14:10:02 -0700 (PDT)
From:      <pmedwards@eircom.net>
To:        freebsd-bugs@FreeBSD.org
Subject:   Re: kern/37057: Problem with rlimits on filesystem mounted from /dev/vn0c
Message-ID:  <200204222110.g3MLA2448203@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help
The following reply was made to PR kern/37057; it has been noted by GNATS.

From: <pmedwards@eircom.net>
To: freebsd-gnats-submit@FreeBSD.org, 
Cc: xi@borderworlds.dk
Subject: Re: kern/37057: Problem with rlimits on filesystem mounted from /dev/vn0c
Date: Mon, 22 Apr 2002 19:18:09 +0100

 This is a multi-part message in MIME format.
 ---------MDCZE8EMTF8F6VRK2SCVG9BS
 Content-Type: text/plain
 Content-Transfer-Encoding: 7bit
 
 My wonderfully reliable mail server is still has DNS issues, and can't talk to freebsd.org.
 
 original message sent from peter.edwards@openet-telecom.com attached
 
 
 
 
 
 ---------MDCZE8EMTF8F6VRK2SCVG9BS
 Content-Type: text/plain
 Content-Disposition: attachment; filename="response.txt"
 
 This comes from the filesystem on which the VN device's file lies,
 rather from anything above it.  To explain: When you write to a
 file on a filesystem hosted by a VN device, which is in turn hosted
 by a file on a UFS filesystem, you get a layering like this:
 
 1: UFS filesystem
 2: VN device
 3: UFS filesystem 
 4: disk device/swap
 
 The filesystem (1) is the one you are explicitly writing to.
 
 Filesystem (3) is the one generating the error: each filesystem
 implementation's write() method checks, and the VN device calls
 VOP_WRITE(). Of course, the VN device is accessing the entire file on which
 the filesystem is laid out, so, its not surprising that it attempts to write
 where it shouldn't.
 
 There's a comment in ufs/ufs/ufs_readwrite.c which indicates what
 
 /*
  * Maybe this should be above the vnode op call, but so long as
  * file servers have no limits, I don't think it matters.
  */
 
 (This is present in rev 1.1, so its quite old)
 
 I wonder if:
     The vn device should use VOP_STRATEGY to do its I/O
 and
     If the best place for the check isn't in the write(2) system
     call, where we know which object the user is acting on.
 
 However, its not quite trivial to move this to the VOP operation
 or write system call, because each filesystem implementation currently
 updates uio_offset for IO_APPEND mode writes, and only the
 filesystem-internal representation of the vnode has the current
 length of the file available, so you don't have enough information
 in VOP_WRITE or dofilewrite() to do the rlimits check, unlesee you call
 VOP_GETATTR() and that would probably be Bad.
 
 In the meantime, you can hack your way around by noting that user
 requests tend to be UIO_USERSPACE, and kernel requests in UIO_SYSSPACE, and
 adding that to the check for sending SIGXFSZ (patch attached).
 
 Security could be an issue here. However, I think the only way to
 extend a file from user-land at all is via write[v](2) or truncate(2),
 and the only UIO_USERSPACEs I can find that can ever hit VOP_WRITE
 come from write[v](2).
 
 mmap(2) and strategy interactions never extend the file, so they
 are not an issue.
 
 (Which actually brings up another point: you can currently modify a file at
 an offset beyond your maximum filesize with mmap(), but not with
 write(). Of course, you can't make the file any bigger with mmap(),
 but its still "weaker" security in mmap() than write())
 
 So I don't think there's any loss of security with the following
 patch, but I'm not an expert, so beware...
 
 The patch updates the checks done by SMBFS, EXT2FS, MSDOSFS NFS, NWFS, and,
 of course UFS/FFS.
 
 -------------->8-------------- Cut Here -------------->8--------------
 
 Index: fs/smbfs/smbfs_io.c
 ===================================================================
 RCS file: /pub/FreeBSD/development/FreeBSD-CVS/src/sys/fs/smbfs/smbfs_io.c,v
 retrieving revision 1.3.2.1
 diff -u -r1.3.2.1 smbfs_io.c
 --- fs/smbfs/smbfs_io.c	22 May 2001 08:32:26 -0000	1.3.2.1
 +++ fs/smbfs/smbfs_io.c	22 Apr 2002 13:42:59 -0000
 @@ -270,7 +270,8 @@
  	}
  	if (uiop->uio_resid == 0)
  		return 0;
 -	if (p && uiop->uio_offset + uiop->uio_resid > p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
 +	if (p && uiop->uio_segflg == UIO_USERSPACE && uiop->uio_offset +
 +	    uiop->uio_resid > p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
  		psignal(p, SIGXFSZ);
  		return EFBIG;
  	}
 Index: gnu/ext2fs/ext2_readwrite.c
 ===================================================================
 RCS file: /pub/FreeBSD/development/FreeBSD-CVS/src/sys/gnu/ext2fs/ext2_readwrite.c,v
 retrieving revision 1.18.2.2
 diff -u -r1.18.2.2 ext2_readwrite.c
 --- gnu/ext2fs/ext2_readwrite.c	22 Dec 2000 18:44:33 -0000	1.18.2.2
 +++ gnu/ext2fs/ext2_readwrite.c	22 Apr 2002 13:43:26 -0000
 @@ -218,6 +218,7 @@
  	 */
  	p = uio->uio_procp;
  	if (vp->v_type == VREG && p &&
 +	    uio->segflg == UIO_USERSPACE &&
  	    uio->uio_offset + uio->uio_resid >
  	    p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
  		psignal(p, SIGXFSZ);
 Index: msdosfs/msdosfs_vnops.c
 ===================================================================
 RCS file: /pub/FreeBSD/development/FreeBSD-CVS/src/sys/msdosfs/Attic/msdosfs_vnops.c,v
 retrieving revision 1.95.2.1
 diff -u -r1.95.2.1 msdosfs_vnops.c
 --- msdosfs/msdosfs_vnops.c	18 Jul 2000 13:19:13 -0000	1.95.2.1
 +++ msdosfs/msdosfs_vnops.c	22 Apr 2002 14:26:49 -0000
 @@ -688,6 +688,7 @@
  	 * If they've exceeded their filesize limit, tell them about it.
  	 */
  	if (p &&
 +	    uio->uio_segflg == UIO_USERSPACE &&
  	    ((uoff_t)uio->uio_offset + uio->uio_resid >
  	    p->p_rlimit[RLIMIT_FSIZE].rlim_cur)) {
  		psignal(p, SIGXFSZ);
 Index: nfs/nfs_bio.c
 ===================================================================
 RCS file: /pub/FreeBSD/development/FreeBSD-CVS/src/sys/nfs/Attic/nfs_bio.c,v
 retrieving revision 1.83.2.2
 diff -u -r1.83.2.2 nfs_bio.c
 --- nfs/nfs_bio.c	20 Dec 2001 19:56:28 -0000	1.83.2.2
 +++ nfs/nfs_bio.c	22 Apr 2002 13:44:51 -0000
 @@ -822,8 +822,8 @@
  	 * Maybe this should be above the vnode op call, but so long as
  	 * file servers have no limits, i don't think it matters
  	 */
 -	if (p && uio->uio_offset + uio->uio_resid >
 -	      p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
 +	if (p && uio->uio_segflg == UIO_USERSPACE && uio->uio_offset +
 +	    uio->uio_resid > p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
  		psignal(p, SIGXFSZ);
  		if (haverslock)
  			nfs_rsunlock(np, p);
 Index: nwfs/nwfs_io.c
 ===================================================================
 RCS file: /pub/FreeBSD/development/FreeBSD-CVS/src/sys/nwfs/Attic/nwfs_io.c,v
 retrieving revision 1.6.2.1
 diff -u -r1.6.2.1 nwfs_io.c
 --- nwfs/nwfs_io.c	25 Oct 2000 02:11:10 -0000	1.6.2.1
 +++ nwfs/nwfs_io.c	22 Apr 2002 13:45:23 -0000
 @@ -235,7 +235,8 @@
  		}
  	}
  	if (uiop->uio_resid == 0) return 0;
 -	if (p && uiop->uio_offset + uiop->uio_resid > p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
 +	if (p && uiop->uio_segflg == UIO_USERSPACE &&
 +	    uiop->uio_offset + uiop->uio_resid > p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
  		psignal(p, SIGXFSZ);
  		return (EFBIG);
  	}
 Index: ufs/ufs/ufs_readwrite.c
 ===================================================================
 RCS file: /pub/FreeBSD/development/FreeBSD-CVS/src/sys/ufs/ufs/ufs_readwrite.c,v
 retrieving revision 1.65.2.10
 diff -u -r1.65.2.10 ufs_readwrite.c
 --- ufs/ufs/ufs_readwrite.c	6 Mar 2002 19:53:08 -0000	1.65.2.10
 +++ ufs/ufs/ufs_readwrite.c	22 Apr 2002 14:36:14 -0000
 @@ -382,6 +382,7 @@
  /*
   * Vnode op for writing.
   */
 +
  int
  WRITE(ap)
  	struct vop_write_args /* {
 @@ -451,9 +452,12 @@
  	/*
  	 * Maybe this should be above the vnode op call, but so long as
  	 * file servers have no limits, I don't think it matters.
 +	 * XXX: Only check !UIO_USERSPACE requests: we assume requests
 +	 * initiated by the kernel will be valid.
  	 */
  	p = uio->uio_procp;
  	if (vp->v_type == VREG && p &&
 +	    uio->uio_segflg == UIO_USERSPACE &&
  	    uio->uio_offset + uio->uio_resid >
  	    p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
  		psignal(p, SIGXFSZ);
 ---------MDCZE8EMTF8F6VRK2SCVG9BS--

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200204222110.g3MLA2448203>