VirtualBox

source: vbox/trunk/src/libs/libslirp-4.8.0/fuzzing/slirp_fuzz_tcp_header.c@ 105529

Last change on this file since 105529 was 105529, checked in by vboxsync, 8 months ago

libs/libslirp: libslirp 4.8.0 fixed exports. bugref:10268

  • Property svn:eol-style set to native
File size: 5.2 KB
Line 
1#include <glib.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include "../src/libslirp.h"
5#include "helper.h"
6#include "slirp_base_fuzz.h"
7
8#ifdef CUSTOM_MUTATOR
9extern size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize);
10size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size, size_t MaxSize, unsigned int Seed);
11
12/// This is a custom mutator, this allows us to mutate only specific parts of
13/// the input and fix the checksum so the packet isn't rejected for bad reasons.
14extern size_t LLVMFuzzerCustomMutator(uint8_t *Data, size_t Size,
15 size_t MaxSize, unsigned int Seed)
16{
17 size_t current_size = Size;
18 uint8_t *Data_ptr = Data;
19 uint8_t *ip_data;
20 uint32_t ipsource;
21 bool mutated = false;
22
23 pcap_hdr_t *hdr = (void *)Data_ptr;
24 pcaprec_hdr_t *rec = NULL;
25
26 if (current_size < sizeof(pcap_hdr_t)) {
27 return 0;
28 }
29
30 Data_ptr += sizeof(*hdr);
31 current_size -= sizeof(*hdr);
32
33 if (hdr->magic_number == 0xd4c3b2a1) {
34 g_debug("FIXME: byteswap fields");
35 return 0;
36 } /* else assume native pcap file */
37 if (hdr->network != 1) {
38 return 0;
39 }
40
41 for ( ; current_size > sizeof(*rec); Data_ptr += rec->incl_len, current_size -= rec->incl_len) {
42 rec = (void *)Data_ptr;
43 Data_ptr += sizeof(*rec);
44 current_size -= sizeof(*rec);
45
46 if (rec->incl_len != rec->orig_len) {
47 return 0;
48 }
49 if (rec->incl_len > current_size) {
50 return 0;
51 }
52 if (rec->incl_len < 14 + 1) {
53 return 0;
54 }
55
56 ip_data = Data_ptr + 14;
57
58 if (rec->incl_len >= 14 + 16) {
59 ipsource = * (uint32_t*) (ip_data + 12);
60
61 // This an answer, which we will produce, so don't mutate
62 if (ipsource == htonl(0x0a000202) || ipsource == htonl(0x0a000203))
63 continue;
64 }
65
66 // Exclude packets that are not TCP from the mutation strategy
67 if (ip_data[9] != IPPROTO_TCP)
68 continue;
69
70 // Allocate a bit more than needed, this is useful for
71 // checksum calculation.
72 uint8_t Data_to_mutate[MaxSize + PSEUDO_IP_SIZE];
73 uint8_t ip_hl = (ip_data[0] & 0xF);
74 uint8_t ip_hl_in_bytes = ip_hl * 4; /* ip header length */
75
76 // The size inside the packet can't be trusted, if it is too big it can
77 // lead to heap overflows in the fuzzing code.
78 // Fixme : don't use ip_hl_in_bytes inside the fuzzing code, maybe use the
79 // rec->incl_len and manually calculate the size.
80 if (ip_hl_in_bytes > rec->incl_len - 14)
81 return 0;
82
83 uint8_t *start_of_tcp = ip_data + ip_hl_in_bytes;
84 uint8_t tcp_header_size = (*(start_of_tcp + 12) >> 4) * 4;
85 uint16_t total_length = ntohs(*((uint16_t *)ip_data + 1));
86 uint16_t tcp_size = (total_length - (uint16_t)ip_hl_in_bytes);
87
88 // The size inside the packet can't be trusted, if it is too big it can
89 // lead to heap overflows in the fuzzing code.
90 // Fixme : don't use tcp_size inside the fuzzing code, maybe use the
91 // rec->incl_len and manually calculate the size.
92 if (tcp_size > MaxSize || tcp_size > rec->incl_len - 14 - ip_hl_in_bytes ||
93 tcp_header_size > MaxSize || tcp_header_size > rec->incl_len - 14 - ip_hl_in_bytes)
94 return 0;
95
96 // Copy interesting data to the `Data_to_mutate` array
97 // here we want to fuzz everything in the tcp packet
98 memset(Data_to_mutate, 0, MaxSize + PSEUDO_IP_SIZE);
99 memcpy(Data_to_mutate, start_of_tcp, tcp_size);
100
101 // Call to libfuzzer's mutation function.
102 // Pass the whole TCP packet, mutate it and then fix checksum value
103 // so the packet isn't rejected.
104 // The new size of the data is returned by LLVMFuzzerMutate.
105 // Fixme: allow to change the size of the TCP packet, this will require
106 // to fix the size before calculating the new checksum and change
107 // how the Data_ptr is advanced.
108 // Most offsets bellow should be good for when the switch will be
109 // done to avoid overwriting new/mutated data.
110 LLVMFuzzerMutate(Data_to_mutate, tcp_header_size, tcp_header_size);
111
112 // Set the `checksum` field to 0 to calculate the new checksum
113
114 *(uint16_t *)(Data_to_mutate + 16) = (uint16_t)0;
115 // Copy the source and destination IP addresses, the tcp length and
116 // protocol number at the end of the `Data_to_mutate` array to calculate
117 // the new checksum.
118 memcpy(Data_to_mutate + tcp_size, ip_data + 12, 4*2);
119
120 *(Data_to_mutate + tcp_size + 9) = IPPROTO_TCP;
121
122 *(Data_to_mutate + tcp_size + 10) = (uint8_t)(tcp_size / 256);
123 *(Data_to_mutate + tcp_size + 11) = (uint8_t)(tcp_size % 256);
124
125 uint16_t new_checksum =
126 compute_checksum(Data_to_mutate, tcp_size + PSEUDO_IP_SIZE);
127 *(uint16_t *)(Data_to_mutate + 16) = htons(new_checksum);
128
129 // Copy the mutated data back to the `Data` array
130 memcpy(start_of_tcp, Data_to_mutate, tcp_size);
131
132 mutated = true;
133 }
134
135 if (!mutated)
136 return 0;
137
138 return Size;
139}
140#endif // CUSTOM_MUTATOR
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette