diff --git a/sbin/mount_cd9660/mount_cd9660.8 b/sbin/mount_cd9660/mount_cd9660.8 index cd6f7a19f6eb..d2cdd2f3ef20 100644 --- a/sbin/mount_cd9660/mount_cd9660.8 +++ b/sbin/mount_cd9660/mount_cd9660.8 @@ -29,7 +29,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd August 11, 2018 +.Dd January 2, 2024 .Dt MOUNT_CD9660 8 .Os .Sh NAME @@ -39,8 +39,12 @@ .Nm .Op Fl begjrv .Op Fl C Ar charset +.Op Fl G Ar gid +.Op Fl m Ar mask +.Op Fl M Ar mask .Op Fl o Ar options .Op Fl s Ar startsector +.Op Fl U Ar uid .Ar special node .Sh DESCRIPTION The @@ -66,6 +70,37 @@ Do not strip version numbers on files. only the last one will be listed.) In either case, files may be opened without explicitly stating a version number. +.It Fl G Ar group +Set the group of the files in the file system to +.Ar group . +The default gid on non-Rockridge volumes is zero. +.It Fl U Ar user +Set the owner of the files in the file system to +.Ar user . +The default uid on non-Rockridge volumes is zero. +.It Fl m Ar mask +Specify the maximum file permissions for files +in the file system. +(For example, a +.Ar mask +of +.Li 755 +specifies that, by default, the owner should have +read, write, and execute permissions for files, but +others should only have read and execute permissions). +See +.Xr chmod 1 +for more information about octal file modes. +Only the nine low-order bits of +.Ar mask +are used. +The default +.Ar mask +on non-Rockridge volumes is 755. +.It Fl M Ar mask +Specify the maximum file permissions for directories +in the file system. +See the previous option's description for details. .It Fl j Do not use any Joliet extensions included in the file system. .It Fl o diff --git a/sbin/mount_cd9660/mount_cd9660.c b/sbin/mount_cd9660/mount_cd9660.c index ab6da7271c17..d8d64eb5a656 100644 --- a/sbin/mount_cd9660/mount_cd9660.c +++ b/sbin/mount_cd9660/mount_cd9660.c @@ -44,8 +44,11 @@ #include +#include #include #include +#include +#include #include #include #include @@ -60,6 +63,9 @@ static struct mntopt mopts[] = { MOPT_END }; +static gid_t a_gid(const char *); +static uid_t a_uid(const char *); +static mode_t a_mask(const char *); static int get_ssector(const char *dev); static int set_charset(struct iovec **, int *iovlen, const char *); void usage(void); @@ -80,7 +86,7 @@ main(int argc, char **argv) mntflags = verbose = 0; ssector = -1; - while ((ch = getopt(argc, argv, "begjo:rs:vC:")) != -1) + while ((ch = getopt(argc, argv, "begG:jm:M:o:rs:U:vC:")) != -1) switch (ch) { case 'b': build_iovec(&iov, &iovlen, "brokenjoliet", NULL, (size_t)-1); @@ -91,6 +97,15 @@ main(int argc, char **argv) case 'g': build_iovec(&iov, &iovlen, "gens", NULL, (size_t)-1); break; + case 'G': + build_iovec_argf(&iov, &iovlen, "gid", "%d", a_gid(optarg)); + break; + case 'm': + build_iovec_argf(&iov, &iovlen, "mask", "%u", a_mask(optarg)); + break; + case 'M': + build_iovec_argf(&iov, &iovlen, "dirmask", "%u", a_mask(optarg)); + break; case 'j': build_iovec(&iov, &iovlen, "nojoliet", NULL, (size_t)-1); break; @@ -110,6 +125,9 @@ main(int argc, char **argv) case 's': ssector = atoi(optarg); break; + case 'U': + build_iovec_argf(&iov, &iovlen, "uid", "%d", a_uid(optarg)); + break; case 'v': verbose++; break; @@ -173,8 +191,8 @@ void usage(void) { (void)fprintf(stderr, -"usage: mount_cd9660 [-begjrv] [-C charset] [-o options] [-s startsector]\n" -" special node\n"); +"usage: mount_cd9660 [-begjrv] [-C charset] [-G gid] [-m mask] [-M mask]\n" +" [-o options] [-U uid] [-s startsector] special node\n"); exit(EX_USAGE); } @@ -254,3 +272,58 @@ set_charset(struct iovec **iov, int *iovlen, const char *localcs) return (0); } + +static gid_t +a_gid(const char *s) +{ + struct group *gr; + const char *gname; + gid_t gid; + + if ((gr = getgrnam(s)) != NULL) + gid = gr->gr_gid; + else { + for (gname = s; *s && isdigit(*s); ++s); + if (!*s) + gid = atoi(gname); + else + errx(EX_NOUSER, "unknown group id: %s", gname); + } + return (gid); +} + +static uid_t +a_uid(const char *s) +{ + struct passwd *pw; + const char *uname; + uid_t uid; + + if ((pw = getpwnam(s)) != NULL) + uid = pw->pw_uid; + else { + for (uname = s; *s && isdigit(*s); ++s); + if (!*s) + uid = atoi(uname); + else + errx(EX_NOUSER, "unknown user id: %s", uname); + } + return (uid); +} + +static mode_t +a_mask(const char *s) +{ + int done, rv; + char *ep; + + done = 0; + rv = -1; + if (*s >= '0' && *s <= '7') { + done = 1; + rv = strtol(optarg, &ep, 8); + } + if (!done || rv < 0 || *ep) + errx(EX_USAGE, "invalid file mode: %s", s); + return (rv); +} diff --git a/sys/fs/cd9660/cd9660_mount.h b/sys/fs/cd9660/cd9660_mount.h index 88075dc2788b..4f2d9538a10a 100644 --- a/sys/fs/cd9660/cd9660_mount.h +++ b/sys/fs/cd9660/cd9660_mount.h @@ -40,6 +40,10 @@ struct iso_args { char *fspec; /* block special device to mount */ struct oexport_args export; /* network export info */ + uid_t uid; /* uid that owns ISO-9660 files */ + gid_t gid; /* gid that owns ISO-9660 files */ + mode_t fmask; /* file mask to be applied for files */ + mode_t dmask; /* file mask to be applied for directories */ int flags; /* mounting flags, see below */ int ssector; /* starting sector, 0 for 1st session */ char *cs_disk; /* disk charset for Joliet cs conversion */ @@ -51,3 +55,6 @@ struct iso_args { #define ISOFSMNT_NOJOLIET 0x00000008 /* disable Joliet Ext.*/ #define ISOFSMNT_BROKENJOLIET 0x00000010/* allow broken Joliet disks */ #define ISOFSMNT_KICONV 0x00000020 /* Use libiconv to convert chars */ + +#define ISOFSMNT_UID 0x00000100 /* override uid */ +#define ISOFSMNT_GID 0x00000200 /* override gid */ diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c index ee0b68714c2a..f067453d3458 100644 --- a/sys/fs/cd9660/cd9660_vfsops.c +++ b/sys/fs/cd9660/cd9660_vfsops.c @@ -104,6 +104,12 @@ cd9660_cmount(struct mntarg *ma, void *data, uint64_t flags) ma = mount_argsu(ma, "from", args.fspec, MAXPATHLEN); ma = mount_arg(ma, "export", &args.export, sizeof(args.export)); + if (args.flags & ISOFSMNT_UID) + ma = mount_argf(ma, "uid", "%d", args.uid); + if (args.flags & ISOFSMNT_GID) + ma = mount_argf(ma, "gid", "%d", args.gid); + ma = mount_argf(ma, "mask", "%d", args.fmask); + ma = mount_argf(ma, "dirmask", "%d", args.dmask); ma = mount_argsu(ma, "cs_disk", args.cs_disk, 64); ma = mount_argsu(ma, "cs_local", args.cs_local, 64); ma = mount_argf(ma, "ssector", "%u", args.ssector); @@ -218,6 +224,7 @@ iso_mountfs(struct vnode *devvp, struct mount *mp) struct g_consumer *cp; struct bufobj *bo; char *cs_local, *cs_disk; + int v; dev = devvp->v_rdev; dev_ref(dev); @@ -387,6 +394,7 @@ iso_mountfs(struct vnode *devvp, struct mount *mp) isomp->im_mountp = mp; isomp->im_dev = dev; isomp->im_devvp = devvp; + isomp->im_fmask = isomp->im_dmask = ACCESSPERMS; vfs_flagopt(mp->mnt_optnew, "norrip", &isomp->im_flags, ISOFSMNT_NORRIP); vfs_flagopt(mp->mnt_optnew, "gens", &isomp->im_flags, ISOFSMNT_GENS); @@ -394,6 +402,21 @@ iso_mountfs(struct vnode *devvp, struct mount *mp) vfs_flagopt(mp->mnt_optnew, "nojoliet", &isomp->im_flags, ISOFSMNT_NOJOLIET); vfs_flagopt(mp->mnt_optnew, "kiconv", &isomp->im_flags, ISOFSMNT_KICONV); + if (vfs_scanopt(mp->mnt_optnew, "uid", "%d", &v) == 1) { + isomp->im_flags |= ISOFSMNT_UID; + isomp->im_uid = v; + } + if (vfs_scanopt(mp->mnt_optnew, "gid", "%d", &v) == 1) { + isomp->im_flags |= ISOFSMNT_GID; + isomp->im_gid = v; + } + if (vfs_scanopt(mp->mnt_optnew, "mask", "%d", &v) == 1) { + isomp->im_fmask &= v; + } + if (vfs_scanopt(mp->mnt_optnew, "dirmask", "%d", &v) == 1) { + isomp->im_dmask &= v; + } + /* Check the Rock Ridge Extension support */ if (!(isomp->im_flags & ISOFSMNT_NORRIP)) { if ((error = bread(isomp->im_devvp, (isomp->root_extent + diff --git a/sys/fs/cd9660/cd9660_vnops.c b/sys/fs/cd9660/cd9660_vnops.c index 1b11da80431b..33ca58472490 100644 --- a/sys/fs/cd9660/cd9660_vnops.c +++ b/sys/fs/cd9660/cd9660_vnops.c @@ -56,6 +56,7 @@ #include #include +#include #include static vop_setattr_t cd9660_setattr; @@ -119,6 +120,9 @@ cd9660_access(struct vop_access_args *ap) struct vnode *vp = ap->a_vp; struct iso_node *ip = VTOI(vp); accmode_t accmode = ap->a_accmode; + accmode_t file_mode; + uid_t uid; + gid_t gid; if (vp->v_type == VCHR || vp->v_type == VBLK) return (EOPNOTSUPP); @@ -140,8 +144,16 @@ cd9660_access(struct vop_access_args *ap) } } - return (vaccess(vp->v_type, ip->inode.iso_mode, ip->inode.iso_uid, - ip->inode.iso_gid, ap->a_accmode, ap->a_cred)); + file_mode = ip->inode.iso_mode; + file_mode &= (vp->v_type == VDIR) ? ip->i_mnt->im_dmask : ip->i_mnt->im_fmask; + + uid = (ip->i_mnt->im_flags & ISOFSMNT_UID) ? + ip->i_mnt->im_uid : ip->inode.iso_uid; + gid = (ip->i_mnt->im_flags & ISOFSMNT_GID) ? + ip->i_mnt->im_gid : ip->inode.iso_gid; + + return (vaccess(vp->v_type, file_mode, uid, + gid, ap->a_accmode, ap->a_cred)); } static int @@ -169,9 +181,13 @@ cd9660_getattr(struct vop_getattr_args *ap) vap->va_fileid = ip->i_number; vap->va_mode = ip->inode.iso_mode; + vap->va_mode &= (vp->v_type == VDIR) ? ip->i_mnt->im_dmask : ip->i_mnt->im_fmask; + vap->va_nlink = ip->inode.iso_links; - vap->va_uid = ip->inode.iso_uid; - vap->va_gid = ip->inode.iso_gid; + vap->va_uid = (ip->i_mnt->im_flags & ISOFSMNT_UID) ? + ip->i_mnt->im_uid : ip->inode.iso_uid; + vap->va_gid = (ip->i_mnt->im_flags & ISOFSMNT_GID) ? + ip->i_mnt->im_gid : ip->inode.iso_gid; vap->va_atime = ip->inode.iso_atime; vap->va_mtime = ip->inode.iso_mtime; vap->va_ctime = ip->inode.iso_ctime; diff --git a/sys/fs/cd9660/iso.h b/sys/fs/cd9660/iso.h index 2d9e2e8b682a..a9733f62c077 100644 --- a/sys/fs/cd9660/iso.h +++ b/sys/fs/cd9660/iso.h @@ -237,6 +237,11 @@ struct iso_mnt { struct g_consumer *im_cp; struct bufobj *im_bo; + uid_t im_uid; + gid_t im_gid; + mode_t im_fmask; + mode_t im_dmask; + int logical_block_size; int im_bshift; int im_bmask;