/src/libmodbus/fuzz/FuzzClient.c
Line | Count | Source (jump to first uncovered line) |
1 | | |
2 | | /* Copyright 2022 Google LLC |
3 | | Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | you may not use this file except in compliance with the License. |
5 | | You may obtain a copy of the License at |
6 | | http://www.apache.org/licenses/LICENSE-2.0 |
7 | | Unless required by applicable law or agreed to in writing, software |
8 | | distributed under the License is distributed on an "AS IS" BASIS, |
9 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
10 | | See the License for the specific language governing permissions and |
11 | | limitations under the License. |
12 | | */ |
13 | | #include <stdio.h> |
14 | | #include <stdlib.h> |
15 | | #include <stdint.h> |
16 | | #include <unistd.h> |
17 | | #include <string.h> |
18 | | #include <errno.h> |
19 | | #include <pthread.h> |
20 | | #include <sys/socket.h> |
21 | | #include <netinet/in.h> |
22 | | #include <arpa/inet.h> |
23 | | |
24 | | #include <modbus.h> |
25 | | #include "unit-test.h" |
26 | | |
27 | 1 | #define PORT 8080 |
28 | 182 | #define kMinInputLength 9 |
29 | 81 | #define kMaxInputLength MODBUS_RTU_MAX_ADU_LENGTH |
30 | | |
31 | | struct Fuzzer{ |
32 | | uint16_t port; |
33 | | char* file; |
34 | | |
35 | | FILE* inFile; |
36 | | uint64_t size; |
37 | | uint8_t* buffer; |
38 | | |
39 | | pthread_t thread; |
40 | | int socket; |
41 | | }; |
42 | | typedef struct Fuzzer Fuzzer; |
43 | | |
44 | | int client(Fuzzer *fuzzer); |
45 | | |
46 | 0 | void fuzzinit(Fuzzer *fuzzer){ |
47 | 0 | struct sockaddr_in server_addr; |
48 | 0 | fuzzer->socket = socket(AF_INET, SOCK_STREAM, 0); |
49 | |
|
50 | 0 | server_addr.sin_family = AF_INET; |
51 | 0 | server_addr.sin_port = htons(fuzzer->port); |
52 | 0 | server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); |
53 | |
|
54 | 0 | setsockopt(fuzzer->socket, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)); |
55 | |
|
56 | 0 | bind(fuzzer->socket, (struct sockaddr*)&server_addr, sizeof(server_addr)); |
57 | 0 | listen(fuzzer->socket,1); |
58 | 0 | } |
59 | | |
60 | 0 | void *Server(void *args){ |
61 | |
|
62 | 0 | Fuzzer *fuzzer = (Fuzzer*)args; |
63 | 0 | { |
64 | 0 | int client; |
65 | 0 | char clientData[10240]; |
66 | 0 | struct sockaddr_in clientAddr; |
67 | 0 | uint32_t clientSZ = sizeof(clientAddr); |
68 | |
|
69 | 0 | client = accept(fuzzer->socket, (struct sockaddr*)&clientAddr, &clientSZ); |
70 | |
|
71 | 0 | send(client, fuzzer->buffer, fuzzer->size, 0); |
72 | 0 | recv(client, clientData, sizeof(clientData), 0); |
73 | |
|
74 | 0 | send(client, fuzzer->buffer, fuzzer->size, 0); |
75 | 0 | recv(client, clientData, sizeof(clientData), 0); |
76 | |
|
77 | 0 | shutdown(client,SHUT_RDWR); |
78 | 0 | close(client); |
79 | 0 | } |
80 | 0 | pthread_exit(NULL); |
81 | 0 | } |
82 | | |
83 | 0 | void clean(Fuzzer *fuzzer){ |
84 | 0 | {//Server |
85 | 0 | shutdown(fuzzer->socket,SHUT_RDWR); |
86 | 0 | close(fuzzer->socket); |
87 | 0 | } |
88 | 0 | free(fuzzer); |
89 | 0 | } |
90 | | |
91 | 91 | extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
92 | | |
93 | 91 | if (size < kMinInputLength || size > kMaxInputLength){ |
94 | 90 | return 0; |
95 | 90 | } |
96 | | |
97 | 1 | Fuzzer *fuzzer = (Fuzzer*)malloc(sizeof(Fuzzer)); |
98 | 1 | fuzzer->port = PORT; |
99 | 1 | fuzzer->size = size; |
100 | 1 | fuzzer->buffer = data; |
101 | | |
102 | 1 | fuzzinit(fuzzer); |
103 | | |
104 | 1 | pthread_create(&fuzzer->thread, NULL,Server,fuzzer); |
105 | 1 | client(fuzzer); |
106 | 1 | pthread_join(fuzzer->thread, NULL);/* To Avoid UAF*/ |
107 | | |
108 | 1 | clean(fuzzer); |
109 | 1 | return 0; |
110 | 91 | } |
111 | | |
112 | | int client(Fuzzer *fuzzer){ |
113 | | |
114 | | uint8_t *tab_rp_bits = NULL; |
115 | | uint16_t *tab_rp_registers = NULL; |
116 | | modbus_t *ctx = NULL; |
117 | | int nb_points; |
118 | | int rc; |
119 | | |
120 | | ctx = modbus_new_tcp("127.0.0.1", fuzzer->port); |
121 | | |
122 | | if (ctx == NULL) { |
123 | | fprintf(stderr, "Unable to allocate libmodbus context\n"); |
124 | | return -1; |
125 | | } |
126 | | |
127 | | if (modbus_connect(ctx) == -1) { |
128 | | fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno)); |
129 | | modbus_free(ctx); |
130 | | return -1; |
131 | | } |
132 | | |
133 | | /* Allocate and initialize the memory to store the bits */ |
134 | | nb_points = (UT_BITS_NB > UT_INPUT_BITS_NB) ? UT_BITS_NB : UT_INPUT_BITS_NB; |
135 | | tab_rp_bits = (uint8_t *) malloc(nb_points * sizeof(uint8_t)); |
136 | | memset(tab_rp_bits, 0, nb_points * sizeof(uint8_t)); |
137 | | |
138 | | /* Allocate and initialize the memory to store the registers */ |
139 | | nb_points = (UT_REGISTERS_NB > UT_INPUT_REGISTERS_NB) ? |
140 | | UT_REGISTERS_NB : UT_INPUT_REGISTERS_NB; |
141 | | tab_rp_registers = (uint16_t *) malloc(nb_points * sizeof(uint16_t)); |
142 | | memset(tab_rp_registers, 0, nb_points * sizeof(uint16_t)); |
143 | | |
144 | | //Read |
145 | | rc = modbus_read_bits(ctx, UT_BITS_ADDRESS, UT_BITS_NB, tab_rp_bits); |
146 | | |
147 | | rc = modbus_read_registers(ctx, UT_REGISTERS_ADDRESS, |
148 | | UT_REGISTERS_NB, tab_rp_registers); |
149 | | |
150 | | /* Free the memory */ |
151 | | free(tab_rp_bits); |
152 | | free(tab_rp_registers); |
153 | | |
154 | | /* Close the connection */ |
155 | | modbus_close(ctx); |
156 | | modbus_free(ctx); |
157 | | |
158 | | return rc; |
159 | | } |