Module Name:    src
Committed By:   pooka
Date:           Fri Apr 23 15:38:47 UTC 2010

Modified Files:
        src/sys/fs/msdosfs: msdosfs_vnops.c
        src/sys/fs/smbfs: smbfs_io.c
        src/sys/fs/tmpfs: tmpfs_vnops.c
        src/sys/kern: vfs_vnops.c
        src/sys/nfs: nfs_bio.c
        src/sys/ufs/ext2fs: ext2fs_readwrite.c
        src/sys/ufs/ufs: ufs_readwrite.c

Log Message:
Enforce RLIMIT_FSIZE before VOP_WRITE.  This adds support to file
system drivers where it was missing from and fixes one buggy
implementation.  The arguably weird semantics of the check are
maintained (v_size vs. va_bytes, overwrite).


To generate a diff of this commit:
cvs rdiff -u -r1.64 -r1.65 src/sys/fs/msdosfs/msdosfs_vnops.c
cvs rdiff -u -r1.33 -r1.34 src/sys/fs/smbfs/smbfs_io.c
cvs rdiff -u -r1.68 -r1.69 src/sys/fs/tmpfs/tmpfs_vnops.c
cvs rdiff -u -r1.170 -r1.171 src/sys/kern/vfs_vnops.c
cvs rdiff -u -r1.183 -r1.184 src/sys/nfs/nfs_bio.c
cvs rdiff -u -r1.55 -r1.56 src/sys/ufs/ext2fs/ext2fs_readwrite.c
cvs rdiff -u -r1.94 -r1.95 src/sys/ufs/ufs/ufs_readwrite.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/fs/msdosfs/msdosfs_vnops.c
diff -u src/sys/fs/msdosfs/msdosfs_vnops.c:1.64 src/sys/fs/msdosfs/msdosfs_vnops.c:1.65
--- src/sys/fs/msdosfs/msdosfs_vnops.c:1.64	Fri Apr  9 08:09:18 2010
+++ src/sys/fs/msdosfs/msdosfs_vnops.c	Fri Apr 23 15:38:46 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: msdosfs_vnops.c,v 1.64 2010/04/09 08:09:18 hannken Exp $	*/
+/*	$NetBSD: msdosfs_vnops.c,v 1.65 2010/04/23 15:38:46 pooka Exp $	*/
 
 /*-
  * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.64 2010/04/09 08:09:18 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.65 2010/04/23 15:38:46 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -564,7 +564,6 @@
 	vsize_t bytelen;
 	off_t oldoff;
 	struct uio *uio = ap->a_uio;
-	struct proc *p = curproc;
 	struct vnode *vp = ap->a_vp;
 	struct denode *dep = VTODE(vp);
 	struct msdosfsmount *pmp = dep->de_pmp;
@@ -599,17 +598,6 @@
 	if (uio->uio_offset + uio->uio_resid > MSDOSFS_FILESIZE_MAX)
 		return (EFBIG);
 
-	/*
-	 * If they've exceeded their filesize limit, tell them about it.
-	 */
-	if (((uio->uio_offset + uio->uio_resid) >
-	    p->p_rlimit[RLIMIT_FSIZE].rlim_cur)) {
-		mutex_enter(proc_lock);
-		psignal(p, SIGXFSZ);
-		mutex_exit(proc_lock);
-		return (EFBIG);
-	}
-
 	fstrans_start(vp->v_mount, FSTRANS_SHARED);
 	/*
 	 * If the offset we are starting the write at is beyond the end of

Index: src/sys/fs/smbfs/smbfs_io.c
diff -u src/sys/fs/smbfs/smbfs_io.c:1.33 src/sys/fs/smbfs/smbfs_io.c:1.34
--- src/sys/fs/smbfs/smbfs_io.c:1.33	Mon Jun 22 21:13:50 2009
+++ src/sys/fs/smbfs/smbfs_io.c	Fri Apr 23 15:38:47 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: smbfs_io.c,v 1.33 2009/06/22 21:13:50 njoly Exp $	*/
+/*	$NetBSD: smbfs_io.c,v 1.34 2010/04/23 15:38:47 pooka Exp $	*/
 
 /*
  * Copyright (c) 2000-2001, Boris Popov
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: smbfs_io.c,v 1.33 2009/06/22 21:13:50 njoly Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smbfs_io.c,v 1.34 2010/04/23 15:38:47 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -244,9 +244,8 @@
 {
 	struct smbmount *smp = VTOSMBFS(vp);
 	struct smbnode *np = VTOSMB(vp);
-	struct smb_cred scred;
 	struct lwp *l = curlwp;
-	struct proc *p = l->l_proc;
+	struct smb_cred scred;
 	int error = 0;
 	int extended = 0;
 	size_t resid = uiop->uio_resid;
@@ -270,6 +269,8 @@
 		}
 		if (ioflag & IO_APPEND) {
 #if notyet
+			struct proc *p = curproc;
+
 			/*
 			 * File size can be changed by another client
 			 */
@@ -277,18 +278,19 @@
 			error = VOP_GETATTR(vp, &vattr, cred, td);
 			if (error)
 				return (error);
+			if (np->n_size + uiop->uio_resid >
+			    p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
+				mutex_enter(proc_lock);
+				psignal(p, SIGXFSZ);
+				mutex_exit(proc_lock);
+				return EFBIG;
+			}
 #endif
 			uiop->uio_offset = np->n_size;
 		}
 	}
 	if (uiop->uio_resid == 0)
 		return 0;
-	if (p && uiop->uio_offset + uiop->uio_resid > p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
-		mutex_enter(proc_lock);
-		psignal(p, SIGXFSZ);
-		mutex_exit(proc_lock);
-		return EFBIG;
-	}
 	smb_makescred(&scred, l, cred);
 	error = smb_write(smp->sm_share, np->n_fid, uiop, &scred);
 	SMBVDEBUG("after: ofs=%lld,resid=%zu,err=%d\n",

Index: src/sys/fs/tmpfs/tmpfs_vnops.c
diff -u src/sys/fs/tmpfs/tmpfs_vnops.c:1.68 src/sys/fs/tmpfs/tmpfs_vnops.c:1.69
--- src/sys/fs/tmpfs/tmpfs_vnops.c:1.68	Mon Mar 29 13:11:33 2010
+++ src/sys/fs/tmpfs/tmpfs_vnops.c	Fri Apr 23 15:38:47 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: tmpfs_vnops.c,v 1.68 2010/03/29 13:11:33 pooka Exp $	*/
+/*	$NetBSD: tmpfs_vnops.c,v 1.69 2010/04/23 15:38:47 pooka Exp $	*/
 
 /*
  * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.68 2010/03/29 13:11:33 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.69 2010/04/23 15:38:47 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/dirent.h>
@@ -594,7 +594,6 @@
 	bool extended;
 	int error;
 	off_t oldsize;
-	struct proc *p = curproc;
 	struct tmpfs_node *node;
 	struct uvm_object *uobj;
 
@@ -613,15 +612,6 @@
 		goto out;
 	}
 
-	if (((uio->uio_offset + uio->uio_resid) >
-	    p->p_rlimit[RLIMIT_FSIZE].rlim_cur)) {
-		mutex_enter(proc_lock);
-		psignal(p, SIGXFSZ);
-		mutex_exit(proc_lock);
-		error = EFBIG;
-		goto out;
-	}
-
 	if (ioflag & IO_APPEND)
 		uio->uio_offset = node->tn_size;
 

Index: src/sys/kern/vfs_vnops.c
diff -u src/sys/kern/vfs_vnops.c:1.170 src/sys/kern/vfs_vnops.c:1.171
--- src/sys/kern/vfs_vnops.c:1.170	Mon Mar 29 13:11:32 2010
+++ src/sys/kern/vfs_vnops.c	Fri Apr 23 15:38:46 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_vnops.c,v 1.170 2010/03/29 13:11:32 pooka Exp $	*/
+/*	$NetBSD: vfs_vnops.c,v 1.171 2010/04/23 15:38:46 pooka Exp $	*/
 
 /*-
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.170 2010/03/29 13:11:32 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.171 2010/04/23 15:38:46 pooka Exp $");
 
 #include "veriexec.h"
 
@@ -351,6 +351,32 @@
 	return (error);
 }
 
+static int
+enforce_rlimit_fsize(struct vnode *vp, struct uio *uio, int ioflag)
+{
+	struct lwp *l = curlwp;
+	off_t testoff;
+
+	if (uio->uio_rw != UIO_WRITE || vp->v_type != VREG)
+		return 0;
+
+	KASSERT(VOP_ISLOCKED(vp) == LK_EXCLUSIVE);
+	if (ioflag & IO_APPEND)
+		testoff = vp->v_size;
+	else
+		testoff = uio->uio_offset;
+
+	if (testoff + uio->uio_resid >
+	    l->l_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
+		mutex_enter(proc_lock);
+		psignal(l->l_proc, SIGXFSZ);
+		mutex_exit(proc_lock);
+		return EFBIG;
+	}
+
+	return 0;
+}
+
 /*
  * Package up an I/O request on a vnode into a uio and do it.
  */
@@ -382,16 +408,23 @@
 	} else {
 		auio.uio_vmspace = l->l_proc->p_vmspace;
 	}
+
+	if ((error = enforce_rlimit_fsize(vp, &auio, ioflg)) != 0)
+		goto out;
+
 	if (rw == UIO_READ) {
 		error = VOP_READ(vp, &auio, ioflg, cred);
 	} else {
 		error = VOP_WRITE(vp, &auio, ioflg, cred);
 	}
+
 	if (aresid)
 		*aresid = auio.uio_resid;
 	else
 		if (auio.uio_resid && error == 0)
 			error = EIO;
+
+ out:
 	if ((ioflg & IO_NODELOCKED) == 0) {
 		VOP_UNLOCK(vp, 0);
 	}
@@ -520,7 +553,12 @@
 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
 	uio->uio_offset = *offset;
 	count = uio->uio_resid;
+
+	if ((error = enforce_rlimit_fsize(vp, uio, ioflag)) != 0)
+		goto out;
+
 	error = VOP_WRITE(vp, uio, ioflag, cred);
+
 	if (flags & FOF_UPDATE_OFFSET) {
 		if (ioflag & IO_APPEND) {
 			/*
@@ -535,6 +573,8 @@
 		} else
 			*offset += count - uio->uio_resid;
 	}
+
+ out:
 	VOP_UNLOCK(vp, 0);
 	return (error);
 }

Index: src/sys/nfs/nfs_bio.c
diff -u src/sys/nfs/nfs_bio.c:1.183 src/sys/nfs/nfs_bio.c:1.184
--- src/sys/nfs/nfs_bio.c:1.183	Sat Mar 14 14:46:11 2009
+++ src/sys/nfs/nfs_bio.c	Fri Apr 23 15:38:47 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs_bio.c,v 1.183 2009/03/14 14:46:11 dsl Exp $	*/
+/*	$NetBSD: nfs_bio.c,v 1.184 2010/04/23 15:38:47 pooka Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_bio.c,v 1.183 2009/03/14 14:46:11 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_bio.c,v 1.184 2010/04/23 15:38:47 pooka Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_nfs.h"
@@ -480,6 +480,19 @@
 		if (error)
 			return (error);
 		uio->uio_offset = np->n_size;
+
+		/*
+		 * This is already checked above VOP_WRITE, but recheck
+		 * the append case here to make sure our idea of the
+		 * file size is as fresh as possible.
+		 */
+		if (uio->uio_offset + uio->uio_resid >
+		      l->l_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
+			mutex_enter(proc_lock);
+			psignal(l->l_proc, SIGXFSZ);
+			mutex_exit(proc_lock);
+			return (EFBIG);
+		}
 	}
 	if (uio->uio_offset < 0)
 		return (EINVAL);
@@ -487,17 +500,6 @@
 		return (EFBIG);
 	if (uio->uio_resid == 0)
 		return (0);
-	/*
-	 * 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 (l && l->l_proc && uio->uio_offset + uio->uio_resid >
-	      l->l_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
-		mutex_enter(proc_lock);
-		psignal(l->l_proc, SIGXFSZ);
-		mutex_exit(proc_lock);
-		return (EFBIG);
-	}
 
 	origoff = uio->uio_offset;
 	do {

Index: src/sys/ufs/ext2fs/ext2fs_readwrite.c
diff -u src/sys/ufs/ext2fs/ext2fs_readwrite.c:1.55 src/sys/ufs/ext2fs/ext2fs_readwrite.c:1.56
--- src/sys/ufs/ext2fs/ext2fs_readwrite.c:1.55	Mon Oct 19 18:41:17 2009
+++ src/sys/ufs/ext2fs/ext2fs_readwrite.c	Fri Apr 23 15:38:46 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs_readwrite.c,v 1.55 2009/10/19 18:41:17 bouyer Exp $	*/
+/*	$NetBSD: ext2fs_readwrite.c,v 1.56 2010/04/23 15:38:46 pooka Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -60,7 +60,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_readwrite.c,v 1.55 2009/10/19 18:41:17 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_readwrite.c,v 1.56 2010/04/23 15:38:46 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -224,7 +224,6 @@
 	struct inode *ip;
 	struct m_ext2fs *fs;
 	struct buf *bp;
-	struct proc *p;
 	struct ufsmount *ump;
 	daddr_t lbn;
 	off_t osize;
@@ -270,19 +269,6 @@
 	if (uio->uio_offset < 0 ||
 	    (uint64_t)uio->uio_offset + uio->uio_resid > ump->um_maxfilesize)
 		return (EFBIG);
-	/*
-	 * Maybe this should be above the vnode op call, but so long as
-	 * file servers have no limits, I don't think it matters.
-	 */
-	p = curproc;
-	if (vp->v_type == VREG && p &&
-	    uio->uio_offset + uio->uio_resid >
-	    p->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
-		mutex_enter(proc_lock);
-		psignal(p, SIGXFSZ);
-		mutex_exit(proc_lock);
-		return (EFBIG);
-	}
 	if (uio->uio_resid == 0)
 		return (0);
 

Index: src/sys/ufs/ufs/ufs_readwrite.c
diff -u src/sys/ufs/ufs/ufs_readwrite.c:1.94 src/sys/ufs/ufs/ufs_readwrite.c:1.95
--- src/sys/ufs/ufs/ufs_readwrite.c:1.94	Sun Feb 22 20:28:07 2009
+++ src/sys/ufs/ufs/ufs_readwrite.c	Fri Apr 23 15:38:46 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_readwrite.c,v 1.94 2009/02/22 20:28:07 ad Exp $	*/
+/*	$NetBSD: ufs_readwrite.c,v 1.95 2010/04/23 15:38:46 pooka Exp $	*/
 
 /*-
  * Copyright (c) 1993
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: ufs_readwrite.c,v 1.94 2009/02/22 20:28:07 ad Exp $");
+__KERNEL_RCSID(1, "$NetBSD: ufs_readwrite.c,v 1.95 2010/04/23 15:38:46 pooka Exp $");
 
 #ifdef LFS_READWRITE
 #define	FS			struct lfs
@@ -217,7 +217,6 @@
 	struct inode *ip;
 	FS *fs;
 	struct buf *bp;
-	struct lwp *l;
 	kauth_cred_t cred;
 	daddr_t lbn;
 	off_t osize, origoff, oldoff, preallocoff, endallocoff, nsize;
@@ -272,19 +271,6 @@
 	if (vp == fs->lfs_ivnode)
 		return (EPERM);
 #endif
-	/*
-	 * Maybe this should be above the vnode op call, but so long as
-	 * file servers have no limits, I don't think it matters.
-	 */
-	l = curlwp;
-	if (vp->v_type == VREG && l &&
-	    uio->uio_offset + uio->uio_resid >
-	    l->l_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
-		mutex_enter(proc_lock);
-		psignal(l->l_proc, SIGXFSZ);
-		mutex_exit(proc_lock);
-		return (EFBIG);
-	}
 	if (uio->uio_resid == 0)
 		return (0);
 

Reply via email to