mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-24 22:13:52 +01:00
19057: fuzzing: Add uri_parser setup r=benpicco a=Teufelchen1 Hello! ### Contribution description This PR is a replacement for PR #18802 In this contribution: * The variable `AFL_FLAGS` is renamed to `FLAGS_FOR_AFL` because AFL is always complaining that `AFL_FLAGS` is not a valid env var for it. While this is not a bug nor an issue, I found it to be annoying. * A generic input reader is added to simplify building a test harness * The usage of this reader is demonstrated by adding a harness for fuzzing the uri_parser (needs squashing after review) ### Testing procedure Go to `fuzzing/uri_parser` and run `make all-asan` and `make fuzz` to get some action going. Also mildly interesting: `./dist/tools/compile_test/compile_like_murdock.py -b native -a fuzzing/uri_parser` ### Issues/PRs references The original PR #18802 is replaced because the generic input reader is present in both PRs but this PoC harness is much simpler. 19151: examples/gcoap: Fix shell parameter validation r=benpicco a=maribu ### Contribution description Executing the shell command with an URI-Path that doesn't start with a slash results in an assertion error while composing the client side message. This is suboptimal user experience, so add an explicit check for a valid URI-Path and a dedicated error message. ### Testing procedure #### In `master` ``` $ make BOARD=microbit-v2 -C examples/gcoap flash term [...] 2023-01-15 22:23:32,512 # coap get [::1] /.well-known/core 2023-01-15 22:23:32,516 # gcoap_cli: sending msg ID 52272, 23 bytes 2023-01-15 22:23:32,520 # gcoap: response Success, code 2.05, 46 bytes 2023-01-15 22:23:32,524 # </cli/stats>;ct=0;rt="count";obs,</riot/board> > coap get [::1] foo 2023-01-15 22:23:34,763 # coap get [::1] foo 2023-01-15 22:23:34,763 # 2329 2023-01-15 22:23:34,765 # *** RIOT kernel panic: 2023-01-15 22:23:34,767 # FAILED ASSERTION. 2023-01-15 22:23:34,767 # 2023-01-15 22:23:34,775 # pid | name | state Q | pri | stack ( used) ( free) | base addr | current 2023-01-15 22:23:34,784 # - | isr_stack | - - | - | 512 ( 200) ( 312) | 0x20000000 | 0x200001c8 2023-01-15 22:23:34,793 # 1 | main | running Q | 7 | 1536 ( 1072) ( 464) | 0x200006c0 | 0x2000095c 2023-01-15 22:23:34,802 # 2 | 6lo | bl rx _ | 3 | 1024 ( 328) ( 696) | 0x200036c0 | 0x200039c4 2023-01-15 22:23:34,810 # 3 | ipv6 | bl rx _ | 4 | 1024 ( 460) ( 564) | 0x20001294 | 0x20001574 2023-01-15 22:23:34,819 # 4 | udp | bl rx _ | 5 | 512 ( 300) ( 212) | 0x20003e98 | 0x20003f9c 2023-01-15 22:23:34,828 # 5 | coap | bl anyfl _ | 6 | 1112 ( 704) ( 408) | 0x20000e38 | 0x200011c4 2023-01-15 22:23:34,837 # 6 | nrf802154 | bl anyfl _ | 2 | 896 ( 288) ( 608) | 0x20001a90 | 0x20001d54 2023-01-15 22:23:34,843 # | SUM | | | 6616 ( 3352) ( 3264) 2023-01-15 22:23:34,843 # 2023-01-15 22:23:34,844 # *** halted. 2023-01-15 22:23:34,844 # ``` #### This PR ``` $ make BOARD=microbit-v2 -C examples/gcoap flash term [...] make: Entering directory '/home/maribu/Repos/software/RIOT/examples/gcoap' /home/maribu/Repos/software/RIOT/dist/tools/pyterm/pyterm -p "/dev/ttyACM0" -b "115200" 2023-01-15 22:22:27,842 # Connect to serial port /dev/ttyACM0 Welcome to pyterm! Type '/exit' to exit. coap get [::1] /.well-known/core 2023-01-15 22:22:40,042 # coap get [::1] /.well-known/core 2023-01-15 22:22:40,046 # gcoap_cli: sending msg ID 25182, 23 bytes 2023-01-15 22:22:40,050 # gcoap: response Success, code 2.05, 46 bytes 2023-01-15 22:22:40,054 # </cli/stats>;ct=0;rt="count";obs,</riot/board> > coap get [::1] foo 2023-01-15 22:22:43,858 # coap get [::1] foo 2023-01-15 22:22:43,862 # ERROR: URI-Path must start with a "/" 2023-01-15 22:22:43,866 # usage: coap <get|post|put|ping|proxy|info> ``` ### Issues/PRs references None Co-authored-by: Teufelchen1 <bennet.blischke@haw-hamburg.de> Co-authored-by: Marian Buschsieweke <marian.buschsieweke@ovgu.de>
This commit is contained in:
commit
6fb340d654
@ -909,7 +909,7 @@ include $(RIOTMAKE)/tests/tests.inc.mk
|
||||
.PHONY: fuzz
|
||||
fuzz:
|
||||
env FLASHFILE="$(FLASHFILE)" PORT="$(PORT)" TERMFLAGS="$(TERMFLAGS)" \
|
||||
"$(RIOTBASE)"/dist/tools/fuzzing/afl.sh $(AFL_FLAGS)
|
||||
"$(RIOTBASE)"/dist/tools/fuzzing/afl.sh $(FLAGS_FOR_AFL)
|
||||
|
||||
# Default OBJDUMPFLAGS for platforms which do not specify it:
|
||||
OBJDUMPFLAGS ?= -S -D -h
|
||||
|
||||
@ -294,6 +294,11 @@ int gcoap_cli_cmd(int argc, char **argv)
|
||||
uri_len = strlen(argv[apos+1]);
|
||||
}
|
||||
|
||||
if (uri && ((uri_len <= 0) || (uri[0] != '/'))) {
|
||||
puts("ERROR: URI-Path must start with a \"/\"");
|
||||
return _print_usage(argv);
|
||||
}
|
||||
|
||||
if (_proxied) {
|
||||
sock_udp_ep_t tmp_remote;
|
||||
if (sock_udp_name2ep(&tmp_remote, argv[apos]) != 0) {
|
||||
@ -329,7 +334,7 @@ int gcoap_cli_cmd(int argc, char **argv)
|
||||
|
||||
gcoap_req_init(&pdu, &buf[0], CONFIG_GCOAP_PDU_BUF_SIZE, code_pos, NULL);
|
||||
}
|
||||
else{
|
||||
else {
|
||||
gcoap_req_init(&pdu, &buf[0], CONFIG_GCOAP_PDU_BUF_SIZE, code_pos, uri);
|
||||
}
|
||||
coap_hdr_set_type(pdu.hdr, msg_type);
|
||||
|
||||
@ -14,6 +14,7 @@ CFLAGS += -ggdb # Make ASAN output more useful error messages
|
||||
CFLAGS += -D_FORTIFY_SOURCE=2 # Compiler hardening
|
||||
|
||||
# Various utilitiy modules
|
||||
USEMODULE += gnrc_ipv6
|
||||
USEMODULE += fuzzing
|
||||
USEMODULE += ssp
|
||||
|
||||
|
||||
@ -72,13 +72,13 @@ Afterwards invoke afl using:
|
||||
|
||||
### Parallel Fuzzing
|
||||
|
||||
Parallel fuzzing is supported through `AFL_FLAGS`, e.g.:
|
||||
Parallel fuzzing is supported through `FLAGS_FOR_AFL`, e.g.:
|
||||
|
||||
# Start first AFL instance
|
||||
AFL_FLAGS="-M fuzzer01" make -C fuzzing/gnrc_tcp/ fuzz
|
||||
FLAGS_FOR_AFL="-M fuzzer01" make -C fuzzing/gnrc_tcp/ fuzz
|
||||
|
||||
# Start second AFL instance in a different terminal
|
||||
AFL_FLAGS="-S fuzzer02" make -C fuzzing/gnrc_tcp/ fuzz
|
||||
FLAGS_FOR_AFL="-S fuzzer02" make -C fuzzing/gnrc_tcp/ fuzz
|
||||
|
||||
[sanitizers github]: https://github.com/google/sanitizers
|
||||
[afl homepage]: http://lcamtuf.coredump.cx/afl/
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
include ../Makefile.fuzzing_common
|
||||
|
||||
USEMODULE += gnrc_ipv6
|
||||
USEMODULE += gcoap
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
|
||||
@ -8,7 +8,6 @@ CFLAGS += -DSERVER_ADDR=\"$(TCP_SERVER_ADDR)\"
|
||||
CFLAGS += -DSERVER_ADDR_PREFIX=$(TCP_SERVER_ADDR_PREFIX)
|
||||
CFLAGS += -DSERVER_PORT=$(TCP_SERVER_PORT)
|
||||
|
||||
USEMODULE += gnrc_ipv6
|
||||
USEMODULE += gnrc_tcp
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
|
||||
5
fuzzing/uri_parser/Makefile
Normal file
5
fuzzing/uri_parser/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
include ../Makefile.fuzzing_common
|
||||
|
||||
USEMODULE += uri_parser
|
||||
|
||||
include $(RIOTBASE)/Makefile.include
|
||||
1
fuzzing/uri_parser/input/input0.txt
Normal file
1
fuzzing/uri_parser/input/input0.txt
Normal file
@ -0,0 +1 @@
|
||||
coap:///R@[2008::1]:5own//R@[2008::1]:5own/?v=1
|
||||
1
fuzzing/uri_parser/input/input1.txt
Normal file
1
fuzzing/uri_parser/input/input1.txt
Normal file
@ -0,0 +1 @@
|
||||
coap://user@[2001:db8::1]:12345
|
||||
1
fuzzing/uri_parser/input/input2.txt
Normal file
1
fuzzing/uri_parser/input/input2.txt
Normal file
@ -0,0 +1 @@
|
||||
ftp://riot-os.org:99/bar/foo
|
||||
1
fuzzing/uri_parser/input/input3.txt
Normal file
1
fuzzing/uri_parser/input/input3.txt
Normal file
@ -0,0 +1 @@
|
||||
http://riot-os.org:99/bar/foo
|
||||
1
fuzzing/uri_parser/input/input4.txt
Normal file
1
fuzzing/uri_parser/input/input4.txt
Normal file
@ -0,0 +1 @@
|
||||
coap://user@[2001:db8::1%eth0]:12345
|
||||
30
fuzzing/uri_parser/main.c
Normal file
30
fuzzing/uri_parser/main.c
Normal file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2022 HAW Hamburg
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
#include <err.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "uri_parser.h"
|
||||
#include "fuzzing.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
size_t input_len;
|
||||
char *input_buf = (char *)fuzzing_read_bytes(STDIN_FILENO, &input_len);
|
||||
|
||||
if (input_buf == NULL) {
|
||||
errx(EXIT_FAILURE, "fuzzing_read_bytes failed");
|
||||
}
|
||||
|
||||
uri_parser_result_t uri_res;
|
||||
|
||||
uri_parser_process(&uri_res, input_buf, input_len);
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@ -128,7 +128,7 @@ export UNZIP_HERE # Use `cd $(SOME_FOLDER) && $(UNZIP_HERE) $(SOME_FI
|
||||
export LAZYSPONGE # Command saving stdin to a file only on content update.
|
||||
export LAZYSPONGE_FLAGS # Parameters supplied to LAZYSPONGE.
|
||||
|
||||
export AFL_FLAGS # Additional command-line flags passed to afl during fuzzing.
|
||||
export FLAGS_FOR_AFL # Additional command-line flags passed to afl during fuzzing.
|
||||
|
||||
# LOG_LEVEL # Logging level as integer (NONE: 0, ERROR: 1, WARNING: 2, INFO: 3, DEBUG: 4, default: 3)
|
||||
# KCONFIG_ADD_CONFIG # List of .config files to be merged used by Boards and CPUs. See kconfig.mk
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Sören Tempel <tempel@uni-bremen.de>
|
||||
* Copyright (C) 2022 Bennet Blischke <bennet.blischke@haw-hamburg.de>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -8,6 +9,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "assert.h"
|
||||
@ -21,13 +23,13 @@
|
||||
extern int fuzzing_netdev(gnrc_netif_t *);
|
||||
extern void fuzzing_netdev_wait(void);
|
||||
|
||||
/* used by gnrc_pktbuf_malloc to exit on free */
|
||||
gnrc_pktsnip_t *gnrc_pktbuf_fuzzptr = NULL;
|
||||
|
||||
/* buffer sizes for reading from an fd */
|
||||
#define FUZZING_BSIZE 1024
|
||||
#define FUZZING_BSTEP 128
|
||||
|
||||
/* used by gnrc_pktbuf_malloc to exit on free */
|
||||
gnrc_pktsnip_t *gnrc_pktbuf_fuzzptr = NULL;
|
||||
|
||||
int
|
||||
fuzzing_init(ipv6_addr_t *addr, unsigned pfx_len)
|
||||
{
|
||||
@ -50,40 +52,61 @@ fuzzing_init(ipv6_addr_t *addr, unsigned pfx_len)
|
||||
int
|
||||
fuzzing_read_packet(int fd, gnrc_pktsnip_t *pkt)
|
||||
{
|
||||
ssize_t r;
|
||||
size_t csiz, rsiz;
|
||||
size_t rsiz;
|
||||
|
||||
/* can only be called once currently */
|
||||
assert(gnrc_pktbuf_fuzzptr == NULL);
|
||||
|
||||
csiz = 0;
|
||||
rsiz = FUZZING_BSIZE;
|
||||
uint8_t *input = fuzzing_read_bytes(fd, &rsiz);
|
||||
if (input == NULL) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (gnrc_pktbuf_realloc_data(pkt, rsiz)) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
while ((r = read(fd, &((char *)pkt->data)[csiz], rsiz)) > 0) {
|
||||
memcpy(pkt->data, input, rsiz);
|
||||
|
||||
gnrc_pktbuf_fuzzptr = pkt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
fuzzing_read_bytes(int fd, size_t *size)
|
||||
{
|
||||
uint8_t *buffer = NULL;
|
||||
ssize_t r;
|
||||
size_t csiz, rsiz;
|
||||
|
||||
csiz = 0;
|
||||
rsiz = FUZZING_BSIZE;
|
||||
if ((buffer = realloc(buffer, rsiz)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((r = read(fd, &(buffer[csiz]), rsiz)) > 0) {
|
||||
assert((size_t)r <= rsiz);
|
||||
|
||||
csiz += r;
|
||||
rsiz -= r;
|
||||
|
||||
if (rsiz == 0) {
|
||||
if (gnrc_pktbuf_realloc_data(pkt, csiz + FUZZING_BSTEP)) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
rsiz += FUZZING_BSTEP;
|
||||
if ((buffer = realloc(buffer, csiz + FUZZING_BSTEP)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
rsiz += FUZZING_BSTEP;
|
||||
}
|
||||
}
|
||||
if (r == -1) {
|
||||
return -errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* shrink packet to actual size */
|
||||
if (gnrc_pktbuf_realloc_data(pkt, csiz)) {
|
||||
return -ENOMEM;
|
||||
/* shrink buffer to actual size */
|
||||
if ((buffer = realloc(buffer, csiz)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gnrc_pktbuf_fuzzptr = pkt;
|
||||
return 0;
|
||||
*size = csiz;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Sören Tempel <tempel@uni-bremen.de>
|
||||
* Copyright (C) 2022 Bennet Blischke <bennet.blischke@haw-hamburg.de>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -25,6 +26,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "net/ipv6/addr.h"
|
||||
#include "net/gnrc/pkt.h"
|
||||
|
||||
@ -49,6 +52,16 @@ int fuzzing_init(ipv6_addr_t *addr, unsigned pfx_len);
|
||||
*/
|
||||
int fuzzing_read_packet(int fd, gnrc_pktsnip_t *pkt);
|
||||
|
||||
/**
|
||||
* @brief Read data from the given file descriptor.
|
||||
*
|
||||
* @param fd File descriptor to read data from.
|
||||
* @param size Byte count of the data read.
|
||||
*
|
||||
* @return pointer to the data on success, NULL otherwise.
|
||||
*/
|
||||
uint8_t *fuzzing_read_bytes(int fd, size_t *size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user