Commit 804d8e0a authored by Chuck Lever's avatar Chuck Lever
Browse files

NFSD: Avoid calling OPDESC() with ops->opnum == OP_ILLEGAL



OPDESC() simply indexes into nfsd4_ops[] by the op's operation
number, without range checking that value. It assumes callers are
careful to avoid calling it with an out-of-bounds opnum value.

nfsd4_decode_compound() is not so careful, and can invoke OPDESC()
with opnum set to OP_ILLEGAL, which is 10044 -- well beyond the end
of nfsd4_ops[].

Reported-by: default avatarJeff Layton <jlayton@kernel.org>
Fixes: f4f9ef4a ("nfsd4: opdesc will be useful outside nfs4proc.c")
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 5f24a872
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -2476,10 +2476,12 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
	for (i = 0; i < argp->opcnt; i++) {
		op = &argp->ops[i];
		op->replay = NULL;
		op->opdesc = NULL;

		if (xdr_stream_decode_u32(argp->xdr, &op->opnum) < 0)
			return false;
		if (nfsd4_opnum_in_range(argp, op)) {
			op->opdesc = OPDESC(op);
			op->status = nfsd4_dec_ops[op->opnum](argp, &op->u);
			if (op->status != nfs_ok)
				trace_nfsd_compound_decode_err(argp->rqstp,
@@ -2490,7 +2492,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
			op->opnum = OP_ILLEGAL;
			op->status = nfserr_op_illegal;
		}
		op->opdesc = OPDESC(op);

		/*
		 * We'll try to cache the result in the DRC if any one
		 * op in the compound wants to be cached: