From ea1d03f8e38aca376adcb80b1851b97a0816a5e9 Mon Sep 17 00:00:00 2001 From: Pierre Chifflier Date: Mon, 8 Nov 2021 23:11:24 +0100 Subject: [PATCH] rust/nfs: add a maximum number of operations per compound The `count` combinator preallocates a number of bytes. Since the value is untrusted, this can result in an Out Of Memory allocation. Use a maximum value, large enough to cover all current implementations. --- rust/src/nfs/nfs4_records.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/rust/src/nfs/nfs4_records.rs b/rust/src/nfs/nfs4_records.rs index 94248db01f..1eb3629b8b 100644 --- a/rust/src/nfs/nfs4_records.rs +++ b/rust/src/nfs/nfs4_records.rs @@ -25,6 +25,10 @@ use nom7::{Err, IResult}; use crate::nfs::types::*; +// Maximum number of operations per compound +// Linux defines NFSD_MAX_OPS_PER_COMPOUND to 16 (tested in Linux 5.15.1). +const NFSD_MAX_OPS_PER_COMPOUND: usize = 64; + #[derive(Debug,PartialEq)] pub enum Nfs4RequestContent<'a> { PutFH(Nfs4Handle<'a>), @@ -464,6 +468,9 @@ pub fn parse_nfs4_request_compound(i: &[u8]) -> IResult<&[u8], Nfs4RequestCompou let (i, _tag) = cond(tag_len > 0, take(tag_len as usize))(i)?; let (i, _min_ver) = be_u32(i)?; let (i, ops_cnt) = be_u32(i)?; + if ops_cnt as usize > NFSD_MAX_OPS_PER_COMPOUND { + return Err(Err::Error(make_error(i, ErrorKind::Count))); + } let (i, commands) = count(parse_request_compound_command, ops_cnt as usize)(i)?; Ok((i, Nfs4RequestCompoundRecord { commands })) } @@ -816,6 +823,9 @@ pub fn parse_nfs4_response_compound(i: &[u8]) -> IResult<&[u8], Nfs4ResponseComp let (i, tag_len) = be_u32(i)?; let (i, _tag) = cond(tag_len > 0, take(tag_len as usize))(i)?; let (i, ops_cnt) = be_u32(i)?; + if ops_cnt as usize > NFSD_MAX_OPS_PER_COMPOUND { + return Err(Err::Error(make_error(i, ErrorKind::Count))); + } let (i, commands) = count(nfs4_res_compound_command, ops_cnt as usize)(i)?; Ok((i, Nfs4ResponseCompoundRecord { status, commands })) }