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: