> Date: Thu, 6 Mar 2025 09:10:18 +0100
> From: Otto Moerbeek <[email protected]>
>
> 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.
Not a kernel address, but the userland address used by mount(8) when
the filesystem was originially mounted. That process is long dead and
dereferencing it in a completely different userland process is likely
to result in a segfault.
At least we're not leaking info about the kernel address space or some
daemon... Unless someone uses amd(8) maybe?
> >
> > -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;
> > }
> >
> >
> >
> >
> >
>
>