better nfsrv_access() control, from netbsd
authorderaadt <deraadt@openbsd.org>
Sat, 14 Dec 1996 15:36:50 +0000 (15:36 +0000)
committerderaadt <deraadt@openbsd.org>
Sat, 14 Dec 1996 15:36:50 +0000 (15:36 +0000)
sys/nfs/nfs_serv.c
sys/nfs/nfs_var.h

index 82ccc51..ba8b2d8 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nfs_serv.c,v 1.7 1996/11/08 23:20:14 niklas Exp $     */
+/*     $OpenBSD: nfs_serv.c,v 1.8 1996/12/14 15:36:50 deraadt Exp $    */
 /*     $NetBSD: nfs_serv.c,v 1.25 1996/03/02 15:55:52 jtk Exp $        */
 
 /*
@@ -132,7 +132,7 @@ nfsrv3_access(nfsd, slp, procp, mrq)
        }
        nfsmode = fxdr_unsigned(u_int32_t, *tl);
        if ((nfsmode & NFSV3ACCESS_READ) &&
-               nfsrv_access(vp, VREAD, cred, rdonly, procp))
+               nfsrv_access(vp, VREAD, cred, rdonly, procp, 0))
                nfsmode &= ~NFSV3ACCESS_READ;
        if (vp->v_type == VDIR)
                testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
@@ -140,14 +140,14 @@ nfsrv3_access(nfsd, slp, procp, mrq)
        else
                testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
        if ((nfsmode & testmode) &&
-               nfsrv_access(vp, VWRITE, cred, rdonly, procp))
+               nfsrv_access(vp, VWRITE, cred, rdonly, procp, 0))
                nfsmode &= ~testmode;
        if (vp->v_type == VDIR)
                testmode = NFSV3ACCESS_LOOKUP;
        else
                testmode = NFSV3ACCESS_EXECUTE;
        if ((nfsmode & testmode) &&
-               nfsrv_access(vp, VEXEC, cred, rdonly, procp))
+               nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0))
                nfsmode &= ~testmode;
        getret = VOP_GETATTR(vp, &va, cred, procp);
        vput(vp);
@@ -315,7 +315,7 @@ nfsrv_setattr(nfsd, slp, procp, mrq)
                        error = EISDIR;
                        goto out;
                } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
-                       procp)) != 0)
+                       procp, 0)) != 0)
                        goto out;
        }
        error = VOP_SETATTR(vp, &va, cred, procp);
@@ -571,8 +571,8 @@ nfsrv_read(nfsd, slp, procp, mrq)
        }
        if (!error) {
            nqsrv_getl(vp, ND_READ);
-           if ((error = nfsrv_access(vp, VREAD, cred, rdonly, procp)) != 0)
-               error = nfsrv_access(vp, VEXEC, cred, rdonly, procp);
+           if ((error = nfsrv_access(vp, VREAD, cred, rdonly, procp, 1)) != 0)
+               error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 1);
        }
        getret = VOP_GETATTR(vp, &va, cred, procp);
        if (!error)
@@ -785,7 +785,7 @@ nfsrv_write(nfsd, slp, procp, mrq)
        }
        if (!error) {
                nqsrv_getl(vp, ND_WRITE);
-               error = nfsrv_access(vp, VWRITE, cred, rdonly, procp);
+               error = nfsrv_access(vp, VWRITE, cred, rdonly, procp, 1);
        }
        if (error) {
                vput(vp);
@@ -1050,7 +1050,7 @@ loop1:
                    vp = NULL;
                if (!error) {
                    nqsrv_getl(vp, ND_WRITE);
-                   error = nfsrv_access(vp, VWRITE, cred, rdonly, procp);
+                   error = nfsrv_access(vp, VWRITE, cred, rdonly, procp, 1);
                }
     
                if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
@@ -1391,7 +1391,7 @@ nfsrv_create(nfsd, slp, procp, mrq)
                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                if (va.va_size != -1) {
                        error = nfsrv_access(vp, VWRITE, cred,
-                           (nd.ni_cnd.cn_flags & RDONLY), procp);
+                           (nd.ni_cnd.cn_flags & RDONLY), procp, 0);
                        if (!error) {
                                nqsrv_getl(vp, ND_WRITE);
                                tempsize = va.va_size;
@@ -2446,7 +2446,7 @@ nfsrv_readdir(nfsd, slp, procp, mrq)
 #endif
        }
        if (!error)
-               error = nfsrv_access(vp, VEXEC, cred, rdonly, procp);
+               error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
        if (error) {
                vput(vp);
                nfsm_reply(NFSX_POSTOPATTR(v3));
@@ -2713,7 +2713,7 @@ nfsrv_readdirplus(nfsd, slp, procp, mrq)
 #endif
        if (!error) {
                nqsrv_getl(vp, ND_READ);
-               error = nfsrv_access(vp, VEXEC, cred, rdonly, procp);
+               error = nfsrv_access(vp, VEXEC, cred, rdonly, procp, 0);
        }
        if (error) {
                vput(vp);
@@ -3285,18 +3285,20 @@ nfsrv_noop(nfsd, slp, procp, mrq)
  * refer to files already opened by a Unix client. You cannot just use
  * vn_writechk() and VOP_ACCESS() for two reasons.
  * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
- * 2 - The owner is to be given access irrespective of mode bits so that
- *     processes that chmod after opening a file don't break. I don't like
- *     this because it opens a security hole, but since the nfs server opens
- *     a security hole the size of a barn door anyhow, what the heck.
+ * 2 - The owner is to be given access irrespective of mode bits for some
+ *     operations, so that processes that chmod after opening a file don't
+ *     break. I don't like this because it opens a security hole, but since
+ *     the nfs server opens a security hole the size of a barn door anyhow,
+ *     what the heck.
  */
 int
-nfsrv_access(vp, flags, cred, rdonly, p)
+nfsrv_access(vp, flags, cred, rdonly, p, override)
        register struct vnode *vp;
        int flags;
        register struct ucred *cred;
        int rdonly;
        struct proc *p;
+       int override;
 {
        struct vattr vattr;
        int error;
@@ -3325,11 +3327,13 @@ nfsrv_access(vp, flags, cred, rdonly, p)
                if ((vp->v_flag & VTEXT) && !vnode_pager_uncache(vp))
                        return (ETXTBSY);
        }
-       error = VOP_GETATTR(vp, &vattr, cred, p);
-       if (error)
-               return (error);
-       if ((error = VOP_ACCESS(vp, flags, cred, p)) != 0 &&
-           cred->cr_uid != vattr.va_uid)
-               return (error);
-       return (0);
+       error = VOP_ACCESS(vp, flags, cred, p);
+       /*
+        * Allow certain operations for the owner (reads and writes
+        * on files that are already open).
+        */
+       if (override && (error == EPERM || error == EACCES) &&
+           cred->cr_uid == vattr.va_uid)
+               error = 0;
+       return error;
 }
index 5e94422..8b7ac70 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: nfs_var.h,v 1.3 1996/09/21 11:06:20 deraadt Exp $     */
+/*     $OpenBSD: nfs_var.h,v 1.4 1996/12/14 15:36:51 deraadt Exp $     */
 /*     $NetBSD: nfs_var.h,v 1.3 1996/02/18 11:53:54 fvdl Exp $ */
 
 /*
@@ -227,7 +227,8 @@ int nfsrv_null __P((struct nfsrv_descript *, struct nfssvc_sock *,
                    struct proc *, struct mbuf **));
 int nfsrv_noop __P((struct nfsrv_descript *, struct nfssvc_sock *,
                    struct proc *, struct mbuf **));
-int nfsrv_access __P((struct vnode *, int, struct ucred *, int, struct proc *));
+int nfsrv_access __P((struct vnode *, int, struct ucred *, int, struct proc *,
+                   int));
 
 /* nfs_socket.c */
 int nfs_connect __P((struct nfsmount *, struct nfsreq *));