> 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;
> > }
> > 
> > 
> > 
> > 
> > 
> 
> 

Reply via email to