SUNRPC/nfs: Fix return value for nfs4_callback_compound()
authorTrond Myklebust <trondmy@gmail.com>
Tue, 9 Apr 2019 15:46:14 +0000 (11:46 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Wed, 24 Apr 2019 13:46:34 +0000 (09:46 -0400)
RPC server procedures are normally expected to return a __be32 encoded
status value of type 'enum rpc_accept_stat', however at least one function
wants to return an authentication status of type 'enum rpc_auth_stat'
in the case where authentication fails.
This patch adds functionality to allow this.

Fixes: a4e187d83d88 ("NFS: Don't drop CB requests with invalid principals")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfs/callback_xdr.c
include/linux/sunrpc/svc.h
net/sunrpc/svc.c

index 06233bfa6d73884ed7e52a30c64054c6b97b7457..73a5a5ea2976680559bc59293ccb554598557a80 100644 (file)
@@ -983,7 +983,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp)
 
 out_invalidcred:
        pr_warn_ratelimited("NFS: NFSv4 callback contains invalid cred\n");
-       return rpc_autherr_badcred;
+       return svc_return_autherr(rqstp, rpc_autherr_badcred);
 }
 
 /*
index e52385340b3b874c3d047b01873791b2bfbd5397..7ff12c9dbeaf9bcd4e8ce8a56afcf135aa30c0ca 100644 (file)
@@ -271,6 +271,7 @@ struct svc_rqst {
 #define        RQ_VICTIM       (5)                     /* about to be shut down */
 #define        RQ_BUSY         (6)                     /* request is busy */
 #define        RQ_DATA         (7)                     /* request has data */
+#define RQ_AUTHERR     (8)                     /* Request status is auth error */
        unsigned long           rq_flags;       /* flags field */
        ktime_t                 rq_qtime;       /* enqueue time */
 
@@ -504,6 +505,7 @@ unsigned int           svc_fill_write_vector(struct svc_rqst *rqstp,
 char             *svc_fill_symlink_pathname(struct svc_rqst *rqstp,
                                             struct kvec *first, void *p,
                                             size_t total);
+__be32            svc_return_autherr(struct svc_rqst *rqstp, __be32 auth_err);
 
 #define        RPC_MAX_ADDRBUFLEN      (63U)
 
index dbd19697ee38e40d5670e31d2b0392beb66aea2e..3d5dd6b86652bc06bc07b2a1b165dfb85489eca9 100644 (file)
@@ -1144,6 +1144,22 @@ void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...)
 static __printf(2,3) void svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) {}
 #endif
 
+__be32
+svc_return_autherr(struct svc_rqst *rqstp, __be32 auth_err)
+{
+       set_bit(RQ_AUTHERR, &rqstp->rq_flags);
+       return auth_err;
+}
+EXPORT_SYMBOL_GPL(svc_return_autherr);
+
+static __be32
+svc_get_autherr(struct svc_rqst *rqstp, __be32 *statp)
+{
+       if (test_and_clear_bit(RQ_AUTHERR, &rqstp->rq_flags))
+               return *statp;
+       return rpc_auth_ok;
+}
+
 /*
  * Common routine for processing the RPC request.
  */
@@ -1290,11 +1306,9 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
                                procp->pc_release(rqstp);
                        goto dropit;
                }
-               if (*statp == rpc_autherr_badcred) {
-                       if (procp->pc_release)
-                               procp->pc_release(rqstp);
-                       goto err_bad_auth;
-               }
+               auth_stat = svc_get_autherr(rqstp, statp);
+               if (auth_stat != rpc_auth_ok)
+                       goto err_release_bad_auth;
                if (*statp == rpc_success && procp->pc_encode &&
                    !procp->pc_encode(rqstp, resv->iov_base + resv->iov_len)) {
                        dprintk("svc: failed to encode reply\n");
@@ -1351,6 +1365,9 @@ err_bad_rpc:
        svc_putnl(resv, 2);
        goto sendit;
 
+err_release_bad_auth:
+       if (procp->pc_release)
+               procp->pc_release(rqstp);
 err_bad_auth:
        dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat));
        serv->sv_stats->rpcbadauth++;