etc~ scripts and random things |
| git clone https://github.com/djnnvx/etc.git |
| log | files | refs | archive |
fuzz_pdu.c (2165B)
1 /* 2 * RPC framing layer. Sits above the per-procedure zdr decoders, below the 3 * raw socket read. libnfs_zdr_replymsg parses the rpc_msg envelope (xid, 4 * direction, accepted-vs-rejected reply, auth verifier flavour, status). 5 * 6 * Reachable on every reply from a malicious server, before any 7 * NFS-procedure-specific code runs. Bugs here break confinement universally. 8 * libnfs_zdr_callmsg sits on the server-side parse path; rarer but exists 9 * (servers/rpcbind, etc.). 10 * 11 * The harness lets the first byte pick the direction (CALL vs REPLY) so a 12 * single corpus hits both framings. 13 */ 14 #include "harness.h" 15 /* libnfs.h has to come first - it defines the EXTERN export macro that 16 * libnfs-raw.h depends on but does not itself provide. */ 17 #include "nfsc/libnfs.h" 18 #include "nfsc/libnfs-raw.h" 19 20 static int fuzz_one(const uint8_t *data, size_t size) 21 { 22 if (size < 1) 23 return 0; 24 int as_call = (data[0] & 1); 25 const uint8_t *payload = data + 1; 26 size_t payload_size = size - 1; 27 28 ZDR zdr; 29 struct rpc_msg msg; 30 nfs_zdrmem_decode(&zdr, payload, payload_size); 31 memset(&msg, 0, sizeof(msg)); 32 33 /* libnfs_accepted_reply (zdr.c:534) dispatches on status=SUCCESS by 34 * calling msg->body.rbody.reply.areply.reply_data.results.proc which is 35 * normally set by rpc_allocate_pdu when sending the request. In a stateless 36 * fuzzer we have no pending PDU; plug in the no-op decoder so the SUCCESS 37 * branch parses without dereferencing a NULL fn ptr. */ 38 msg.body.rbody.reply.areply.reply_data.results.proc = 39 (zdrproc_t)libnfs_zdr_void; 40 msg.body.rbody.reply.areply.reply_data.results.where = NULL; 41 42 struct rpc_context *rpc = rpc_init_context(); 43 if (!rpc) { 44 zdr_destroy(&zdr); 45 return 0; 46 } 47 48 if (as_call) { 49 if (libnfs_zdr_callmsg(rpc, &zdr, &msg)) { 50 /* nothing to free - the call body's auth fields aren't owned. */ 51 } 52 } else { 53 if (libnfs_zdr_replymsg(rpc, &zdr, &msg)) { 54 /* same: reply envelope doesn't own its sub-buffers in this layer. */ 55 } 56 } 57 58 zdr_destroy(&zdr); 59 rpc_destroy_context(rpc); 60 return 0; 61 }