1
0
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:
bors[bot] 2023-01-16 02:34:21 +00:00 committed by GitHub
commit 6fb340d654
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 106 additions and 26 deletions

View File

@ -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

View File

@ -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);

View File

@ -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

View File

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

View File

@ -1,6 +1,5 @@
include ../Makefile.fuzzing_common
USEMODULE += gnrc_ipv6
USEMODULE += gcoap
include $(RIOTBASE)/Makefile.include

View File

@ -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

View File

@ -0,0 +1,5 @@
include ../Makefile.fuzzing_common
USEMODULE += uri_parser
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1 @@
coap:///R@[2008::1]:5own//R@[2008::1]:5own/?v=1

View File

@ -0,0 +1 @@
coap://user@[2001:db8::1]:12345

View File

@ -0,0 +1 @@
ftp://riot-os.org:99/bar/foo

View File

@ -0,0 +1 @@
http://riot-os.org:99/bar/foo

View File

@ -0,0 +1 @@
coap://user@[2001:db8::1%eth0]:12345

30
fuzzing/uri_parser/main.c Normal file
View 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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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