fuzz_injector.rs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. use crate::phy::{self, Device, DeviceCapabilities};
  2. use crate::time::Instant;
  3. use crate::Result;
  4. // This could be fixed once associated consts are stable.
  5. const MTU: usize = 1536;
  6. /// Represents a fuzzer. It is expected to replace bytes in the packet with fuzzed data.
  7. pub trait Fuzzer {
  8. /// Modify a single packet with fuzzed data.
  9. fn fuzz_packet(&self, packet_data: &mut [u8]);
  10. }
  11. /// A fuzz injector device.
  12. ///
  13. /// A fuzz injector is a device that alters packets traversing through it according to the
  14. /// directions of a guided fuzzer. It is designed to support fuzzing internal state machines inside
  15. /// smoltcp, and is not for production use.
  16. #[allow(unused)]
  17. #[derive(Debug)]
  18. #[cfg_attr(feature = "defmt", derive(defmt::Format))]
  19. pub struct FuzzInjector<D: for<'a> Device<'a>, FTx: Fuzzer, FRx: Fuzzer> {
  20. inner: D,
  21. fuzz_tx: FTx,
  22. fuzz_rx: FRx,
  23. }
  24. #[allow(unused)]
  25. impl<D: for<'a> Device<'a>, FTx: Fuzzer, FRx: Fuzzer> FuzzInjector<D, FTx, FRx> {
  26. /// Create a fuzz injector device.
  27. pub fn new(inner: D, fuzz_tx: FTx, fuzz_rx: FRx) -> FuzzInjector<D, FTx, FRx> {
  28. FuzzInjector {
  29. inner,
  30. fuzz_tx,
  31. fuzz_rx,
  32. }
  33. }
  34. /// Return the underlying device, consuming the fuzz injector.
  35. pub fn into_inner(self) -> D {
  36. self.inner
  37. }
  38. }
  39. impl<'a, D, FTx, FRx> Device<'a> for FuzzInjector<D, FTx, FRx>
  40. where
  41. D: for<'b> Device<'b>,
  42. FTx: Fuzzer + 'a,
  43. FRx: Fuzzer + 'a,
  44. {
  45. type RxToken = RxToken<'a, <D as Device<'a>>::RxToken, FRx>;
  46. type TxToken = TxToken<'a, <D as Device<'a>>::TxToken, FTx>;
  47. fn capabilities(&self) -> DeviceCapabilities {
  48. let mut caps = self.inner.capabilities();
  49. if caps.max_transmission_unit > MTU {
  50. caps.max_transmission_unit = MTU;
  51. }
  52. caps
  53. }
  54. fn receive(&'a mut self) -> Option<(Self::RxToken, Self::TxToken)> {
  55. let &mut Self {
  56. ref mut inner,
  57. ref fuzz_rx,
  58. ref fuzz_tx,
  59. } = self;
  60. inner.receive().map(|(rx_token, tx_token)| {
  61. let rx = RxToken {
  62. fuzzer: fuzz_rx,
  63. token: rx_token,
  64. };
  65. let tx = TxToken {
  66. fuzzer: fuzz_tx,
  67. token: tx_token,
  68. };
  69. (rx, tx)
  70. })
  71. }
  72. fn transmit(&'a mut self) -> Option<Self::TxToken> {
  73. let &mut Self {
  74. ref mut inner,
  75. fuzz_rx: _,
  76. ref fuzz_tx,
  77. } = self;
  78. inner.transmit().map(|token| TxToken {
  79. fuzzer: fuzz_tx,
  80. token: token,
  81. })
  82. }
  83. }
  84. #[doc(hidden)]
  85. pub struct RxToken<'a, Rx: phy::RxToken, F: Fuzzer + 'a> {
  86. fuzzer: &'a F,
  87. token: Rx,
  88. }
  89. impl<'a, Rx: phy::RxToken, FRx: Fuzzer> phy::RxToken for RxToken<'a, Rx, FRx> {
  90. fn consume<R, F>(self, timestamp: Instant, f: F) -> Result<R>
  91. where
  92. F: FnOnce(&mut [u8]) -> Result<R>,
  93. {
  94. let Self { fuzzer, token } = self;
  95. token.consume(timestamp, |buffer| {
  96. fuzzer.fuzz_packet(buffer);
  97. f(buffer)
  98. })
  99. }
  100. }
  101. #[doc(hidden)]
  102. pub struct TxToken<'a, Tx: phy::TxToken, F: Fuzzer + 'a> {
  103. fuzzer: &'a F,
  104. token: Tx,
  105. }
  106. impl<'a, Tx: phy::TxToken, FTx: Fuzzer> phy::TxToken for TxToken<'a, Tx, FTx> {
  107. fn consume<R, F>(self, timestamp: Instant, len: usize, f: F) -> Result<R>
  108. where
  109. F: FnOnce(&mut [u8]) -> Result<R>,
  110. {
  111. let Self { fuzzer, token } = self;
  112. token.consume(timestamp, len, |buf| {
  113. fuzzer.fuzz_packet(buf);
  114. f(buf)
  115. })
  116. }
  117. }