]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/nfs/nfs_serv.c
xnu-792.6.22.tar.gz
[apple/xnu.git] / bsd / nfs / nfs_serv.c
index 7f513b01589d1421c52a92db59f5decb10741722..f6fc25fd4884de609610b04a5b2ddb2a8e338f7e 100644 (file)
@@ -147,7 +147,7 @@ nfsrv3_access(nfsd, slp, procp, mrq)
        mbuf_t mrep = nfsd->nd_mrep, md = nfsd->nd_md;
        mbuf_t nam = nfsd->nd_nam;
        caddr_t dpos = nfsd->nd_dpos;
-       vnode_t vp, dvp;
+       vnode_t vp;
        struct nfs_filehandle nfh;
        u_long *tl;
        long t1;
@@ -234,18 +234,17 @@ nfsrv3_access(nfsd, slp, procp, mrq)
                if (nfsrv_authorize(vp, NULL, testaction, &context, nxo, 0))
                        nfsmode &= ~NFSV3ACCESS_EXTEND;
        }
-       dvp = NULLVP;
+
        /*
-        * For hard links, this answer may be wrong if the vnode
+        * Note concerning NFSV3ACCESS_DELETE:
+        * For hard links, the answer may be wrong if the vnode
         * has multiple parents with different permissions.
+        * Also, some clients (e.g. MacOSX 10.3) may incorrectly
+        * interpret the missing/cleared DELETE bit.
+        * So we'll just leave the DELETE bit alone.  At worst,
+        * we're telling the client it might be able to do
+        * something it really can't.
         */
-       if ((nfsmode & NFSV3ACCESS_DELETE) &&
-           (((dvp = vnode_getparent(vp)) == NULL) ||
-            nfsrv_authorize(vp, dvp, KAUTH_VNODE_DELETE, &context, nxo, 0))) {
-               nfsmode &= ~NFSV3ACCESS_DELETE;
-       }
-       if (dvp != NULLVP)
-               vnode_put(dvp);
 
        if ((nfsmode & NFSV3ACCESS_EXECUTE) &&
            (vnode_isdir(vp) ||
@@ -2996,6 +2995,8 @@ nfsrv_symlink(nfsd, slp, procp, mrq)
                        VATTR_SET(vap, va_gid, kauth_cred_getgid(nfsd->nd_cr));
        }
        VATTR_SET(vap, va_type, VLNK);
+       VATTR_CLEAR_ACTIVE(vap, va_data_size);
+       VATTR_CLEAR_ACTIVE(vap, va_access_time);
 
        /* authorize before creating */
        error = nfsrv_authorize(dvp, NULL, KAUTH_VNODE_ADD_FILE, &context, nxo, 0);
@@ -3485,6 +3486,8 @@ nfsrv_readdir(nfsd, slp, procp, mrq)
        }
        context.vc_proc = procp;
        context.vc_ucred = nfsd->nd_cr;
+       if (!v3 || (nxo->nxo_flags & NX_32BITCLIENTS))
+               vnopflag |= VNODE_READDIR_SEEKOFF32;
        if (v3) {
                nfsm_srv_vattr_init(&at, v3);
                error = getret = vnode_getattr(vp, &at, &context);
@@ -3654,6 +3657,8 @@ again:
                        /* Finish off the record with the cookie */
                        nfsm_clget;
                        if (v3) {
+                               if (vnopflag & VNODE_READDIR_SEEKOFF32)
+                                       dp->d_seekoff &= 0x00000000ffffffffULL;
                                txdr_hyper(&dp->d_seekoff, &tquad);
                                *tl = tquad.nfsuquad[0];
                                bp += NFSX_UNSIGNED;
@@ -3761,6 +3766,8 @@ nfsrv_readdirplus(nfsd, slp, procp, mrq)
        }
        context.vc_proc = procp;
        context.vc_ucred = nfsd->nd_cr;
+       if (nxo->nxo_flags & NX_32BITCLIENTS)
+               vnopflag |= VNODE_READDIR_SEEKOFF32;
        nfsm_srv_vattr_init(&at, 1);
        error = getret = vnode_getattr(vp, &at, &context);
        if (!error && toff && verf && verf != at.va_filerev)
@@ -3931,6 +3938,8 @@ again:
                        fl.fl_fhsize = txdr_unsigned(nfhp->nfh_len);
                        fl.fl_fhok = nfs_true;
                        fl.fl_postopok = nfs_true;
+                       if (vnopflag & VNODE_READDIR_SEEKOFF32)
+                               dp->d_seekoff &= 0x00000000ffffffffULL;
                        txdr_hyper(&dp->d_seekoff, &fl.fl_off);
 
                        nfsm_clget;