The branch stable/14 has been updated by mckusick:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=45197d29ced2f57941a771dc8ec37243a52b9a7e

commit 45197d29ced2f57941a771dc8ec37243a52b9a7e
Author:     Kirk McKusick <[email protected]>
AuthorDate: 2025-10-22 18:01:03 +0000
Commit:     Kirk McKusick <[email protected]>
CommitDate: 2025-11-17 23:47:36 +0000

    Fix getmntpoint(3) to operate as it is documented in its manual page.
    
    The -libutil function getmntpoint(3) is documented as accepting a device
    name “with or without /dev/ prepended to it” but did not attempt to
    prepend /dev/. This patch corrects the problem by prepending /dev/ to
    names that do not begin with a '/'.
    
    Reported-by: Dag-Erling Smørgrav
    Differential Revision: https://reviews.freebsd.org/D53185
    Sponsored-by: Netflix
    
    (cherry picked from commit 99bf680a8499dea71db5da705dfe41f4bb5e00ab)
---
 sbin/mount/getmntopts.c | 53 ++++++++++++++++++++++++++++++++++---------------
 1 file changed, 37 insertions(+), 16 deletions(-)

diff --git a/sbin/mount/getmntopts.c b/sbin/mount/getmntopts.c
index fab25466425f..32f2920eb9c5 100644
--- a/sbin/mount/getmntopts.c
+++ b/sbin/mount/getmntopts.c
@@ -152,6 +152,18 @@ checkpath_allow_file(const char *path, char *resolved)
        return (0);
 }
 
+static char *
+prependdevtopath(const char *path, char *buf, u_long buflen)
+{
+       u_long len;
+
+       if ((len = strlen(_PATH_DEV) + strlen(path) + 1) > buflen)
+               return NULL;
+       strncpy(buf, _PATH_DEV, len);
+       strncat(buf, path, len - sizeof(_PATH_DEV));
+       return (buf);
+}
+
 /*
  * Get the mount point information for name. Name may be mount point name
  * or device name (with or without /dev/ preprended).
@@ -160,19 +172,27 @@ struct statfs *
 getmntpoint(const char *name)
 {
        struct stat devstat, mntdevstat;
-       char device[sizeof(_PATH_DEV) - 1 + MNAMELEN];
-       char *ddevname;
+       char *devname;
        struct statfs *mntbuf, *statfsp;
-       int i, mntsize, isdev;
-       u_long len;
+       int i, len, isdev, mntsize, mntfromnamesize;
+       char device[sizeof(_PATH_DEV) - 1 + MNAMELEN];
+       u_long devlen;
 
-       if (stat(name, &devstat) != 0)
+       devlen = sizeof(device);
+       /*
+        * Note that stat(NULL, &statbuf) returns -1 (EBADF) which will
+        * cause us to return NULL if prependdevtopath() returns NULL.
+        */
+       if (stat(name, &devstat) != 0 &&
+           (name[0] != '/' &&
+            stat(prependdevtopath(name, device, devlen), &devstat) != 0))
                return (NULL);
        if (S_ISCHR(devstat.st_mode) || S_ISBLK(devstat.st_mode))
                isdev = 1;
        else
                isdev = 0;
        mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
+       mntfromnamesize = sizeof(statfsp->f_mntfromname);
        for (i = 0; i < mntsize; i++) {
                statfsp = &mntbuf[i];
                if (isdev == 0) {
@@ -180,19 +200,20 @@ getmntpoint(const char *name)
                                continue;
                        return (statfsp);
                }
-               ddevname = statfsp->f_mntfromname;
-               if (*ddevname != '/') {
-                       if ((len = strlen(_PATH_DEV) + strlen(ddevname) + 1) >
-                           sizeof(statfsp->f_mntfromname) ||
-                           len > sizeof(device))
+               devname = statfsp->f_mntfromname;
+               if (*devname == '/') {
+                       if (stat(devname, &mntdevstat) != 0)
+                               continue;
+               } else {
+                       devname = prependdevtopath(devname, device, devlen);
+                       if (devname == NULL ||
+                           (len = strlen(devname)) > mntfromnamesize)
+                               continue;
+                       if (stat(devname, &mntdevstat) != 0)
                                continue;
-                       strncpy(device, _PATH_DEV, len);
-                       strncat(device, ddevname, len);
-                       if (stat(device, &mntdevstat) == 0)
-                               strncpy(statfsp->f_mntfromname, device, len);
+                       strncpy(statfsp->f_mntfromname, devname, len);
                }
-               if (stat(ddevname, &mntdevstat) == 0 &&
-                   S_ISCHR(mntdevstat.st_mode) &&
+               if (S_ISCHR(mntdevstat.st_mode) &&
                    mntdevstat.st_rdev == devstat.st_rdev)
                        return (statfsp);
        }

Reply via email to