Quellcode durchsuchen

Implement Fuzz Injector

Closes: #284
Approved by: whitequark
jhwgh1968 vor 6 Jahren
Ursprung
Commit
326079c54c
2 geänderte Dateien mit 116 neuen und 0 gelöschten Zeilen
  1. 114 0
      src/phy/fuzz_injector.rs
  2. 2 0
      src/phy/mod.rs

+ 114 - 0
src/phy/fuzz_injector.rs

@@ -0,0 +1,114 @@
+use Result;
+use phy::{self, DeviceCapabilities, Device};
+use time::Instant;
+
+// This could be fixed once associated consts are stable.
+const MTU: usize = 1536;
+
+/// Represents a fuzzer. It is expected to replace bytes in the packet with fuzzed data.
+pub trait Fuzzer {
+    /// Modify a single packet with fuzzed data.
+    fn fuzz_packet(&self, packet_data: &mut [u8]);
+}
+
+/// A fuzz injector device.
+///
+/// A fuzz injector is a device that alters packets traversing through it according to the
+/// directions of a guided fuzzer. It is designed to support fuzzing internal state machines inside
+/// smoltcp, and is not for production use.
+#[allow(unused)]
+#[derive(Debug)]
+pub struct FuzzInjector<D: for<'a> Device<'a>, FTx: Fuzzer, FRx: Fuzzer> {
+    inner:   D,
+    fuzz_tx: FTx,
+    fuzz_rx: FRx,
+}
+
+#[allow(unused)]
+impl<D: for<'a> Device<'a>, FTx: Fuzzer, FRx: Fuzzer> FuzzInjector<D, FTx, FRx> {
+    /// Create a fuzz injector device.
+    pub fn new(inner: D, fuzz_tx: FTx, fuzz_rx: FRx) -> FuzzInjector<D, FTx, FRx> {
+        FuzzInjector { inner, fuzz_tx, fuzz_rx }
+    }
+
+    /// Return the underlying device, consuming the fuzz injector.
+    pub fn into_inner(self) -> D {
+        self.inner
+    }
+}
+
+impl<'a, D, FTx, FRx> Device<'a> for FuzzInjector<D, FTx, FRx>
+    where D: for<'b> Device<'b>,
+          FTx: Fuzzer + 'a,
+          FRx: Fuzzer + 'a
+{
+    type RxToken = RxToken<'a, <D as Device<'a>>::RxToken, FRx>;
+    type TxToken = TxToken<'a, <D as Device<'a>>::TxToken, FTx>;
+
+    fn capabilities(&self) -> DeviceCapabilities {
+        let mut caps = self.inner.capabilities();
+        if caps.max_transmission_unit > MTU {
+            caps.max_transmission_unit = MTU;
+        }
+        caps
+    }
+
+    fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
+        let &mut Self { ref mut inner, ref fuzz_rx, ref fuzz_tx } = self;
+        inner.receive().map(|(rx_token, tx_token)| {
+            let rx = RxToken {
+                fuzzer: fuzz_rx,
+                token:   rx_token,
+            };
+            let tx = TxToken {
+                fuzzer: fuzz_tx,
+                token:   tx_token,
+            };
+            (rx, tx)
+        })
+    }
+
+    fn transmit(&'a mut self) -> Option<Self::TxToken> {
+        let &mut Self { ref mut inner, fuzz_rx: _, ref fuzz_tx } = self;
+        inner.transmit().map(|token| TxToken {
+            fuzzer: fuzz_tx,
+            token:   token,
+        })
+    }
+}
+
+#[doc(hidden)]
+pub struct RxToken<'a, Rx: phy::RxToken, F: Fuzzer>{
+    fuzzer: &'a F,
+    token:   Rx,
+}
+
+impl<'a, Rx: phy::RxToken, FRx: Fuzzer> phy::RxToken for RxToken<'a, Rx, FRx> {
+    fn consume<R, F>(self, timestamp: Instant, f: F) -> Result<R>
+        where F: FnOnce(&mut [u8]) -> Result<R>
+    {
+        let Self { fuzzer, token } = self;
+        token.consume(timestamp, |buffer| {
+            fuzzer.fuzz_packet(buffer);
+            f(buffer)
+        })
+    }
+}
+
+#[doc(hidden)]
+pub struct TxToken<'a, Tx: phy::TxToken, F: Fuzzer> {
+    fuzzer: &'a F,
+    token:  Tx,
+}
+
+impl<'a, Tx: phy::TxToken, FTx: Fuzzer> phy::TxToken for TxToken<'a, Tx, FTx> {
+    fn consume<R, F>(self, timestamp: Instant, len: usize, f: F) -> Result<R>
+        where F: FnOnce(&mut [u8]) -> Result<R>
+    {
+        let Self { fuzzer, token } = self;
+        token.consume(timestamp, len, |mut buf| {
+            fuzzer.fuzz_packet(&mut buf);
+            f(buf)
+        })
+    }
+}

+ 2 - 0
src/phy/mod.rs

@@ -92,6 +92,7 @@ mod sys;
 
 mod tracer;
 mod fault_injector;
+mod fuzz_injector;
 mod pcap_writer;
 #[cfg(any(feature = "std", feature = "alloc"))]
 mod loopback;
@@ -105,6 +106,7 @@ pub use self::sys::wait;
 
 pub use self::tracer::Tracer;
 pub use self::fault_injector::FaultInjector;
+pub use self::fuzz_injector::{Fuzzer, FuzzInjector};
 pub use self::pcap_writer::{PcapLinkType, PcapMode, PcapSink, PcapWriter};
 #[cfg(any(feature = "std", feature = "alloc"))]
 pub use self::loopback::Loopback;