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

Commit 87dbe42a authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
 "Including:

   - nine bug fixes for stable. Some of these we found at the recent two
     weeks of SMB3 test events/plugfests.

   - significant improvements in reconnection (e.g. if server or network
     crashes) especially when mounted with "persistenthandles" or to
     server which advertises Continuous Availability on the share.

   - a new mount option "idsfromsid" which improves POSIX compatibility
     in some cases (when winbind not configured e.g.) by better (and
     faster) fetching uid/gid from acl (when "cifsacl" mount option is
     enabled). NB: we are almost complete work on "cifsacl" (querying
     mode/uid/gid from ACL) for SMB3, but SMB3 support for cifsacl is
     not included in this set.

   - improved handling for SMB3 "credits" (even if server is buggy)

  Still working on two sets of changes:

   - cifsacl enablement for SMB3

   - cleanup of RFC1001 length calculation (so we can handle encryption
     and multichannel and RDMA)

  And a couple of new bugs were reported recently (unrelated to above)
  so will probably have another merge request next week"

* 'for-next' of git://git.samba.org/sfrench/cifs-2.6: (21 commits)
  CIFS: Retrieve uid and gid from special sid if enabled
  CIFS: Add new mount option to set owner uid and gid from special sids in acl
  CIFS: Reset read oplock to NONE if we have mandatory locks after reopen
  CIFS: Fix persistent handles re-opening on reconnect
  SMB2: Separate RawNTLMSSP authentication from SMB2_sess_setup
  SMB2: Separate Kerberos authentication from SMB2_sess_setup
  Expose cifs module parameters in sysfs
  Cleanup missing frees on some ioctls
  Enable previous version support
  Do not send SMB3 SET_INFO request if nothing is changing
  SMB3: Add mount parameter to allow user to override max credits
  fs/cifs: reopen persistent handles on reconnect
  Clarify locking of cifs file and tcon structures and make more granular
  Fix regression which breaks DFS mounting
  fs/cifs: keep guid when assigning fid to fileinfo
  SMB3: GUIDs should be constructed as random but valid uuids
  Set previous session id correctly on SMB3 reconnect
  cifs: Limit the overall credit acquired
  Display number of credits available
  Add way to query creation time of file via cifs xattr
  ...
parents d3304cad 3514de3f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -152,6 +152,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
	list_for_each(tmp1, &cifs_tcp_ses_list) {
		server = list_entry(tmp1, struct TCP_Server_Info,
				    tcp_ses_list);
		seq_printf(m, "\nNumber of credits: %d", server->credits);
		i++;
		list_for_each(tmp2, &server->smb_ses_list) {
			ses = list_entry(tmp2, struct cifs_ses,
+1 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@
#define CIFS_MOUNT_USE_PREFIX_PATH 0x1000000 /* make subpath with unaccessible
					      * root mountable
					      */
#define CIFS_MOUNT_UID_FROM_ACL 0x2000000 /* try to get UID via special SID */

struct cifs_sb_info {
	struct rb_root tlink_tree;
+8 −0
Original line number Diff line number Diff line
@@ -36,7 +36,15 @@ struct smb_mnt_fs_info {
	__u64   cifs_posix_caps;
} __packed;

struct smb_snapshot_array {
	__u32	number_of_snapshots;
	__u32	number_of_snapshots_returned;
	__u32	snapshot_array_size;
	/*	snapshots[]; */
} __packed;

#define CIFS_IOCTL_MAGIC	0xCF
#define CIFS_IOC_COPYCHUNK_FILE	_IOW(CIFS_IOCTL_MAGIC, 3, int)
#define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
#define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
#define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
+123 −0
Original line number Diff line number Diff line
@@ -42,6 +42,35 @@ static const struct cifs_sid sid_authusers = {
/* group users */
static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };

/* S-1-22-1 Unmapped Unix users */
static const struct cifs_sid sid_unix_users = {1, 1, {0, 0, 0, 0, 0, 22},
		{cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };

/* S-1-22-2 Unmapped Unix groups */
static const struct cifs_sid sid_unix_groups = { 1, 1, {0, 0, 0, 0, 0, 22},
		{cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };

/*
 * See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
 */

/* S-1-5-88 MS NFS and Apple style UID/GID/mode */

/* S-1-5-88-1 Unix uid */
static const struct cifs_sid sid_unix_NFS_users = { 1, 2, {0, 0, 0, 0, 0, 5},
	{cpu_to_le32(88),
	 cpu_to_le32(1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };

/* S-1-5-88-2 Unix gid */
static const struct cifs_sid sid_unix_NFS_groups = { 1, 2, {0, 0, 0, 0, 0, 5},
	{cpu_to_le32(88),
	 cpu_to_le32(2), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };

/* S-1-5-88-3 Unix mode */
static const struct cifs_sid sid_unix_NFS_mode = { 1, 2, {0, 0, 0, 0, 0, 5},
	{cpu_to_le32(88),
	 cpu_to_le32(3), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} };

static const struct cred *root_cred;

static int
@@ -183,6 +212,62 @@ compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
	return 0; /* sids compare/match */
}

static bool
is_well_known_sid(const struct cifs_sid *psid, uint32_t *puid, bool is_group)
{
	int i;
	int num_subauth;
	const struct cifs_sid *pwell_known_sid;

	if (!psid || (puid == NULL))
		return false;

	num_subauth = psid->num_subauth;

	/* check if Mac (or Windows NFS) vs. Samba format for Unix owner SID */
	if (num_subauth == 2) {
		if (is_group)
			pwell_known_sid = &sid_unix_groups;
		else
			pwell_known_sid = &sid_unix_users;
	} else if (num_subauth == 3) {
		if (is_group)
			pwell_known_sid = &sid_unix_NFS_groups;
		else
			pwell_known_sid = &sid_unix_NFS_users;
	} else
		return false;

	/* compare the revision */
	if (psid->revision != pwell_known_sid->revision)
		return false;

	/* compare all of the six auth values */
	for (i = 0; i < NUM_AUTHS; ++i) {
		if (psid->authority[i] != pwell_known_sid->authority[i]) {
			cifs_dbg(FYI, "auth %d did not match\n", i);
			return false;
		}
	}

	if (num_subauth == 2) {
		if (psid->sub_auth[0] != pwell_known_sid->sub_auth[0])
			return false;

		*puid = le32_to_cpu(psid->sub_auth[1]);
	} else /* 3 subauths, ie Windows/Mac style */ {
		*puid = le32_to_cpu(psid->sub_auth[0]);
		if ((psid->sub_auth[0] != pwell_known_sid->sub_auth[0]) ||
		    (psid->sub_auth[1] != pwell_known_sid->sub_auth[1]))
			return false;

		*puid = le32_to_cpu(psid->sub_auth[2]);
	}

	cifs_dbg(FYI, "Unix UID %d returned from SID\n", *puid);
	return true; /* well known sid found, uid returned */
}

static void
cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
{
@@ -276,6 +361,43 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
		return -EIO;
	}

	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) {
		uint32_t unix_id;
		bool is_group;

		if (sidtype != SIDOWNER)
			is_group = true;
		else
			is_group = false;

		if (is_well_known_sid(psid, &unix_id, is_group) == false)
			goto try_upcall_to_get_id;

		if (is_group) {
			kgid_t gid;
			gid_t id;

			id = (gid_t)unix_id;
			gid = make_kgid(&init_user_ns, id);
			if (gid_valid(gid)) {
				fgid = gid;
				goto got_valid_id;
			}
		} else {
			kuid_t uid;
			uid_t id;

			id = (uid_t)unix_id;
			uid = make_kuid(&init_user_ns, id);
			if (uid_valid(uid)) {
				fuid = uid;
				goto got_valid_id;
			}
		}
		/* If unable to find uid/gid easily from SID try via upcall */
	}

try_upcall_to_get_id:
	sidstr = sid_to_key_str(psid, sidtype);
	if (!sidstr)
		return -ENOMEM;
@@ -329,6 +451,7 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
	 * Note that we return 0 here unconditionally. If the mapping
	 * fails then we just fall back to using the mnt_uid/mnt_gid.
	 */
got_valid_id:
	if (sidtype == SIDOWNER)
		fattr->cf_uid = fuid;
	else
+6 −5
Original line number Diff line number Diff line
@@ -64,15 +64,15 @@ unsigned int global_secflags = CIFSSEC_DEF;
unsigned int sign_CIFS_PDUs = 1;
static const struct super_operations cifs_super_ops;
unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE;
module_param(CIFSMaxBufSize, uint, 0);
module_param(CIFSMaxBufSize, uint, 0444);
MODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header). "
				 "Default: 16384 Range: 8192 to 130048");
unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL;
module_param(cifs_min_rcv, uint, 0);
module_param(cifs_min_rcv, uint, 0444);
MODULE_PARM_DESC(cifs_min_rcv, "Network buffers in pool. Default: 4 Range: "
				"1 to 64");
unsigned int cifs_min_small = 30;
module_param(cifs_min_small, uint, 0);
module_param(cifs_min_small, uint, 0444);
MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 "
				 "Range: 2 to 256");
unsigned int cifs_max_pending = CIFS_MAX_REQ;
@@ -271,7 +271,7 @@ cifs_alloc_inode(struct super_block *sb)
	cifs_inode->createtime = 0;
	cifs_inode->epoch = 0;
#ifdef CONFIG_CIFS_SMB2
	get_random_bytes(cifs_inode->lease_key, SMB2_LEASE_KEY_SIZE);
	generate_random_uuid(cifs_inode->lease_key);
#endif
	/*
	 * Can not set i_flags here - they get immediately overwritten to zero
@@ -469,6 +469,8 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
		seq_puts(s, ",posixpaths");
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)
		seq_puts(s, ",setuids");
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
		seq_puts(s, ",idsfromsid");
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
		seq_puts(s, ",serverino");
	if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD)
@@ -1262,7 +1264,6 @@ init_cifs(void)
	GlobalTotalActiveXid = 0;
	GlobalMaxActiveXid = 0;
	spin_lock_init(&cifs_tcp_ses_lock);
	spin_lock_init(&cifs_file_list_lock);
	spin_lock_init(&GlobalMid_Lock);

	get_random_bytes(&cifs_lock_secret, sizeof(cifs_lock_secret));
Loading