Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Enforce RLIMIT_FSIZE before VOP_WRITE. This adds suppor...



details:   https://anonhg.NetBSD.org/src/rev/a7492617536f
branches:  trunk
changeset: 754199:a7492617536f
user:      pooka <pooka%NetBSD.org@localhost>
date:      Fri Apr 23 15:38:46 2010 +0000

description:
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).

diffstat:

 sys/fs/msdosfs/msdosfs_vnops.c    |  16 +------------
 sys/fs/smbfs/smbfs_io.c           |  22 ++++++++++--------
 sys/fs/tmpfs/tmpfs_vnops.c        |  14 +----------
 sys/kern/vfs_vnops.c              |  44 +++++++++++++++++++++++++++++++++++++-
 sys/nfs/nfs_bio.c                 |  28 +++++++++++++-----------
 sys/ufs/ext2fs/ext2fs_readwrite.c |  18 +--------------
 sys/ufs/ufs/ufs_readwrite.c       |  18 +--------------
 7 files changed, 77 insertions(+), 83 deletions(-)

diffs (truncated from 395 to 300 lines):

diff -r 930359ed1f9b -r a7492617536f sys/fs/msdosfs/msdosfs_vnops.c
--- a/sys/fs/msdosfs/msdosfs_vnops.c    Fri Apr 23 15:37:01 2010 +0000
+++ b/sys/fs/msdosfs/msdosfs_vnops.c    Fri Apr 23 15:38:46 2010 +0000
@@ -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
diff -r 930359ed1f9b -r a7492617536f sys/fs/smbfs/smbfs_io.c
--- a/sys/fs/smbfs/smbfs_io.c   Fri Apr 23 15:37:01 2010 +0000
+++ b/sys/fs/smbfs/smbfs_io.c   Fri Apr 23 15:38:46 2010 +0000
@@ -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 lwp *l = curlwp;
        struct smb_cred scred;
-       struct lwp *l = curlwp;
-       struct proc *p = l->l_proc;
        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",
diff -r 930359ed1f9b -r a7492617536f sys/fs/tmpfs/tmpfs_vnops.c
--- a/sys/fs/tmpfs/tmpfs_vnops.c        Fri Apr 23 15:37:01 2010 +0000
+++ b/sys/fs/tmpfs/tmpfs_vnops.c        Fri Apr 23 15:38:46 2010 +0000
@@ -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;
 
diff -r 930359ed1f9b -r a7492617536f sys/kern/vfs_vnops.c
--- a/sys/kern/vfs_vnops.c      Fri Apr 23 15:37:01 2010 +0000
+++ b/sys/kern/vfs_vnops.c      Fri Apr 23 15:38:46 2010 +0000
@@ -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);
 }
diff -r 930359ed1f9b -r a7492617536f sys/nfs/nfs_bio.c
--- a/sys/nfs/nfs_bio.c Fri Apr 23 15:37:01 2010 +0000
+++ b/sys/nfs/nfs_bio.c Fri Apr 23 15:38:46 2010 +0000
@@ -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);
-       }



Home | Main Index | Thread Index | Old Index