summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-05-22 10:52:26 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-05-22 10:52:26 -0700
commit558c3eca715ea0110fe6fce38b063a6f9936188c (patch)
treec3ef3073c7b18bd51fe30cd95833d4fd3a63a66e /fs
parent632360e8f5fce2eee720e952fd84e8cefb5749b6 (diff)
parentdcd4313f0987d69c4134c12bbe3a8cdf795f6c1e (diff)
downloadlinux-next-558c3eca715ea0110fe6fce38b063a6f9936188c.tar.gz
linux-next-558c3eca715ea0110fe6fce38b063a6f9936188c.zip
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()
Diffstat (limited to 'fs')
-rw-r--r--fs/smb/client/cifs_spnego.c16
-rw-r--r--fs/smb/client/cifsfs.c2
-rw-r--r--fs/smb/client/fs_context.c2
-rw-r--r--fs/smb/client/netlink.c6
-rw-r--r--fs/smb/client/smb2ops.c4
-rw-r--r--fs/smb/client/smb2transport.c2
-rw-r--r--fs/smb/smbdirect/debug.c2
7 files changed, 29 insertions, 5 deletions
diff --git a/fs/smb/client/cifs_spnego.c b/fs/smb/client/cifs_spnego.c
index 3a41bbada04c..44c407275680 100644
--- a/fs/smb/client/cifs_spnego.c
+++ b/fs/smb/client/cifs_spnego.c
@@ -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,
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index f557eb7875c7..ce23924f01b3 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -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);
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
index 4c8b1b9ade8b..2f86158f85d7 100644
--- a/fs/smb/client/fs_context.c
+++ b/fs/smb/client/fs_context.c
@@ -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; \
diff --git a/fs/smb/client/netlink.c b/fs/smb/client/netlink.c
index 147d9409252c..0dd10913c37a 100644
--- a/fs/smb/client/netlink.c
+++ b/fs/smb/client/netlink.c
@@ -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 = {
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 189bb863a9af..61b60114e4b8 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -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) {
diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c
index e8eeff9e50d6..1143ee52470a 100644
--- a/fs/smb/client/smb2transport.c
+++ b/fs/smb/client/smb2transport.c
@@ -169,7 +169,9 @@ smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid)
list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
if (tcon->tid != tid)
continue;
+ spin_lock(&tcon->tc_lock);
++tcon->tc_count;
+ spin_unlock(&tcon->tc_lock);
trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
netfs_trace_tcon_ref_get_find_sess_tcon);
return tcon;
diff --git a/fs/smb/smbdirect/debug.c b/fs/smb/smbdirect/debug.c
index 05ba7c8d165e..3445843445bf 100644
--- a/fs/smb/smbdirect/debug.c
+++ b/fs/smb/smbdirect/debug.c
@@ -40,7 +40,7 @@ void smbdirect_connection_legacy_debug_proc_show(struct smbdirect_socket *sc,
seq_puts(m, "\n");
seq_printf(m, "Conn keep_alive_interval: %u ",
- sp->keepalive_interval_msec * 1000);
+ sp->keepalive_interval_msec / 1000);
seq_printf(m, "max_readwrite_size: %u rdma_readwrite_threshold: %u",
sp->max_read_write_size,
rdma_readwrite_threshold);