vfs_mount.c (c79126f2e4b31976a54d1c30961d8c7b0f740a3c) vfs_mount.c (31260bf042555bba6523d127ed80172bb97c1839)
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1999-2004 Poul-Henning Kamp
5 * Copyright (c) 1999 Michael Smith
6 * Copyright (c) 1989, 1993
7 * The Regents of the University of California. All rights reserved.
8 * (c) UNIX System Laboratories, Inc.

--- 67 unchanged lines hidden (view full) ---

76static int vfs_domount(struct thread *td, const char *fstype, char *fspath,
77 uint64_t fsflags, struct vfsoptlist **optlist);
78static void free_mntarg(struct mntarg *ma);
79
80static int usermount = 0;
81SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0,
82 "Unprivileged users may mount and unmount file systems");
83
1/*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 1999-2004 Poul-Henning Kamp
5 * Copyright (c) 1999 Michael Smith
6 * Copyright (c) 1989, 1993
7 * The Regents of the University of California. All rights reserved.
8 * (c) UNIX System Laboratories, Inc.

--- 67 unchanged lines hidden (view full) ---

76static int vfs_domount(struct thread *td, const char *fstype, char *fspath,
77 uint64_t fsflags, struct vfsoptlist **optlist);
78static void free_mntarg(struct mntarg *ma);
79
80static int usermount = 0;
81SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0,
82 "Unprivileged users may mount and unmount file systems");
83
84static bool default_autoro = false;
85SYSCTL_BOOL(_vfs, OID_AUTO, default_autoro, CTLFLAG_RW, &default_autoro, 0,
86 "Retry failed r/w mount as r/o if no explicit ro/rw option is specified");
87
84MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure");
85MALLOC_DEFINE(M_STATFS, "statfs", "statfs structure");
86static uma_zone_t mount_zone;
87
88/* List of mounted filesystems. */
89struct mntlist mountlist = TAILQ_HEAD_INITIALIZER(mountlist);
90
91/* For any iteration/modification of mountlist */

--- 449 unchanged lines hidden (view full) ---

541 mac_mount_destroy(mp);
542#endif
543 if (mp->mnt_opt != NULL)
544 vfs_freeopts(mp->mnt_opt);
545 crfree(mp->mnt_cred);
546 uma_zfree(mount_zone, mp);
547}
548
88MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount structure");
89MALLOC_DEFINE(M_STATFS, "statfs", "statfs structure");
90static uma_zone_t mount_zone;
91
92/* List of mounted filesystems. */
93struct mntlist mountlist = TAILQ_HEAD_INITIALIZER(mountlist);
94
95/* For any iteration/modification of mountlist */

--- 449 unchanged lines hidden (view full) ---

545 mac_mount_destroy(mp);
546#endif
547 if (mp->mnt_opt != NULL)
548 vfs_freeopts(mp->mnt_opt);
549 crfree(mp->mnt_cred);
550 uma_zfree(mount_zone, mp);
551}
552
553static bool
554vfs_should_downgrade_to_ro_mount(uint64_t fsflags, int error)
555{
556 /* This is an upgrade of an exisiting mount. */
557 if ((fsflags & MNT_UPDATE) != 0)
558 return (false);
559 /* This is already an R/O mount. */
560 if ((fsflags & MNT_RDONLY) != 0)
561 return (false);
562
563 switch (error) {
564 case ENODEV: /* generic, geom, ... */
565 case EACCES: /* cam/scsi, ... */
566 case EROFS: /* md, mmcsd, ... */
567 /*
568 * These errors can be returned by the storage layer to signal
569 * that the media is read-only. No harm in the R/O mount
570 * attempt if the error was returned for some other reason.
571 */
572 return (true);
573 default:
574 return (false);
575 }
576}
577
549int
550vfs_donmount(struct thread *td, uint64_t fsflags, struct uio *fsoptions)
551{
552 struct vfsoptlist *optlist;
553 struct vfsopt *opt, *tmp_opt;
554 char *fstype, *fspath, *errmsg;
555 int error, fstypelen, fspathlen, errmsg_len, errmsg_pos;
578int
579vfs_donmount(struct thread *td, uint64_t fsflags, struct uio *fsoptions)
580{
581 struct vfsoptlist *optlist;
582 struct vfsopt *opt, *tmp_opt;
583 char *fstype, *fspath, *errmsg;
584 int error, fstypelen, fspathlen, errmsg_len, errmsg_pos;
585 bool autoro;
556
557 errmsg = fspath = NULL;
558 errmsg_len = fspathlen = 0;
559 errmsg_pos = -1;
586
587 errmsg = fspath = NULL;
588 errmsg_len = fspathlen = 0;
589 errmsg_pos = -1;
590 autoro = default_autoro;
560
561 error = vfs_buildopts(fsoptions, &optlist);
562 if (error)
563 return (error);
564
565 if (vfs_getopt(optlist, "errmsg", (void **)&errmsg, &errmsg_len) == 0)
566 errmsg_pos = vfs_getopt_pos(optlist, "errmsg");
567

--- 75 unchanged lines hidden (view full) ---

643 opt->name = strdup("nonosuid", M_MOUNT);
644 }
645 else if (strcmp(opt->name, "nosymfollow") == 0)
646 fsflags |= MNT_NOSYMFOLLOW;
647 else if (strcmp(opt->name, "symfollow") == 0) {
648 free(opt->name, M_MOUNT);
649 opt->name = strdup("nonosymfollow", M_MOUNT);
650 }
591
592 error = vfs_buildopts(fsoptions, &optlist);
593 if (error)
594 return (error);
595
596 if (vfs_getopt(optlist, "errmsg", (void **)&errmsg, &errmsg_len) == 0)
597 errmsg_pos = vfs_getopt_pos(optlist, "errmsg");
598

--- 75 unchanged lines hidden (view full) ---

674 opt->name = strdup("nonosuid", M_MOUNT);
675 }
676 else if (strcmp(opt->name, "nosymfollow") == 0)
677 fsflags |= MNT_NOSYMFOLLOW;
678 else if (strcmp(opt->name, "symfollow") == 0) {
679 free(opt->name, M_MOUNT);
680 opt->name = strdup("nonosymfollow", M_MOUNT);
681 }
651 else if (strcmp(opt->name, "noro") == 0)
682 else if (strcmp(opt->name, "noro") == 0) {
652 fsflags &= ~MNT_RDONLY;
683 fsflags &= ~MNT_RDONLY;
653 else if (strcmp(opt->name, "rw") == 0)
684 autoro = false;
685 }
686 else if (strcmp(opt->name, "rw") == 0) {
654 fsflags &= ~MNT_RDONLY;
687 fsflags &= ~MNT_RDONLY;
655 else if (strcmp(opt->name, "ro") == 0)
688 autoro = false;
689 }
690 else if (strcmp(opt->name, "ro") == 0) {
656 fsflags |= MNT_RDONLY;
691 fsflags |= MNT_RDONLY;
692 autoro = false;
693 }
657 else if (strcmp(opt->name, "rdonly") == 0) {
658 free(opt->name, M_MOUNT);
659 opt->name = strdup("ro", M_MOUNT);
660 fsflags |= MNT_RDONLY;
694 else if (strcmp(opt->name, "rdonly") == 0) {
695 free(opt->name, M_MOUNT);
696 opt->name = strdup("ro", M_MOUNT);
697 fsflags |= MNT_RDONLY;
698 autoro = false;
661 }
699 }
700 else if (strcmp(opt->name, "autoro") == 0) {
701 vfs_freeopt(optlist, opt);
702 autoro = true;
703 }
662 else if (strcmp(opt->name, "suiddir") == 0)
663 fsflags |= MNT_SUIDDIR;
664 else if (strcmp(opt->name, "sync") == 0)
665 fsflags |= MNT_SYNCHRONOUS;
666 else if (strcmp(opt->name, "union") == 0)
667 fsflags |= MNT_UNION;
668 else if (strcmp(opt->name, "automounted") == 0) {
669 fsflags |= MNT_AUTOMOUNTED;

--- 7 unchanged lines hidden (view full) ---

677 * terminating NUL.
678 */
679 if (fstypelen > MFSNAMELEN || fspathlen > MNAMELEN) {
680 error = ENAMETOOLONG;
681 goto bail;
682 }
683
684 error = vfs_domount(td, fstype, fspath, fsflags, &optlist);
704 else if (strcmp(opt->name, "suiddir") == 0)
705 fsflags |= MNT_SUIDDIR;
706 else if (strcmp(opt->name, "sync") == 0)
707 fsflags |= MNT_SYNCHRONOUS;
708 else if (strcmp(opt->name, "union") == 0)
709 fsflags |= MNT_UNION;
710 else if (strcmp(opt->name, "automounted") == 0) {
711 fsflags |= MNT_AUTOMOUNTED;

--- 7 unchanged lines hidden (view full) ---

719 * terminating NUL.
720 */
721 if (fstypelen > MFSNAMELEN || fspathlen > MNAMELEN) {
722 error = ENAMETOOLONG;
723 goto bail;
724 }
725
726 error = vfs_domount(td, fstype, fspath, fsflags, &optlist);
727
728 /*
729 * See if we can mount in the read-only mode if the error code suggests
730 * that it could be possible and the mount options allow for that.
731 * Never try it if "[no]{ro|rw}" has been explicitly requested and not
732 * overridden by "autoro".
733 */
734 if (autoro && vfs_should_downgrade_to_ro_mount(fsflags, error)) {
735 printf("%s: R/W mount failed, possibly R/O media,"
736 " trying R/O mount\n", __func__);
737 fsflags |= MNT_RDONLY;
738 error = vfs_domount(td, fstype, fspath, fsflags, &optlist);
739 }
685bail:
686 /* copyout the errmsg */
687 if (errmsg_pos != -1 && ((2 * errmsg_pos + 1) < fsoptions->uio_iovcnt)
688 && errmsg_len > 0 && errmsg != NULL) {
689 if (fsoptions->uio_segflg == UIO_SYSSPACE) {
690 bcopy(errmsg,
691 fsoptions->uio_iov[2 * errmsg_pos + 1].iov_base,
692 fsoptions->uio_iov[2 * errmsg_pos + 1].iov_len);

--- 1296 unchanged lines hidden ---
740bail:
741 /* copyout the errmsg */
742 if (errmsg_pos != -1 && ((2 * errmsg_pos + 1) < fsoptions->uio_iovcnt)
743 && errmsg_len > 0 && errmsg != NULL) {
744 if (fsoptions->uio_segflg == UIO_SYSSPACE) {
745 bcopy(errmsg,
746 fsoptions->uio_iov[2 * errmsg_pos + 1].iov_base,
747 fsoptions->uio_iov[2 * errmsg_pos + 1].iov_len);

--- 1296 unchanged lines hidden ---