Coverage Report

Created: 2023-06-07 06:32

/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
}