NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/58901: nfs server should allow specifying fsid in exports(5)
>Number: 58901
>Category: kern
>Synopsis: nfs server should allow specifying fsid in exports(5)
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Dec 13 21:55:00 +0000 2024
>Originator: Taylor R Campbell
>Release: current, 10, 9, ...
>Organization:
The Nfsid Foundinode
>Environment:
>Description:
When exporting a local file system, the NFS server uses the fsid of the local file system. This fsid is often assembled by boot-dependent quantities like the ordering of bus scanning or file system mounting:
1523 mp->mnt_stat.f_fsidx.__fsid_val[0] = (long)dev;
1524 mp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_FFS);
1525 mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
https://nxr.netbsd.org/xref/src/sys/ufs/ffs/ffs_vfsops.c?r=1.382#1523
232 mutex_enter(&mntid_lock);
233 if (xxxfs_mntid == 0)
234 ++xxxfs_mntid;
235 mtype = makefstype(mp->mnt_op->vfs_name);
236 tfsid.__fsid_val[0] = makedev(mtype & 0xff, xxxfs_mntid);
237 tfsid.__fsid_val[1] = mtype;
238 /* Always increment to not return the same fsid to parallel mounts. */
239 xxxfs_mntid++;
240
241 /*
242 * Directly walk mountlist to prevent deadlock through
243 * mountlist_iterator_next() -> vfs_busy().
244 */
245 mutex_enter(&mountlist_lock);
246 for (me = TAILQ_FIRST(&mountlist); me != TAILQ_END(&mountlist); ) {
247 if (me->me_type == ME_MOUNT &&
248 me->me_mount->mnt_stat.f_fsidx.__fsid_val[0] ==
249 tfsid.__fsid_val[0] &&
250 me->me_mount->mnt_stat.f_fsidx.__fsid_val[1] ==
251 tfsid.__fsid_val[1]) {
252 tfsid.__fsid_val[0]++;
253 xxxfs_mntid++;
254 me = TAILQ_FIRST(&mountlist);
255 } else {
256 me = TAILQ_NEXT(me, me_list);
257 }
258 }
259 mutex_exit(&mountlist_lock);
260
261 mp->mnt_stat.f_fsidx.__fsid_val[0] = tfsid.__fsid_val[0];
262 mp->mnt_stat.f_fsidx.__fsid_val[1] = tfsid.__fsid_val[1];
263 mp->mnt_stat.f_fsid = mp->mnt_stat.f_fsidx.__fsid_val[0];
https://nxr.netbsd.org/xref/src/sys/kern/vfs_mount.c#221
If anything changes this -- you move disks around or change partitions so the dkN numbers change, you edit /etc/fstab to mount file systems in a different order, or whatever -- all NFS file handles for what should be the `same' local file system will change.
Worse, if /export/A is mounted from /dev/dk3 and /export/B from /dev/dk4 at first, and then they are exchanged so /export/A is mounted from /dev/dk4 and /export/B is mounted from /dev/dk3, file handles could collide, causing the wrong data to be read or written by clients with cached file handles.
zfs avoids this by randomly generating its fsids and storing them in the file system, so they're independent of the device enumeration at boot and the number of times other file systems have been mounted. But file systems that haven't reserved space in their metadata for this can't take advantage of the same approach.
>How-To-Repeat:
1. Mount a file system on /dev/dkN via named wedge and export it.
2. Mount a file system on /dev/dkM via named wedge and export it (M =/= N).
3. Start some clients caching some file handles.
4. Reboot and rejigger the hardware or partitioning so dkN and dkM are swapped but the same file systems are mounted at the same paths as before.
5. ???
6. Profit!
>Fix:
1. Create new syntax (or search other NFS server software for syntax) in /etc/exports for explicitly specifying the fsid of each exported file system.
2. Decide how to detect and address the entirely new problem of accidentally exporting an _actually different_ file system at the same path with the same fsid recorded in /etc/exports.
Home |
Main Index |
Thread Index |
Old Index