ALSA: dummy: Implement timer backend switching more safely
[pandora-kernel.git] / fs / nfsd / nfs4proc.c
index 08921b8..9a959de 100644 (file)
@@ -267,6 +267,7 @@ static __be32
 do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
 {
        __be32 status;
+       int accmode = 0;
 
        /* Only reclaims from previously confirmed clients are valid */
        if ((status = nfs4_check_open_reclaim(&open->op_clientid)))
@@ -284,9 +285,19 @@ do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_
 
        open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
                (open->op_iattr.ia_size == 0);
+       /*
+        * In the delegation case, the client is telling us about an
+        * open that it *already* performed locally, some time ago.  We
+        * should let it succeed now if possible.
+        *
+        * In the case of a CLAIM_FH open, on the other hand, the client
+        * may be counting on us to enforce permissions (the Linux 4.1
+        * client uses this for normal opens, for example).
+        */
+       if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEG_CUR_FH)
+               accmode = NFSD_MAY_OWNER_OVERRIDE;
 
-       status = do_open_permission(rqstp, current_fh, open,
-                                   NFSD_MAY_OWNER_OVERRIDE);
+       status = do_open_permission(rqstp, current_fh, open, accmode);
 
        return status;
 }
@@ -518,15 +529,6 @@ nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        switch (create->cr_type) {
        case NF4LNK:
-               /* ugh! we have to null-terminate the linktext, or
-                * vfs_symlink() will choke.  it is always safe to
-                * null-terminate by brute force, since at worst we
-                * will overwrite the first byte of the create namelen
-                * in the XDR buffer, which has already been extracted
-                * during XDR decode.
-                */
-               create->cr_linkname[create->cr_linklen] = 0;
-
                status = nfsd_symlink(rqstp, &cstate->current_fh,
                                      create->cr_name, create->cr_namelen,
                                      create->cr_linkname, create->cr_linklen,
@@ -1109,7 +1111,8 @@ static bool need_wrongsec_check(struct svc_rqst *rqstp)
         */
        if (argp->opcnt == resp->opcnt)
                return false;
-
+       if (next->opnum == OP_ILLEGAL)
+               return false;
        nextd = OPDESC(next);
        /*
         * Rest of 2.6.3.1.1: certain operations will return WRONGSEC
@@ -1213,6 +1216,12 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
                /* If op is non-idempotent */
                if (opdesc->op_flags & OP_MODIFIES_SOMETHING) {
                        plen = opdesc->op_rsize_bop(rqstp, op);
+                       /*
+                        * If there's still another operation, make sure
+                        * we'll have space to at least encode an error:
+                        */
+                       if (resp->opcnt < args->opcnt)
+                               plen += COMPOUND_ERR_SLACK_SPACE;
                        op->status = nfsd4_check_resp_size(resp, plen);
                }
 
@@ -1370,7 +1379,8 @@ static inline u32 nfsd4_setattr_rsize(struct svc_rqst *rqstp, struct nfsd4_op *o
 
 static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
 {
-       return (op_encode_hdr_size + 2 + 1024) * sizeof(__be32);
+       return (op_encode_hdr_size + 2 + XDR_QUADLEN(NFS4_VERIFIER_SIZE)) *
+                                                               sizeof(__be32);
 }
 
 static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)