ksmbd: add per-share SMB3 encryption enforcement

Add a share flag for requiring SMB3 encryption on an individual share.

Advertise SMB2_SHAREFLAG_ENCRYPT_DATA in TREE_CONNECT responses and
reject both unencrypted TREE_CONNECT attempts and plaintext requests for
shares carrying the flag.

Keep BIT(19) reserved for the existing ksmbd-tools WIDE_LINKS flag and
use BIT(20) for the new netlink ABI flag.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
Namjae Jeon 2026-08-16 09:33:41 +09:00
parent abe5acb342
commit 50a400cff5
5 changed files with 34 additions and 5 deletions

View File

@ -370,7 +370,8 @@ struct smb2_tree_connect_req {
#define SMB2_SHAREFLAG_FORCE_LEVELII_OPLOCK 0x00001000
#define SMB2_SHAREFLAG_ENABLE_HASH_V1 0x00002000
#define SMB2_SHAREFLAG_ENABLE_HASH_V2 0x00004000
#define SHI1005_FLAGS_ENCRYPT_DATA 0x00008000
#define SMB2_SHAREFLAG_ENCRYPT_DATA 0x00008000
#define SHI1005_FLAGS_ENCRYPT_DATA SMB2_SHAREFLAG_ENCRYPT_DATA
#define SMB2_SHAREFLAG_IDENTITY_REMOTING 0x00040000 /* 3.1.1 */
#define SMB2_SHAREFLAG_COMPRESS_DATA 0x00100000 /* 3.1.1 */
#define SMB2_SHAREFLAG_ISOLATED_TRANSPORT 0x00200000

View File

@ -381,6 +381,8 @@ enum KSMBD_TREE_CONN_STATUS {
#define KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY BIT(16)
#define KSMBD_SHARE_FLAG_HIDE_UNREADABLE BIT(17)
#define KSMBD_SHARE_FLAG_TIME_MACHINE BIT(18)
/* Keep BIT(19) reserved for the existing ksmbd-tools WIDE_LINKS flag. */
#define KSMBD_SHARE_FLAG_ENCRYPT_DATA BIT(20)
/*
* Tree connect request flags.

View File

@ -47,6 +47,7 @@ static const struct ksmbd_const_name ksmbd_share_flag_names[] = {
{KSMBD_SHARE_FLAG_UPDATE, "update"},
{KSMBD_SHARE_FLAG_CROSSMNT, "crossmnt"},
{KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY, "continuous-availability"},
{KSMBD_SHARE_FLAG_ENCRYPT_DATA, "encrypt-data"},
};
static int proc_show_shares(struct seq_file *m, void *v)

View File

@ -24,6 +24,8 @@
#include "auth.h"
#include "stats.h"
#include "compress.h"
#include "mgmt/share_config.h"
#include "mgmt/tree_connect.h"
int ksmbd_debug_types;
@ -236,6 +238,15 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
STATUS_NETWORK_NAME_DELETED);
goto send;
}
if (work->tcon &&
test_share_config_flag(work->tcon->share_conf,
KSMBD_SHARE_FLAG_ENCRYPT_DATA) &&
!work->encrypted) {
conn->ops->set_rsp_status(work,
STATUS_ACCESS_DENIED);
goto send;
}
}
}

View File

@ -2636,12 +2636,22 @@ int smb2_tree_connect(struct ksmbd_work *work)
name, treename);
status = ksmbd_tree_conn_connect(work, name);
if (status.ret == KSMBD_TREE_CONN_STATUS_OK)
if (status.ret == KSMBD_TREE_CONN_STATUS_OK) {
rsp->hdr.Id.SyncId.TreeId = cpu_to_le32(status.tree_conn->id);
else
share = status.tree_conn->share_conf;
/* A share that requires encryption needs a negotiated SMB3 cipher. */
if (test_share_config_flag(share, KSMBD_SHARE_FLAG_ENCRYPT_DATA) &&
!smb3_encryption_negotiated(conn)) {
ksmbd_tree_conn_disconnect(sess, status.tree_conn);
status.tree_conn = NULL;
share = NULL;
status.ret = KSMBD_TREE_CONN_STATUS_ERROR;
goto out_err1;
}
} else
goto out_err1;
share = status.tree_conn->share_conf;
if (test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
ksmbd_debug(SMB, "IPC share path request\n");
rsp->ShareType = SMB2_SHARE_TYPE_PIPE;
@ -2687,9 +2697,13 @@ int smb2_tree_connect(struct ksmbd_work *work)
conn->compress_algorithm != SMB3_COMPRESS_NONE)
rsp->ShareFlags |= cpu_to_le32(SMB2_SHAREFLAG_COMPRESS_DATA);
if (share && test_share_config_flag(share,
KSMBD_SHARE_FLAG_HIDE_UNREADABLE))
KSMBD_SHARE_FLAG_HIDE_UNREADABLE))
rsp->ShareFlags |=
cpu_to_le32(SMB2_SHAREFLAG_ACCESS_BASED_DIRECTORY_ENUM);
if (share && test_share_config_flag(share,
KSMBD_SHARE_FLAG_ENCRYPT_DATA))
rsp->ShareFlags |=
cpu_to_le32(SMB2_SHAREFLAG_ENCRYPT_DATA);
rc = ksmbd_iov_pin_rsp(work, rsp, sizeof(struct smb2_tree_connect_rsp));
if (rc) {