1*35c0a8c4SKyle Evans /*- 2*35c0a8c4SKyle Evans * Copyright (c) 2024 Kyle Evans <kevans@FreeBSD.org> 3*35c0a8c4SKyle Evans * 4*35c0a8c4SKyle Evans * SPDX-License-Identifier: BSD-2-Clause 5*35c0a8c4SKyle Evans */ 6*35c0a8c4SKyle Evans 7*35c0a8c4SKyle Evans #include <sys/param.h> 8*35c0a8c4SKyle Evans #include <sys/socket.h> 9*35c0a8c4SKyle Evans 10*35c0a8c4SKyle Evans #include <assert.h> 11*35c0a8c4SKyle Evans #include <pthread.h> 12*35c0a8c4SKyle Evans #include <signal.h> 13*35c0a8c4SKyle Evans #include <stdbool.h> 14*35c0a8c4SKyle Evans #include <stdint.h> 15*35c0a8c4SKyle Evans #include <stdio.h> 16*35c0a8c4SKyle Evans #include <stdlib.h> 17*35c0a8c4SKyle Evans #include <unistd.h> 18*35c0a8c4SKyle Evans 19*35c0a8c4SKyle Evans #include <libder.h> 20*35c0a8c4SKyle Evans 21*35c0a8c4SKyle Evans #include "fuzzers.h" 22*35c0a8c4SKyle Evans 23*35c0a8c4SKyle Evans struct fuzz_frame { 24*35c0a8c4SKyle Evans uint8_t frame_threads; 25*35c0a8c4SKyle Evans }; 26*35c0a8c4SKyle Evans 27*35c0a8c4SKyle Evans struct thread_input { 28*35c0a8c4SKyle Evans const uint8_t *data; 29*35c0a8c4SKyle Evans size_t datasz; 30*35c0a8c4SKyle Evans }; 31*35c0a8c4SKyle Evans 32*35c0a8c4SKyle Evans static void * 33*35c0a8c4SKyle Evans thread_main(void *cookie) 34*35c0a8c4SKyle Evans { 35*35c0a8c4SKyle Evans const struct thread_input *input = cookie; 36*35c0a8c4SKyle Evans struct libder_ctx *ctx; 37*35c0a8c4SKyle Evans struct libder_object *obj; 38*35c0a8c4SKyle Evans const uint8_t *data = input->data; 39*35c0a8c4SKyle Evans size_t readsz, sz = input->datasz; 40*35c0a8c4SKyle Evans 41*35c0a8c4SKyle Evans ctx = libder_open(); 42*35c0a8c4SKyle Evans readsz = sz; 43*35c0a8c4SKyle Evans obj = libder_read(ctx, data, &readsz); 44*35c0a8c4SKyle Evans if (obj == NULL || readsz != sz) 45*35c0a8c4SKyle Evans goto out; 46*35c0a8c4SKyle Evans 47*35c0a8c4SKyle Evans if (obj != NULL) { 48*35c0a8c4SKyle Evans uint8_t *buf = NULL; 49*35c0a8c4SKyle Evans size_t bufsz = 0; 50*35c0a8c4SKyle Evans 51*35c0a8c4SKyle Evans /* 52*35c0a8c4SKyle Evans * If we successfully read it, then it shouldn't 53*35c0a8c4SKyle Evans * overflow. We're letting libder allocate the buffer, 54*35c0a8c4SKyle Evans * so we shouldn't be able to hit the 'too small' bit. 55*35c0a8c4SKyle Evans * 56*35c0a8c4SKyle Evans * I can't imagine what other errors might happen, so 57*35c0a8c4SKyle Evans * we'll just assert on it. 58*35c0a8c4SKyle Evans */ 59*35c0a8c4SKyle Evans buf = libder_write(ctx, obj, buf, &bufsz); 60*35c0a8c4SKyle Evans if (buf == NULL) 61*35c0a8c4SKyle Evans goto out; 62*35c0a8c4SKyle Evans 63*35c0a8c4SKyle Evans assert(bufsz != 0); 64*35c0a8c4SKyle Evans 65*35c0a8c4SKyle Evans free(buf); 66*35c0a8c4SKyle Evans } 67*35c0a8c4SKyle Evans 68*35c0a8c4SKyle Evans out: 69*35c0a8c4SKyle Evans libder_obj_free(obj); 70*35c0a8c4SKyle Evans libder_close(ctx); 71*35c0a8c4SKyle Evans return (NULL); 72*35c0a8c4SKyle Evans } 73*35c0a8c4SKyle Evans 74*35c0a8c4SKyle Evans int 75*35c0a8c4SKyle Evans LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) 76*35c0a8c4SKyle Evans { 77*35c0a8c4SKyle Evans const struct fuzz_frame *frame; 78*35c0a8c4SKyle Evans pthread_t *threads; 79*35c0a8c4SKyle Evans struct thread_input inp; 80*35c0a8c4SKyle Evans size_t nthreads; 81*35c0a8c4SKyle Evans 82*35c0a8c4SKyle Evans if (sz <= sizeof(*frame)) 83*35c0a8c4SKyle Evans return (-1); 84*35c0a8c4SKyle Evans 85*35c0a8c4SKyle Evans frame = (const void *)data; 86*35c0a8c4SKyle Evans data += sizeof(*frame); 87*35c0a8c4SKyle Evans sz -= sizeof(*frame); 88*35c0a8c4SKyle Evans 89*35c0a8c4SKyle Evans if (frame->frame_threads < 2) 90*35c0a8c4SKyle Evans return (-1); 91*35c0a8c4SKyle Evans 92*35c0a8c4SKyle Evans threads = malloc(sizeof(*threads) * frame->frame_threads); 93*35c0a8c4SKyle Evans if (threads == NULL) 94*35c0a8c4SKyle Evans return (-1); 95*35c0a8c4SKyle Evans 96*35c0a8c4SKyle Evans inp.data = data; 97*35c0a8c4SKyle Evans inp.datasz = sz; 98*35c0a8c4SKyle Evans 99*35c0a8c4SKyle Evans for (nthreads = 0; nthreads < frame->frame_threads; nthreads++) { 100*35c0a8c4SKyle Evans if (pthread_create(&threads[nthreads], NULL, thread_main, 101*35c0a8c4SKyle Evans &inp) != 0) 102*35c0a8c4SKyle Evans break; 103*35c0a8c4SKyle Evans } 104*35c0a8c4SKyle Evans 105*35c0a8c4SKyle Evans for (uint8_t i = 0; i < nthreads; i++) 106*35c0a8c4SKyle Evans pthread_join(threads[i], NULL); 107*35c0a8c4SKyle Evans 108*35c0a8c4SKyle Evans free(threads); 109*35c0a8c4SKyle Evans 110*35c0a8c4SKyle Evans return (0); 111*35c0a8c4SKyle Evans } 112