git: 470de7a717fc - stable/13 - cd9660: Add support for mask,dirmask,uid,gid options

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Mon, 08 Apr 2024 20:25:37 UTC
The branch stable/13 has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=470de7a717fc1c5954f1196c1d10b96fd9f2d524

commit 470de7a717fc1c5954f1196c1d10b96fd9f2d524
Author:     Ricardo Branco <rbranco@suse.de>
AuthorDate: 2024-01-08 20:24:53 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2024-04-08 17:29:11 +0000

    cd9660: Add support for mask,dirmask,uid,gid options
    
    Reviewed by:    jhb
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/982
    
    (cherry picked from commit 82f2275b73e556580b155ea9bbf7f7e364458fa1)
---
 sbin/mount_cd9660/mount_cd9660.8 | 37 ++++++++++++++++++-
 sbin/mount_cd9660/mount_cd9660.c | 79 ++++++++++++++++++++++++++++++++++++++--
 sys/fs/cd9660/cd9660_mount.h     |  7 ++++
 sys/fs/cd9660/cd9660_vfsops.c    | 23 ++++++++++++
 sys/fs/cd9660/cd9660_vnops.c     | 24 ++++++++++--
 sys/fs/cd9660/iso.h              |  5 +++
 6 files changed, 167 insertions(+), 8 deletions(-)

diff --git a/sbin/mount_cd9660/mount_cd9660.8 b/sbin/mount_cd9660/mount_cd9660.8
index a31e6d833245..af417d4d025e 100644
--- a/sbin/mount_cd9660/mount_cd9660.8
+++ b/sbin/mount_cd9660/mount_cd9660.8
@@ -31,7 +31,7 @@
 .\"
 .\"     @(#)mount_cd9660.8	8.3 (Berkeley) 3/27/94
 .\"
-.Dd August 11, 2018
+.Dd January 2, 2024
 .Dt MOUNT_CD9660 8
 .Os
 .Sh NAME
@@ -41,8 +41,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
@@ -68,6 +72,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 f867e94da417..253b9eb32540 100644
--- a/sbin/mount_cd9660/mount_cd9660.c
+++ b/sbin/mount_cd9660/mount_cd9660.c
@@ -58,8 +58,11 @@ static char sccsid[] = "@(#)mount_cd9660.c	8.7 (Berkeley) 5/1/95";
 
 #include <arpa/inet.h>
 
+#include <ctype.h>
 #include <err.h>
 #include <errno.h>
+#include <grp.h>
+#include <pwd.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -74,6 +77,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);
@@ -94,7 +100,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);
@@ -105,6 +111,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;
@@ -124,6 +139,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;
@@ -187,8 +205,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);
 }
 
@@ -268,3 +286,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 99642603cc7a..97637f66ad93 100644
--- a/sys/fs/cd9660/cd9660_mount.h
+++ b/sys/fs/cd9660/cd9660_mount.h
@@ -42,6 +42,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 */
@@ -53,3 +57,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 90a8996c9651..c3339438fcd8 100644
--- a/sys/fs/cd9660/cd9660_vfsops.c
+++ b/sys/fs/cd9660/cd9660_vfsops.c
@@ -107,6 +107,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);
@@ -223,6 +229,7 @@ iso_mountfs(devvp, mp)
 	struct g_consumer *cp;
 	struct bufobj *bo;
 	char *cs_local, *cs_disk;
+	int v;
 
 	dev = devvp->v_rdev;
 	dev_ref(dev);
@@ -392,6 +399,7 @@ iso_mountfs(devvp, 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);
@@ -399,6 +407,21 @@ iso_mountfs(devvp, 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 4fee81eb76ea..9598ecdd7712 100644
--- a/sys/fs/cd9660/cd9660_vnops.c
+++ b/sys/fs/cd9660/cd9660_vnops.c
@@ -59,6 +59,7 @@
 
 #include <fs/cd9660/iso.h>
 #include <fs/cd9660/cd9660_node.h>
+#include <fs/cd9660/cd9660_mount.h>
 #include <fs/cd9660/iso_rrip.h>
 
 static vop_setattr_t	cd9660_setattr;
@@ -134,6 +135,9 @@ cd9660_access(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);
@@ -155,8 +159,16 @@ cd9660_access(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
@@ -196,9 +208,13 @@ cd9660_getattr(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 ac3f61e56cc1..bf98e75c42d9 100644
--- a/sys/fs/cd9660/iso.h
+++ b/sys/fs/cd9660/iso.h
@@ -239,6 +239,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;