NFS: Don't drop CB requests with invalid principals
[pandora-kernel.git] / fs / nfs / callback_xdr.c
index 726e59a..9839726 100644 (file)
@@ -9,6 +9,8 @@
 #include <linux/sunrpc/svc.h>
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
+#include <linux/ratelimit.h>
+#include <linux/printk.h>
 #include <linux/slab.h>
 #include <linux/sunrpc/bc_xprt.h>
 #include "nfs4_fs.h"
@@ -167,7 +169,7 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound
        if (hdr->minorversion <= 1) {
                hdr->cb_ident = ntohl(*p++); /* ignored by v4.1 */
        } else {
-               printk(KERN_WARNING "%s: NFSv4 server callback with "
+               pr_warn_ratelimited("NFS: %s: NFSv4 server callback with "
                        "illegal minor version %u!\n",
                        __func__, hdr->minorversion);
                return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
@@ -449,16 +451,18 @@ static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp,
        args->csa_nrclists = ntohl(*p++);
        args->csa_rclists = NULL;
        if (args->csa_nrclists) {
-               args->csa_rclists = kmalloc(args->csa_nrclists *
-                                           sizeof(*args->csa_rclists),
-                                           GFP_KERNEL);
+               args->csa_rclists = kmalloc_array(args->csa_nrclists,
+                                                 sizeof(*args->csa_rclists),
+                                                 GFP_KERNEL);
                if (unlikely(args->csa_rclists == NULL))
                        goto out;
 
                for (i = 0; i < args->csa_nrclists; i++) {
                        status = decode_rc_list(xdr, &args->csa_rclists[i]);
-                       if (status)
+                       if (status) {
+                               args->csa_nrclists = i;
                                goto out_free;
+                       }
                }
        }
        status = 0;
@@ -874,7 +878,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
        if (hdr_arg.minorversion == 0) {
                cps.clp = nfs4_find_client_ident(hdr_arg.cb_ident);
                if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp))
-                       return rpc_drop_reply;
+                       goto out_invalidcred;
        }
 
        hdr_res.taglen = hdr_arg.taglen;
@@ -901,6 +905,10 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
        nfs_put_client(cps.clp);
        dprintk("%s: done, status = %u\n", __func__, ntohl(status));
        return rpc_success;
+
+out_invalidcred:
+       pr_warn_ratelimited("NFS: NFSv4 callback contains invalid cred\n");
+       return rpc_autherr_badcred;
 }
 
 /*