Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFSD: Prevent a potential integer overflow

If the tag length is >= U32_MAX - 3 then the "length + 4" addition
can result in an integer overflow. Address this by splitting the
decoding into several steps so that decode_cb_compound4res() does
not have to perform arithmetic on the unsafe length value.

Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Cc: stable@vger.kernel.org
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

+7 -7
+7 -7
fs/nfsd/nfs4callback.c
··· 287 287 u32 length; 288 288 __be32 *p; 289 289 290 - p = xdr_inline_decode(xdr, 4 + 4); 290 + p = xdr_inline_decode(xdr, XDR_UNIT); 291 291 if (unlikely(p == NULL)) 292 292 goto out_overflow; 293 - hdr->status = be32_to_cpup(p++); 293 + hdr->status = be32_to_cpup(p); 294 294 /* Ignore the tag */ 295 - length = be32_to_cpup(p++); 296 - p = xdr_inline_decode(xdr, length + 4); 297 - if (unlikely(p == NULL)) 295 + if (xdr_stream_decode_u32(xdr, &length) < 0) 298 296 goto out_overflow; 299 - p += XDR_QUADLEN(length); 300 - hdr->nops = be32_to_cpup(p); 297 + if (xdr_inline_decode(xdr, length) == NULL) 298 + goto out_overflow; 299 + if (xdr_stream_decode_u32(xdr, &hdr->nops) < 0) 300 + goto out_overflow; 301 301 return 0; 302 302 out_overflow: 303 303 return -EIO;