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 }