Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3d3ea8e6 authored by Shirish Pargaonkar's avatar Shirish Pargaonkar Committed by Steve French
Browse files

cifs: Add mount options for backup intent (try #6)



Add mount options backupuid and backugid.

It allows an authenticated user to access files with the intent to back them
up including their ACLs, who may not have access permission but has
"Backup files and directories user right" on them (by virtue of being part
of the built-in group Backup Operators.

When mount options backupuid is specified, cifs client restricts the
use of backup intents to the user whose effective user id is specified
along with the mount option.

When mount options backupgid is specified, cifs client restricts the
use of backup intents to the users whose effective user id belongs to the
group id specified along with the mount option.

If an authenticated user is not part of the built-in group Backup Operators
at the server, access to such files is denied, even if allowed by the client.

Signed-off-by: default avatarShirish Pargaonkar <shirishpargaonkar@gmail.com>
Reviewed-by: default avatarJeff Layton <jlayton@redhat.com>
Signed-off-by: default avatarSteve French <smfrench@gmail.com>
parent 8bc4392a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@
#define CIFS_MOUNT_STRICT_IO	0x40000 /* strict cache mode */
#define CIFS_MOUNT_RWPIDFORWARD	0x80000 /* use pid forwarding for rw */
#define CIFS_MOUNT_POSIXACL	0x100000 /* mirror of MS_POSIXACL in mnt_cifs_flags */
#define CIFS_MOUNT_CIFS_BACKUPUID 0x200000 /* backup intent bit for a user */
#define CIFS_MOUNT_CIFS_BACKUPGID 0x400000 /* backup intent bit for a group */

struct cifs_sb_info {
	struct rb_root tlink_tree;
@@ -55,6 +57,8 @@ struct cifs_sb_info {
	atomic_t active;
	uid_t	mnt_uid;
	gid_t	mnt_gid;
	uid_t	mnt_backupuid;
	gid_t	mnt_backupgid;
	mode_t	mnt_file_mode;
	mode_t	mnt_dir_mode;
	unsigned int mnt_cifs_flags;
+12 −6
Original line number Diff line number Diff line
@@ -945,7 +945,7 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
{
	struct cifs_ntsd *pntsd = NULL;
	int oplock = 0;
	int xid, rc;
	int xid, rc, create_options = 0;
	__u16 fid;
	struct cifs_tcon *tcon;
	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
@@ -956,8 +956,11 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
	tcon = tlink_tcon(tlink);
	xid = GetXid();

	rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0,
			 &fid, &oplock, NULL, cifs_sb->local_nls,
	if (backup_cred(cifs_sb))
		create_options |= CREATE_OPEN_BACKUP_INTENT;

	rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL,
			create_options, &fid, &oplock, NULL, cifs_sb->local_nls,
			cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
	if (!rc) {
		rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen);
@@ -995,7 +998,7 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
		struct cifs_ntsd *pnntsd, u32 acllen)
{
	int oplock = 0;
	int xid, rc;
	int xid, rc, create_options = 0;
	__u16 fid;
	struct cifs_tcon *tcon;
	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
@@ -1006,7 +1009,10 @@ static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path,
	tcon = tlink_tcon(tlink);
	xid = GetXid();

	rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, WRITE_DAC, 0,
	if (backup_cred(cifs_sb))
		create_options |= CREATE_OPEN_BACKUP_INTENT;

	rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, WRITE_DAC, create_options,
			 &fid, &oplock, NULL, cifs_sb->local_nls,
			 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
	if (rc) {
+6 −1
Original line number Diff line number Diff line
@@ -167,6 +167,8 @@ struct smb_vol {
	uid_t cred_uid;
	uid_t linux_uid;
	gid_t linux_gid;
	uid_t backupuid;
	gid_t backupgid;
	mode_t file_mode;
	mode_t dir_mode;
	unsigned secFlg;
@@ -179,6 +181,8 @@ struct smb_vol {
	bool noperm:1;
	bool no_psx_acl:1; /* set if posix acl support should be disabled */
	bool cifs_acl:1;
	bool backupuid_specified; /* mount option  backupuid  is specified */
	bool backupgid_specified; /* mount option  backupgid  is specified */
	bool no_xattr:1;   /* set if xattr (EA) support should be disabled*/
	bool server_ino:1; /* use inode numbers from server ie UniqueId */
	bool direct_io:1;
@@ -219,7 +223,8 @@ struct smb_vol {
			 CIFS_MOUNT_OVERR_GID | CIFS_MOUNT_DYNPERM | \
			 CIFS_MOUNT_NOPOSIXBRL | CIFS_MOUNT_NOSSYNC | \
			 CIFS_MOUNT_FSCACHE | CIFS_MOUNT_MF_SYMLINKS | \
			 CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO)
			 CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO | \
			 CIFS_MOUNT_CIFS_BACKUPUID | CIFS_MOUNT_CIFS_BACKUPGID)

#define CIFS_MS_MASK (MS_RDONLY | MS_MANDLOCK | MS_NOEXEC | MS_NOSUID | \
		      MS_NODEV | MS_SYNCHRONOUS)
+1 −0
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ extern int SendReceiveBlockingLock(const unsigned int xid,
extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length);
extern bool is_valid_oplock_break(struct smb_hdr *smb,
				  struct TCP_Server_Info *);
extern bool backup_cred(struct cifs_sb_info *);
extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
			    unsigned int bytes_written);
+27 −0
Original line number Diff line number Diff line
@@ -831,6 +831,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
{
	char *value, *data, *end;
	char *mountdata_copy = NULL, *options;
	int err;
	unsigned int  temp_len, i, j;
	char separator[2];
	short int override_uid = -1;
@@ -887,6 +888,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
			cFYI(1, "Null separator not allowed");
		}
	}
	vol->backupuid_specified = false; /* no backup intent for a user */
	vol->backupgid_specified = false; /* no backup intent for a group */

	while ((data = strsep(&options, separator)) != NULL) {
		if (!*data)
@@ -1446,6 +1449,22 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
			vol->mfsymlinks = true;
		} else if (strnicmp(data, "multiuser", 8) == 0) {
			vol->multiuser = true;
		} else if (!strnicmp(data, "backupuid", 9) && value && *value) {
			err = kstrtouint(value, 0, &vol->backupuid);
			if (err < 0) {
				cERROR(1, "%s: Invalid backupuid value",
					__func__);
				goto cifs_parse_mount_err;
			}
			vol->backupuid_specified = true;
		} else if (!strnicmp(data, "backupgid", 9) && value && *value) {
			err = kstrtouint(value, 0, &vol->backupgid);
			if (err < 0) {
				cERROR(1, "%s: Invalid backupgid value",
					__func__);
				goto cifs_parse_mount_err;
			}
			vol->backupgid_specified = true;
		} else
			printk(KERN_WARNING "CIFS: Unknown mount option %s\n",
						data);
@@ -2737,6 +2756,10 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,

	cifs_sb->mnt_uid = pvolume_info->linux_uid;
	cifs_sb->mnt_gid = pvolume_info->linux_gid;
	if (pvolume_info->backupuid_specified)
		cifs_sb->mnt_backupuid = pvolume_info->backupuid;
	if (pvolume_info->backupgid_specified)
		cifs_sb->mnt_backupgid = pvolume_info->backupgid;
	cifs_sb->mnt_file_mode = pvolume_info->file_mode;
	cifs_sb->mnt_dir_mode = pvolume_info->dir_mode;
	cFYI(1, "file mode: 0x%x  dir mode: 0x%x",
@@ -2767,6 +2790,10 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD;
	if (pvolume_info->cifs_acl)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL;
	if (pvolume_info->backupuid_specified)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID;
	if (pvolume_info->backupgid_specified)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID;
	if (pvolume_info->override_uid)
		cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID;
	if (pvolume_info->override_gid)
Loading