]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
rust/nfs: add a maximum number of operations per compound
authorPierre Chifflier <chifflier@wzdftpd.net>
Mon, 8 Nov 2021 22:11:24 +0000 (23:11 +0100)
committerVictor Julien <vjulien@oisf.net>
Mon, 22 Nov 2021 10:20:23 +0000 (11:20 +0100)
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

index 94248db01fe39c71d1d090ebc975e2f119522457..1eb3629b8b6ce03cad0f7f368743254778772aca 100644 (file)
@@ -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 }))
 }