etc.git


etc

~ scripts and random things
git clone https://github.com/djnnvx/etc.git
log | files | refs | archive

fuzz_nfs3.c (2055B)

      1 /*
      2  * NFSv3 reply parsing. Attacker model: malicious NFS server. Victim's libnfs
      3  * client (e.g. VLC's nfs:// handler, kodi, gvfs) sends a request; we replay
      4  * the response payload directly through the per-procedure ZDR decoder.
      5  *
      6  * Cycle through the major NFS3 result types so a single corpus exercises
      7  * GETATTR/READ/READDIR/LOOKUP/FSINFO/...; the first byte of the fuzz input
      8  * selects which decoder runs (mod the number of decoders).
      9  */
     10 #include "harness.h"
     11 #include "libnfs-raw-nfs.h"
     12 
     13 typedef bool_t (*nfs3_dec)(ZDR *, void *);
     14 
     15 #define DEC(name)  { #name, (nfs3_dec)zdr_##name, sizeof(name) }
     16 
     17 static const struct {
     18     const char *name;
     19     nfs3_dec fn;
     20     size_t result_size;
     21 } decoders[] = {
     22     DEC(GETATTR3res),
     23     DEC(SETATTR3res),
     24     DEC(LOOKUP3res),
     25     DEC(ACCESS3res),
     26     DEC(READLINK3res),
     27     DEC(READ3res),
     28     DEC(WRITE3res),
     29     DEC(CREATE3res),
     30     DEC(MKDIR3res),
     31     DEC(SYMLINK3res),
     32     DEC(MKNOD3res),
     33     DEC(REMOVE3res),
     34     DEC(RMDIR3res),
     35     DEC(RENAME3res),
     36     DEC(LINK3res),
     37     DEC(READDIR3res),
     38     DEC(READDIRPLUS3res),
     39     DEC(FSSTAT3res),
     40     DEC(FSINFO3res),
     41     DEC(PATHCONF3res),
     42     DEC(COMMIT3res),
     43 };
     44 #define N_DEC (sizeof(decoders) / sizeof(decoders[0]))
     45 
     46 static int fuzz_one(const uint8_t *data, size_t size)
     47 {
     48     if (size < 1)
     49         return 0;
     50 
     51     unsigned idx = data[0] % N_DEC;
     52     const uint8_t *payload = data + 1;
     53     size_t payload_size = size - 1;
     54 
     55     ZDR zdr;
     56     nfs_zdrmem_decode(&zdr, payload, payload_size);
     57 
     58     /* Calloc'd target struct so any uninitialised pointer fields are NULL;
     59      * the decoder will overwrite the parts it parses. Leaks ignored. */
     60     void *res = calloc(1, decoders[idx].result_size);
     61     if (!res) {
     62         zdr_destroy(&zdr);
     63         return 0;
     64     }
     65 
     66     if (decoders[idx].fn(&zdr, res)) {
     67         /* Decode succeeded - the post-decode free walks the same struct
     68          * shape and exercises any boundary cases in zdr_free. */
     69         zdr_free((zdrproc_t)decoders[idx].fn, (caddr_t)res);
     70     }
     71     free(res);
     72     zdr_destroy(&zdr);
     73     return 0;
     74 }