Commit 83dd59a0 authored by Trond Myklebust's avatar Trond Myklebust Committed by J. Bruce Fields
Browse files

SUNRPC/nfs: Fix return value for nfs4_callback_compound()



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: a4e187d8 ("NFS: Don't drop CB requests with invalid principals")
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 8a9f4f41
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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);
}

/*
+2 −0
Original line number Diff line number Diff line
@@ -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)

+22 −5
Original line number Diff line number Diff line
@@ -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++;