/src/libmodbus/fuzz/FuzzServer.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Copyright 2021 Google LLC |
2 | | Licensed under the Apache License, Version 2.0 (the "License"); |
3 | | you may not use this file except in compliance with the License. |
4 | | You may obtain a copy of the License at |
5 | | http://www.apache.org/licenses/LICENSE-2.0 |
6 | | Unless required by applicable law or agreed to in writing, software |
7 | | distributed under the License is distributed on an "AS IS" BASIS, |
8 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
9 | | See the License for the specific language governing permissions and |
10 | | limitations under the License. |
11 | | */ |
12 | | #include <stdio.h> |
13 | | #include <errno.h> |
14 | | #include <stdlib.h> |
15 | | #include <stdint.h> |
16 | | #include <unistd.h> |
17 | | #include <string.h> |
18 | | #include <stddef.h> |
19 | | #include <pthread.h> |
20 | | #include <arpa/inet.h> |
21 | | #include <sys/socket.h> |
22 | | #include <netinet/in.h> |
23 | | #include <netinet/tcp.h> |
24 | | |
25 | | #include <modbus.h> |
26 | | #include "unit-test.h" |
27 | | |
28 | 1 | #define PORT 8080 |
29 | 40 | #define kMinInputLength 9 |
30 | 17 | #define kMaxInputLength MODBUS_RTU_MAX_ADU_LENGTH |
31 | | |
32 | | struct Fuzzer{ |
33 | | uint16_t port; |
34 | | char* file; |
35 | | |
36 | | FILE* inFile; |
37 | | uint64_t size; |
38 | | uint8_t* buffer; |
39 | | |
40 | | pthread_t thread; |
41 | | int socket; |
42 | | }; |
43 | | typedef struct Fuzzer Fuzzer; |
44 | | |
45 | | int server(Fuzzer *fuzzer); |
46 | | |
47 | 1 | void *client(void *args){ |
48 | | |
49 | 1 | Fuzzer *fuzzer = (Fuzzer*)args; |
50 | 1 | int sockfd; |
51 | 1 | struct sockaddr_in serv_addr; |
52 | | |
53 | 1 | sockfd = socket(AF_INET, SOCK_STREAM, 0); |
54 | 1 | serv_addr.sin_family = AF_INET; |
55 | 1 | serv_addr.sin_port = htons(fuzzer->port); |
56 | 1 | serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); |
57 | | |
58 | 1 | while(1){/* Try until connect*/ |
59 | 1 | if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){ |
60 | 0 | continue; |
61 | 1 | }else{ |
62 | 1 | break; |
63 | 1 | } |
64 | 1 | } |
65 | | |
66 | 1 | send(sockfd,fuzzer->buffer,fuzzer->size,0); |
67 | | |
68 | 1 | close(sockfd); |
69 | 1 | pthread_exit(NULL); |
70 | 1 | } |
71 | | |
72 | 20 | extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
73 | | |
74 | 20 | if (size < kMinInputLength || size > kMaxInputLength){ |
75 | 19 | return 0; |
76 | 19 | } |
77 | | |
78 | 1 | Fuzzer *fuzzer = (Fuzzer*)malloc(sizeof(Fuzzer)); |
79 | 1 | fuzzer->port = PORT; |
80 | | |
81 | 1 | fuzzer->size = size; |
82 | 1 | fuzzer->buffer = data; |
83 | | |
84 | 1 | pthread_create(&fuzzer->thread, NULL,client,fuzzer); |
85 | 1 | server(fuzzer); |
86 | 1 | pthread_join(fuzzer->thread, NULL); /* Avoid UAF*/ |
87 | | |
88 | 1 | free(fuzzer); |
89 | 1 | return 0; |
90 | 20 | } |
91 | | |
92 | | int server(Fuzzer *fuzzer) |
93 | 1 | { |
94 | 1 | int s = -1; |
95 | 1 | modbus_t *ctx; |
96 | 1 | modbus_mapping_t *mb_mapping; |
97 | 1 | int rc; |
98 | 1 | int i; |
99 | 1 | uint8_t *query; |
100 | | |
101 | 1 | ctx = modbus_new_tcp("127.0.0.1", fuzzer->port); |
102 | 1 | query = malloc(MODBUS_TCP_MAX_ADU_LENGTH); |
103 | | |
104 | 1 | mb_mapping = modbus_mapping_new_start_address( |
105 | 1 | UT_BITS_ADDRESS, UT_BITS_NB, |
106 | 1 | UT_INPUT_BITS_ADDRESS, UT_INPUT_BITS_NB, |
107 | 1 | UT_REGISTERS_ADDRESS, UT_REGISTERS_NB_MAX, |
108 | 1 | UT_INPUT_REGISTERS_ADDRESS, UT_INPUT_REGISTERS_NB); |
109 | 1 | if (mb_mapping == NULL) { |
110 | 0 | fprintf(stderr, "Failed to allocate the mapping: %s\n", |
111 | 0 | modbus_strerror(errno)); |
112 | 0 | modbus_free(ctx); |
113 | 0 | return -1; |
114 | 0 | } |
115 | | |
116 | | /* Initialize input values that's can be only done server side. */ |
117 | 1 | modbus_set_bits_from_bytes(mb_mapping->tab_input_bits, 0, UT_INPUT_BITS_NB, |
118 | 1 | UT_INPUT_BITS_TAB); |
119 | | |
120 | | /* Initialize values of INPUT REGISTERS */ |
121 | 2 | for (i=0; i < UT_INPUT_REGISTERS_NB; i++) { |
122 | 1 | mb_mapping->tab_input_registers[i] = UT_INPUT_REGISTERS_TAB[i]; |
123 | 1 | } |
124 | | |
125 | 1 | s = modbus_tcp_listen(ctx, 1); |
126 | 1 | modbus_tcp_accept(ctx, &s); |
127 | | |
128 | 1 | rc = modbus_receive(ctx, query); |
129 | | |
130 | 1 | if (s != -1) { |
131 | 1 | close(s); |
132 | 1 | } |
133 | | |
134 | 1 | modbus_mapping_free(mb_mapping); |
135 | 1 | free(query); |
136 | | /* For RTU */ |
137 | 1 | modbus_close(ctx); |
138 | 1 | modbus_free(ctx); |
139 | | |
140 | 1 | return rc; |
141 | 1 | } |