[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#409272: nfsmount: incompatible with nfsv4



Short version:

  1. nfsmount(8klibc) is still explicitly broken for NFSv4.
  2. mount.nfs(8nfs-utils) works in the ramdisk.
  3. A single mount(2) call also works!


Boring detailed version follows.

John Goerzen wrote:
> nfsmount is incapable of mounting NFSv4 filesystems.  It seems to have
> support for v3 and maybe v2, but not v4.

This is still the case in Debian 11, klibc-utils=2.0.8-6.1.
A workaround is to copy nfs-utils 1.3's mount.nfs into the initrd:

    /usr/share/initramfs-tools/hooks/zz-nfs4:

        #!/bin/sh
        [ prereqs = "$1" ] && exit
        . /usr/share/initramfs-tools/hook-functions
        copy_exec /sbin/mount.nfs /bin/nfsmount

Here are some specific errors I saw, with an NFSv4-only server on 10.0.2.100 port 2049/tcp

    # Normal nfs-common=1:1.3.4-6 works fine
    root@main:~# mount.nfs 10.0.2.100:/srv/netboot/images /mnt
    root@main:~# umount /mnt

    root@main:~# /usr/lib/klibc/bin/nfsmount -o nfsvers=4.2,sec=sys 10.0.2.100:/srv/netboot/images /mnt
    4.2: invalid value for nfsvers
    https://sources.debian.org/src/klibc/2.0.8-6.1/usr/kinit/nfsmount/main.c/#L145

    root@main:~# /usr/lib/klibc/bin/nfsmount -o nfsvers=4,sec=sys 10.0.2.100:/srv/netboot/images /mnt
    /usr/lib/klibc/bin/nfsmount: bad option 'sec'

    # This hangs because NFSv3 ports (inc. portmap) are not allowed AT ALL by 10.0.2.100.
    # klibc-utils is hard-coded to *EXPLICITLY* ask for a NFSv3 mount.
    root@main:~# /usr/lib/klibc/bin/nfsmount 10.0.2.100:/srv/netboot/images /mnt
    connect: Connection timed out



It is quite annoying that we need *anything* special in userland, because
a nfsvers=4.2,sec=sys mount requires only 2049/tcp (no other ports/services), and
the actual filesystem is in-kernel, so
really all that should be needed is enough of a C program to issue a single mount(2)!

As an experiment, I tried do compile in EXACTLY that, and it works for me:

    root@main:~# apt install build-essential strace
    root@main:~# strace -s99999 -emount mount.nfs 10.0.2.100:/srv/netboot /mnt
    mount("10.0.2.100:/srv/netboot", "/mnt", "nfs", 0, "vers=4.2,addr=10.0.2.100,clientaddr=10.0.2.15") = 0
    root@main:~# umount /mnt

    root@main:~# journalctl -kfn0 &
    root@main:~# cc -x c - <<< 'int main() {exit(mount("10.0.2.100:/srv/netboot", "/mnt", "nfs", 0, "vers=4.2,addr=10.0.2.100,clientaddr=10.0.2.15"));}' && ./a.out; echo $?
    <stdin>: In function ‘main’:
    <stdin>:1:13: warning: implicit declaration of function ‘exit’ [-Wimplicit-function-declaration]
    <stdin>:1:13: warning: incompatible implicit declaration of built-in function ‘exit’
    <stdin>:1: note: include ‘<stdlib.h>’ or provide a declaration of ‘exit’
    <stdin>:1:18: warning: implicit declaration of function ‘mount’ [-Wimplicit-function-declaration]
    0
    root@main:~# umount /mnt

Can I do the same thing with klibc instead of glibc?
Well, the compiler wrapper is a bit confused...

    root@main:~# apt install libklibc-dev
    root@main:~# klcc -x c - <<< 'int main() {exit(mount("10.0.2.100:/srv/netboot", "/mnt", "nfs", 0, "vers=4.2,addr=10.0.2.100,clientaddr=10.0.2.15"));}' && ./a.out; echo $?
    <ot", "/mnt", "nfs", 0, "vers=4.2,addr=10.0.2.100,clientaddr=10.0.2.15"));}' && ./a.out; echo $?
    Died at /usr/bin/klcc line 294.
    25

But if I write the C program to a file, it works perfectly:

    root@main:~# >nfsmount.c printf '#include <stdlib.h>\n#include <sys/mount.h>\nint main() {exit(mount("10.0.2.100:/srv/netboot", "/mnt", "nfs", 0, "vers=4.2,addr=10.0.2.100,clientaddr=10.0.2.15"));}'
    root@main:~# klcc -o nfsmount nfsmount.c
    root@main:~# ./nfsmount; echo $?
    ./nfsmount; echo $?
    Nov 17 10:11:31 main.lan kernel: process '/root/nfsmount' started with executable stack
    0

So for current-generation NFS, without kerberos, all we *REALLY* need
is something to getopts from

    nfsmount -t nfs -o nfsvers=4.2,sec=sys example.com:/srv /srv

into

    mount("example.com:/srv", "/srv", 0, "nfsvers=4.2,sec=sys");

This is pretty narrow in scope and is probably achievable.
It allows you to boot off NFSv4, without putting glibc into the initrd.


Reply to: