Commit 558c3eca authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'v7.1-rc5-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:
 - Fix missing lock
 - Fix dentry in use after unmounting
 - cifs.upcall security fix
 - require CAP_NET_ADMIN for swn netlink
 - change allocation in DUP_CTX_STR to GFP_KERNEL
 - minor smbdirect debug fix
 - handle_read_data() folio fix

* tag 'v7.1-rc5-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  smb: client: change allocation requirements in DUP_CTX_STR macro
  smb: client: require net admin for CIFS SWN netlink
  smb: smbdirect: divide, not multiply, milliseconds by 1000
  cifs: Fix busy dentry used after unmounting
  smb: client: use data_len for SMB2 READ encrypted folioq copy
  smb: client: reject userspace cifs.spnego descriptions
  smb: client: protect tc_count increment in smb2_find_smb_sess_tcon_unlocked()
parents 632360e8 dcd4313f
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
 */

#include <linux/list.h>
#include <linux/cred.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <keys/user-type.h>
@@ -40,12 +41,27 @@ cifs_spnego_key_destroy(struct key *key)
	kfree(key->payload.data[0]);
}

static int
cifs_spnego_key_vet_description(const char *description)
{
	/*
	 * cifs.spnego descriptions are authority-bearing inputs to cifs.upcall.
	 * They are only valid when produced by CIFS while using the private
	 * spnego_cred installed below.  Do not let userspace create this type
	 * of key through request_key(2)/add_key(2), since the helper treats
	 * pid/uid/creduid/upcall_target as kernel-originating fields.
	 */
	if (current_cred() != spnego_cred)
		return -EPERM;
	return 0;
}

/*
 * keytype for CIFS spnego keys
 */
struct key_type cifs_spnego_key_type = {
	.name		= "cifs.spnego",
	.vet_description = cifs_spnego_key_vet_description,
	.instantiate	= cifs_spnego_key_instantiate,
	.destroy	= cifs_spnego_key_destroy,
	.describe	= user_describe,
+2 −0
Original line number Diff line number Diff line
@@ -306,6 +306,8 @@ static void cifs_kill_sb(struct super_block *sb)

		/* Wait for all pending oplock breaks to complete */
		flush_workqueue(cifsoplockd_wq);
		/* Wait for all opened files to release */
		flush_workqueue(deferredclose_wq);

		/* finally release root dentry */
		dput(cifs_sb->root);
+1 −1
Original line number Diff line number Diff line
@@ -420,7 +420,7 @@ static int parse_symlink_flavor(struct fs_context *fc, char *value,
#define DUP_CTX_STR(field)						\
do {									\
	if (ctx->field) {						\
		new_ctx->field = kstrdup(ctx->field, GFP_ATOMIC);	\
		new_ctx->field = kstrdup(ctx->field, GFP_KERNEL);	\
		if (new_ctx->field == NULL) {				\
			smb3_cleanup_fs_context_contents(new_ctx);	\
			return -ENOMEM;					\
+5 −1
Original line number Diff line number Diff line
@@ -33,13 +33,17 @@ static const struct nla_policy cifs_genl_policy[CIFS_GENL_ATTR_MAX + 1] = {
static const struct genl_ops cifs_genl_ops[] = {
	{
		.cmd = CIFS_GENL_CMD_SWN_NOTIFY,
		.flags = GENL_ADMIN_PERM,
		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
		.doit = cifs_swn_notify,
	},
};

static const struct genl_multicast_group cifs_genl_mcgrps[] = {
	[CIFS_GENL_MCGRP_SWN] = { .name = CIFS_GENL_MCGRP_SWN_NAME },
	[CIFS_GENL_MCGRP_SWN] = {
		.name = CIFS_GENL_MCGRP_SWN_NAME,
		.flags = GENL_MCAST_CAP_NET_ADMIN,
	},
};

struct genl_family cifs_genl_family = {
+2 −2
Original line number Diff line number Diff line
@@ -4836,7 +4836,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
		}

		/* Copy the data to the output I/O iterator. */
		rdata->result = cifs_copy_folioq_to_iter(buffer, buffer_len,
		rdata->result = cifs_copy_folioq_to_iter(buffer, data_len,
							 cur_off, &rdata->subreq.io_iter);
		if (rdata->result != 0) {
			if (is_offloaded)
@@ -4845,7 +4845,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
				dequeue_mid(server, mid, rdata->result);
			return 0;
		}
		rdata->got_bytes = buffer_len;
		rdata->got_bytes = data_len;

	} else if (!check_add_overflow(data_offset, data_len, &end_off) &&
		   buf_len >= end_off) {
Loading