The problem:

$ mount /dev/tty /tmp
Abort trap (core dumped)

The relevant kdump snippet:

 45441 mount    CALL  open(0x7f7ffffeb580,0x10000<O_RDONLY|O_CLOEXEC>)
 45441 mount    NAMI  "/dev/tty"
 45441 mount    RET   open 3
 45441 mount    CALL  ioctl(3,DIOCGDINFO,0x7f7ffffeb350)
 45441 mount    PLDG  ioctl, "tty", errno 1 Operation not permitted
 45441 mount    PSIG  SIGABRT SIG_DFL

and the backtrace:

#0  0x00001103967a72aa in ioctl () at <stdin>:2
#1  0x0000110364ca97b9 in readlabelfs (device=0x7f7ffffd0ada "/dev/tty", 
verbose=0) at /usr/src/lib/libutil/readlabel.c:128
#2  0x00001100d4201210 in main () from /usr/obj/sbin/mount/mount

As usual, the fix consists of hoisting the problematic bit above the
pledge call.  This has the side effect that the string bashing functions
hasopt(), catopt() and maketypelist() are now called without pledge from
the getopt switch, but I don't think that's a problem.  It would be easy
to postpone the call to maketypelist() until after pledge, if anyone is
worried about it.

Index: mount.c
===================================================================
RCS file: /var/cvs/src/sbin/mount/mount.c,v
retrieving revision 1.70
diff -u -p -r1.70 mount.c
--- mount.c     25 Jan 2017 02:33:25 -0000      1.70
+++ mount.c     28 Jan 2017 14:11:28 -0000
@@ -109,9 +109,6 @@ main(int argc, char * const argv[])
        int all, ch, forceall, i, mntsize, rval, new;
        char *options, mntpath[PATH_MAX];
 
-       if (pledge("stdio rpath disklabel proc exec", NULL) == -1)
-               err(1, "pledge");
-
        all = forceall = 0;
        options = NULL;
        vfstype = "ffs";
@@ -168,6 +165,25 @@ main(int argc, char * const argv[])
        argc -= optind;
        argv += optind;
 
+       if (typelist == NULL && argc == 2) {
+               /*
+                * If -t flag has not been specified, and spec contains either
+                * a ':' or a '@' then assume that an NFS filesystem is being
+                * specified ala Sun.  If not, check the disklabel for a
+                * known filesystem type.
+                */
+               if (strpbrk(argv[0], ":@") != NULL)
+                       vfstype = "nfs";
+               else {
+                       char *labelfs = readlabelfs(argv[0], 0);
+                       if (labelfs != NULL)
+                               vfstype = labelfs;
+               }
+       }
+
+       if (pledge("stdio rpath disklabel proc exec", NULL) == -1)
+               err(1, "pledge");
+
 #define        BADTYPE(type)                                                   
\
        (strcmp(type, FSTAB_RO) &&                                      \
            strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ))
@@ -261,23 +277,7 @@ main(int argc, char * const argv[])
                    mntonname, options, fs->fs_mntops, skip);
                break;
        case 2:
-               /*
-                * If -t flag has not been specified, and spec contains either
-                * a ':' or a '@' then assume that an NFS filesystem is being
-                * specified ala Sun.  If not, check the disklabel for a
-                * known filesystem type.
-                */
-               if (typelist == NULL) {
-                       if (strpbrk(argv[0], ":@") != NULL)
-                               vfstype = "nfs";
-                       else {
-                               char *labelfs = readlabelfs(argv[0], 0);
-                               if (labelfs != NULL)
-                                       vfstype = labelfs;
-                       }
-               }
-               rval = mountfs(vfstype,
-                   argv[0], argv[1], options, NULL, 0);
+               rval = mountfs(vfstype, argv[0], argv[1], options, NULL, 0);
                break;
        default:
                usage();

Reply via email to