On Wed, Mar 05, 2025 at 06:45:13PM -0600, Tim Chase wrote: > An issue came up on Reddit today > > https://www.reddit.com/r/openbsd/comments/1j45t16/openbsd_statfs/ > > that seems to be a bug in getmntinfo(3) wherein it doesn't populate > the corresponding mount_info values with a valid pointer. > > I was able to reproduce the OP's segfault with the demonstration > code below. > > If I don't dereference ufs_args.fspec (the commented-out UFS printf() > statements), the code properly iterates over all my mounts and dumps the > corresponding info. > > However, when I dereference ufs_args.fspec (change the corresponding > `#if 0`), my first mountpoint comes back with proper output until I > reach the dereferencing at which point it segfaults : > > f_fstypename: ffs > f_mntonname: / > f_mntfromname: /dev/sd0a > f_mntfromspec: 0aa7ddd292874c57.a > UFS: fspec 0x7684154ce733 > Segmentation fault (core dumped) > > The f_fstypename is indeed "ffs" (MOUNT_UFS/MOUNT_FFS), and the value > of ufs_args.fspec is NOT null (in the output above, it comes back as > 0x7684154ce733), so I would expect fspec to be a valid pointer. > > I don't see anything in the man-pages for getmntinfo(3), statfs(2), or > mount(2) about it NOT populating the mount_info fields with valid data. > > It might be a misunderstanding of what that value should be, but that > value isn't well-documented beyond "block special file to mount" (which, > as a char*, sounds like it should be a string I could dump), and > statfs(2) describes the union as "per-filesystem mount options". > > If it's an opaque object for kernel-use-only, the documentation should > advise about the hazards of dereferencing (or modifying?) that pointer.
Looks like a pointer into kernel mem. Dereffing it will cause a segfault. If anything, it should probably be cleared in the kernel before copying out, there are also other pointers in export_args. The mount helpers do use fspec and a few fields of export_info as an input argument, check mount_ffs.c. -Otto > > -tkc > > #include <err.h> > #include <stdio.h> > #include <string.h> > #include <sys/mount.h> > int main() { > int mntsize, i; > struct statfs *mntbuf; > if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) > err(1, "getmntinfo"); > for (i = 0; i < mntsize; i++) { > printf( > "f_fstypename: %s\n" > "f_mntonname: %s\n" > "f_mntfromname: %s\n" > "f_mntfromspec: %s\n" > , > mntbuf[i].f_fstypename, > mntbuf[i].f_mntonname, > mntbuf[i].f_mntfromname, > mntbuf[i].f_mntfromspec > ); > if (strcmp(mntbuf[i].f_fstypename, MOUNT_UFS) == 0) { > if (mntbuf[i].mount_info.ufs_args.fspec) { > printf("UFS: fspec %p\n", > mntbuf[i].mount_info.ufs_args.fspec); > /* segfaults here: */ > #if 0 > printf("UFS: *fspec %s\n", > mntbuf[i].mount_info.ufs_args.fspec); > #endif > /* even dereferencing the pointer causes a segfault: */ > #if 0 > printf("UFS: fspec[0] %c\n", > *mntbuf[i].mount_info.ufs_args.fspec); > #endif > } else { > printf("UFS: fpsec NULL\n"); > } > } > putchar('\n'); > } > return 0; > } > > > > >