Package: libpam-mount Version: 2.14-1.1 Severity: minor 1. libpam_mount considers something "already mounted" if it can find a mount in libmount's iterator where both the source (device) and target (mountpoint) match.
This is the code responsible: libpam-mount/src/mount.c:149:pmt_already_mounted() libpam-mount/src/mount.c:125:pmt_utabent_matches() THE PROBLEM ==================== 2. If pam_mount.conf.xml has <volume fstype="nfs" server="nfs" path="~" mountpoint="~" options="..."> then "already mounted?" fails because it compares nfs:/home/prisoners/p to /home/prisoners/p. I think. command: 'mount' '-onfsvers=3,intr,bg,nodev,noexec,nosuid' '-tnfs' 'nfs:/home/prisoners/p' '/home/prisoners/p' (mount.c:72): Messages from underlying mount program: (mount.c:76): mount.nfs: access denied by server while mounting (null) The odd error from mount.nfs is because nfs:/home is root_squash and user nobody can't read it: # mkdir x y # mount -tnfs nfs:/home x # mount -tnfs nfs:/home x mount.nfs: /root/x is busy or already mounted # mount -tnfs nfs:/home/prisoners/p y # mount -tnfs nfs:/home/prisoners/p y mount.nfs: access denied by server while mounting (null) # ls -ld x y drwxr-x--x 8 root root 1024 Nov 12 2014 x drwx------ 13 p p 4096 Sep 22 12:35 y # ls -ld x/prisoners drwxr-x--x 24 root root 1024 Sep 21 17:09 x/prisoners WORKAROUNDS DON'T WORK ============================== 3. If pam_mount.conf.xml has <volume fstype="nfs" path="nfs:~" mountpoint="~" options="..."> then mounting fails because the nfs:~ is not expanded. command: 'mount' '-onfsvers=3,intr,bg,nodev,noexec,nosuid' '-tnfs' 'nfs:~' '/home/prisoners/p' (mount.c:72): Messages from underlying mount program: (mount.c:76): mount.nfs: access denied by server while mounting nfs:~ 4. If pam_mount.conf.xml has <volume fstype="nfs" path="nfs:/home/prisoners/p" mountpoint="~" options="..."> then mounting & detection both work: (mount.c:628): nfs:/home/prisoners/p already seems to be mounted at /home/prisoners/p, skipping ...but now I have to list every user's login individually, which is not feasible. 5. If pam_mount.conf.xml has <volume fstype="nfs" path="nfs:/home/prisoners/%(USER)" mountpoint="~" options="..."> the source is wrong path for staff users. Constructing $HOME from $USER also fails for setups like ~ajking2 ==> /home/students/a/j/ajking2/ which used to be common in large universities. I could probably get away with this, but it feels awful: <volume group="prisoners" fstype="nfs" path="nfs:/home/prisoners/%(USER)" mountpoint="~" options="..."> <volume group="staff" fstype="nfs" path="nfs:/home/staff/%(USER)" mountpoint="~" options="..."> IMPACT ==================== This is not an immediate problem for me, because the duplicate mount fails & the login succeeds. But! If the *first* mount fails (e.g. when NFS is down), the user get a working login with $HOME on the local root filesystem. If I fix that by making PAM abort when the mount fails, the problem in pmt_utabent_matches() will break the user's second concurrent login (e.g. GUI desktop + ssh). I'm too dumb to see exactly how to patch this, but I hope it's a one-line change. :-) POSTSCRIPT ==================== I pulled out pmt_already_mounted() into the following stand-alone script, to confirm that libmount could see the mountpoint: bash4$ cat mount-test.c /* #!/usr/bin/tcc -run -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/uuid -lmount */ /* bash4$ pkg-config --cflags --libs mount */ /* -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/uuid -lmount */ #include <libmount.h> main() { struct libmnt_context *ctx; struct libmnt_table *table; struct libmnt_iter *iter; struct libmnt_fs *fs; const char *source, *target; ctx = mnt_new_context(); if (ctx == NULL) return -1; if (mnt_context_get_mtab(ctx, &table) != 0) goto out; iter = mnt_new_iter(MNT_ITER_BACKWARD); if (iter == NULL) goto out; while (mnt_table_next_fs(table, iter, &fs) == 0) { source = mnt_fs_get_source(fs); target = mnt_fs_get_target(fs); printf("source<%s> target<%s>\n", source ?: "NULL", target ?: "NULL"); } out: mnt_free_context(ctx); return 0; } bash4$ cc mount-test.c $(pkg-config --cflags --libs mount) bash4$ cat a.out | ssh x 'cat >a.out && chmod +x a.out && ./a.out' Warning: Permanently added 'het' (ECDSA) to the list of known hosts. source<tmpfs> target</run/user/10242> source<nfs:/home/prisoners/p> target</home/prisoners/p> source<tmpfs> target</run/user/0> source<nfs:/srv/share> target</srv/share> source<tmpfs> target</lib/live/mount> source<tmpfs> target</tmp> source<tmpfs> target</var/tmp> source<pstore> target</sys/fs/pstore> source<cgroup> target</sys/fs/cgroup/systemd> source<tmpfs> target</sys/fs/cgroup> source<tmpfs> target</run/lock> source<devpts> target</dev/pts> source<tmpfs> target</dev/shm> source<securityfs> target</sys/kernel/security> source<devtmpfs> target</dev> source<aufs> target</> source<tmpfs> target</lib/live/mount/overlay> source</dev/loop0> target</lib/live/mount/rootfs/filesystem.squashfs> source<10.128.0.1:/srv/netboot/images> target</lib/live/mount/medium> source<tmpfs> target</run> source<proc> target</proc> source<sysfs> target</sys> The full pam_mount.conf.xml I used for these tests was: <?xml version="1.0" encoding="utf-8" ?> <!DOCTYPE pam_mount SYSTEM "pam_mount.conf.xml.dtd"> <pam_mount> <debug enable="1" /> <volume fstype="nfs" server="nfs" path="~" mountpoint="~" options="nfsvers=3,intr,bg,nodev,noexec,nosuid"> <uid>1000-29999</uid> </volume> <mkmountpoint enable="1" remove="false" /> </pam_mount>