etc.git


etc

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

README.md (3685B)

      1 # libnfs fuzzing
      2 
      3 Fuzzing harnesses for **libnfs** (Ronnie Sahlberg's userspace NFSv3 / NFSv4 /
      4 MOUNT / NLM / NSM / PORTMAP / RQUOTA client). Same machine setup as the
      5 libksba/libusb harnesses: AFL++ (CLASSIC + laf-intel), a CmpLog sibling per
      6 harness, ASan + UBSan at `-O0 -g` with `signed-integer-overflow` and `shift`
      7 dropped (XDR's `(v << 8) | next` idiom is pure noise under those checks).
      8 
      9 Why libnfs:
     10 - Same profile as libksba. Hand-rolled binary parser, ~87% of commits by one
     11   person, ubiquitous (VLC `nfs://`, Kodi, gvfs, QEMU block layer, mpd, fio),
     12   **not on OSS-Fuzz**, no fuzz harness in-tree.
     13 - Attacker model: malicious NFS server. Victim's libnfs client (typically
     14   invoked via `vlc nfs://attacker/x.mp4` style URLs) sends a request; the
     15   attacker controls every reply byte.
     16 
     17 ## Harnesses
     18 
     19 | harness     | drives                                      | reach                                  |
     20 |-------------|---------------------------------------------|----------------------------------------|
     21 | `fuzz_nfs3` | per-procedure `zdr_*_3res` decoders (21 of) | NFSv3 reply parsing (most common use)  |
     22 | `fuzz_nfs4` | `zdr_COMPOUND4res`                          | NFSv4 COMPOUND reply (biggest parser)  |
     23 | `fuzz_mount`| `zdr_mountres3`, `zdr_exports`, others      | MOUNT v3 - the auth-less first surface |
     24 | `fuzz_pdu`  | `libnfs_zdr_callmsg` / `libnfs_zdr_replymsg`| RPC framing layer above the decoders   |
     25 
     26 The first byte of each input picks the sub-decoder where applicable, so each
     27 corpus is shared across many procedures.
     28 
     29 ## Usage
     30 
     31 ```
     32 bash setup.sh            # deps + AFL++ + instrumented libnfs + harnesses + corpus
     33 bash start-fuzzers.sh    # 8 instances in tmux (master + CmpLog secondary per harness)
     34 bash start-fuzzers.sh --status
     35 bash cleanup.sh          # kill + remove artifacts (flags: --keep-corpus --keep-source ...)
     36 ```
     37 
     38 `setup.sh` flags: `--skip-deps` (deps already installed), `--skip-afl` (use a
     39 system afl-clang-fast instead of building AFL++ from source).
     40 
     41 Each harness builds three ways: `H` (AFL persistent), `H.cmplog` (CmpLog), and
     42 `H.repro` (plain clang + ASan, reads files from argv) for crash triage:
     43 
     44 ```
     45 ./fuzz_nfs3.repro output/master_nfs3/crashes/id:000000*
     46 ```
     47 
     48 ## Target version
     49 
     50 `setup.sh` defaults to libnfs git tip (6.0.x). To pin to a release:
     51 
     52 ```
     53 LIBNFS_TAG=libnfs-6.0.1 bash setup.sh
     54 ```
     55 
     56 ## Soft spots flagged before fuzzing (corpus is biased toward these)
     57 
     58 The libnfs parsing stack is XDR-shaped: tagged unions everywhere
     59 (accepted-vs-rejected reply, NFS3res ok-vs-fail, NFS4 resop4 by opcode).
     60 Classes of bug worth pre-seeding:
     61 
     62 - **Negative/huge length fields** through `zdr_bytes`, `zdr_array`,
     63   `zdr_string`. XDR length fields are u32; some callers cast to int and
     64   loop. Trigger: `0xffffffff` in length slot.
     65 - **Tag mismatch** in tagged unions: claim status=NFS3_OK then truncate the
     66   expected `fattr3` payload, or claim a v4 opcode that doesn't match the
     67   result body that follows.
     68 - **Linked-list cycles** in MOUNT `exports` / `groups` (each entry has a
     69   "next" pointer; nothing in the decoder caps traversal depth).
     70 
     71 ## Notes
     72 
     73 - libnfs's ZDR is a re-implementation of Sun XDR; it predates and replaces
     74   glibc's `tirpc`. Bugs found here may or may not exist upstream in tirpc -
     75   worth checking once a real crash lands.
     76 - `--without-libkrb5` is set at configure time to avoid the GSSAPI optional
     77   dep. Krb5-protected NFS isn't reachable for the kind of attacker we care
     78   about (server-controlled) since the krb5 wrap is verified before the inner
     79   payload is fed to ZDR.
     80 - `--disable-utils --disable-examples`: skip the bundled tools - they bring
     81   in unrelated link deps and we only need `libnfs.la`.