Skip to content

Commit

Permalink
Merge tag '6.1-rc-ksmbd-fixes' of git://git.samba.org/ksmbd
Browse files Browse the repository at this point in the history
Pull ksmbd updates from Steve French:

 - RDMA (smbdirect) fixes

 - fixes for SMB3.1.1 POSIX Extensions (especially for id mapping)

 - various casemapping fixes for mount and lookup

 - UID mapping fixes

 - fix confusing error message

 - protocol negotiation fixes, including NTLMSSP fix

 - two encryption fixes

 - directory listing fix

 - some cleanup fixes

* tag '6.1-rc-ksmbd-fixes' of git://git.samba.org/ksmbd: (24 commits)
  ksmbd: validate share name from share config response
  ksmbd: call ib_drain_qp when disconnected
  ksmbd: make utf-8 file name comparison work in __caseless_lookup()
  ksmbd: Fix user namespace mapping
  ksmbd: hide socket error message when ipv6 config is disable
  ksmbd: reduce server smbdirect max send/receive segment sizes
  ksmbd: decrease the number of SMB3 smbdirect server SGEs
  ksmbd: Fix wrong return value and message length check in smb2_ioctl()
  ksmbd: set NTLMSSP_NEGOTIATE_SEAL flag to challenge blob
  ksmbd: fix encryption failure issue for session logoff response
  ksmbd: fix endless loop when encryption for response fails
  ksmbd: fill sids in SMB_FIND_FILE_POSIX_INFO response
  ksmbd: set file permission mode to match Samba server posix extension behavior
  ksmbd: change security id to the one samba used for posix extension
  ksmbd: update documentation
  ksmbd: casefold utf-8 share names and fix ascii lowercase conversion
  ksmbd: port to vfs{g,u}id_t and associated helpers
  ksmbd: fix incorrect handling of iterate_dir
  MAINTAINERS: remove Hyunchul Lee from ksmbd maintainers
  MAINTAINERS: Add Tom Talpey as ksmbd reviewer
  ...
  • Loading branch information
Linus Torvalds committed Oct 7, 2022
2 parents 4c86114 + f5ba1cd commit 9f4b9be
Show file tree
Hide file tree
Showing 26 changed files with 284 additions and 152 deletions.
42 changes: 30 additions & 12 deletions Documentation/filesystems/cifs/ksmbd.rst
Original file line number Diff line number Diff line change
Expand Up @@ -118,26 +118,44 @@ ksmbd/nfsd interoperability Planned for future. The features that ksmbd
How to run
==========

1. Download ksmbd-tools and compile them.
- https://github.com/cifsd-team/ksmbd-tools
1. Download ksmbd-tools(https://github.com/cifsd-team/ksmbd-tools/releases) and
compile them.

2. Create user/password for SMB share.
- Refer README(https://github.com/cifsd-team/ksmbd-tools/blob/master/README.md)
to know how to use ksmbd.mountd/adduser/addshare/control utils

# mkdir /etc/ksmbd/
# ksmbd.adduser -a <Enter USERNAME for SMB share access>
$ ./autogen.sh
$ ./configure --with-rundir=/run
$ make && sudo make install

3. Create /etc/ksmbd/smb.conf file, add SMB share in smb.conf file
- Refer smb.conf.example and
https://github.com/cifsd-team/ksmbd-tools/blob/master/Documentation/configuration.txt
2. Create /usr/local/etc/ksmbd/ksmbd.conf file, add SMB share in ksmbd.conf file.

4. Insert ksmbd.ko module
- Refer ksmbd.conf.example in ksmbd-utils, See ksmbd.conf manpage
for details to configure shares.

# insmod ksmbd.ko
$ man ksmbd.conf

3. Create user/password for SMB share.

- See ksmbd.adduser manpage.

$ man ksmbd.adduser
$ sudo ksmbd.adduser -a <Enter USERNAME for SMB share access>

4. Insert ksmbd.ko module after build your kernel. No need to load module
if ksmbd is built into the kernel.

- Set ksmbd in menuconfig(e.g. $ make menuconfig)
[*] Network File Systems --->
<M> SMB3 server support (EXPERIMENTAL)

$ sudo modprobe ksmbd.ko

5. Start ksmbd user space daemon
# ksmbd.mountd

6. Access share from Windows or Linux using CIFS
$ sudo ksmbd.mountd

6. Access share from Windows or Linux using SMB3 client (cifs.ko or smbclient of samba)

Shutdown KSMBD
==============
Expand Down
2 changes: 1 addition & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -11101,8 +11101,8 @@ F: tools/testing/selftests/
KERNEL SMB3 SERVER (KSMBD)
M: Namjae Jeon <linkinjeon@kernel.org>
M: Steve French <sfrench@samba.org>
M: Hyunchul Lee <hyc.lee@gmail.com>
R: Sergey Senozhatsky <senozhatsky@chromium.org>
R: Tom Talpey <tom@talpey.com>
L: linux-cifs@vger.kernel.org
S: Maintained
T: git git://git.samba.org/ksmbd.git
Expand Down
15 changes: 11 additions & 4 deletions fs/ksmbd/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,9 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
NTLMSSP_NEGOTIATE_56);
}

if (cflags & NTLMSSP_NEGOTIATE_SEAL && smb3_encryption_negotiated(conn))
flags |= NTLMSSP_NEGOTIATE_SEAL;

if (cflags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;

Expand Down Expand Up @@ -984,13 +987,16 @@ int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len,
return rc;
}

static int ksmbd_get_encryption_key(struct ksmbd_conn *conn, __u64 ses_id,
static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,
int enc, u8 *key)
{
struct ksmbd_session *sess;
u8 *ses_enc_key;

sess = ksmbd_session_lookup_all(conn, ses_id);
if (enc)
sess = work->sess;
else
sess = ksmbd_session_lookup_all(work->conn, ses_id);
if (!sess)
return -EINVAL;

Expand Down Expand Up @@ -1078,9 +1084,10 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
return sg;
}

int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
unsigned int nvec, int enc)
{
struct ksmbd_conn *conn = work->conn;
struct smb2_transform_hdr *tr_hdr = smb2_get_msg(iov[0].iov_base);
unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
int rc;
Expand All @@ -1094,7 +1101,7 @@ int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
struct ksmbd_crypto_ctx *ctx;

rc = ksmbd_get_encryption_key(conn,
rc = ksmbd_get_encryption_key(work,
le64_to_cpu(tr_hdr->SessionId),
enc,
key);
Expand Down
3 changes: 2 additions & 1 deletion fs/ksmbd/auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@

struct ksmbd_session;
struct ksmbd_conn;
struct ksmbd_work;
struct kvec;

int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
unsigned int nvec, int enc);
void ksmbd_copy_gss_neg_header(void *buf);
int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
Expand Down
8 changes: 8 additions & 0 deletions fs/ksmbd/connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
conn->local_nls = load_nls("utf8");
if (!conn->local_nls)
conn->local_nls = load_nls_default();
if (IS_ENABLED(CONFIG_UNICODE))
conn->um = utf8_load(UNICODE_AGE(12, 1, 0));
else
conn->um = ERR_PTR(-EOPNOTSUPP);
if (IS_ERR(conn->um))
conn->um = NULL;
atomic_set(&conn->req_running, 0);
atomic_set(&conn->r_count, 0);
conn->total_credits = 1;
Expand Down Expand Up @@ -350,6 +356,8 @@ int ksmbd_conn_handler_loop(void *p)
wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);


if (IS_ENABLED(CONFIG_UNICODE))
utf8_unload(conn->um);
unload_nls(conn->local_nls);
if (default_conn_ops.terminate_fn)
default_conn_ops.terminate_fn(conn);
Expand Down
2 changes: 2 additions & 0 deletions fs/ksmbd/connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <net/request_sock.h>
#include <linux/kthread.h>
#include <linux/nls.h>
#include <linux/unicode.h>

#include "smb_common.h"
#include "ksmbd_work.h"
Expand Down Expand Up @@ -46,6 +47,7 @@ struct ksmbd_conn {
char *request_buf;
struct ksmbd_transport *transport;
struct nls_table *local_nls;
struct unicode_map *um;
struct list_head conns_list;
/* smb session 1 per user */
struct xarray sessions;
Expand Down
3 changes: 2 additions & 1 deletion fs/ksmbd/ksmbd_netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ struct ksmbd_share_config_response {
__u16 force_directory_mode;
__u16 force_uid;
__u16 force_gid;
__u32 reserved[128]; /* Reserved room */
__s8 share_name[KSMBD_REQ_MAX_SHARE_NAME];
__u32 reserved[112]; /* Reserved room */
__u32 veto_list_sz;
__s8 ____payload[];
};
Expand Down
36 changes: 21 additions & 15 deletions fs/ksmbd/mgmt/share_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "user_config.h"
#include "user_session.h"
#include "../transport_ipc.h"
#include "../misc.h"

#define SHARE_HASH_BITS 3
static DEFINE_HASHTABLE(shares_table, SHARE_HASH_BITS);
Expand All @@ -26,7 +27,7 @@ struct ksmbd_veto_pattern {
struct list_head list;
};

static unsigned int share_name_hash(char *name)
static unsigned int share_name_hash(const char *name)
{
return jhash(name, strlen(name), 0);
}
Expand Down Expand Up @@ -72,7 +73,7 @@ __get_share_config(struct ksmbd_share_config *share)
return share;
}

static struct ksmbd_share_config *__share_lookup(char *name)
static struct ksmbd_share_config *__share_lookup(const char *name)
{
struct ksmbd_share_config *share;
unsigned int key = share_name_hash(name);
Expand Down Expand Up @@ -119,7 +120,8 @@ static int parse_veto_list(struct ksmbd_share_config *share,
return 0;
}

static struct ksmbd_share_config *share_config_request(char *name)
static struct ksmbd_share_config *share_config_request(struct unicode_map *um,
const char *name)
{
struct ksmbd_share_config_response *resp;
struct ksmbd_share_config *share = NULL;
Expand All @@ -133,6 +135,19 @@ static struct ksmbd_share_config *share_config_request(char *name)
if (resp->flags == KSMBD_SHARE_FLAG_INVALID)
goto out;

if (*resp->share_name) {
char *cf_resp_name;
bool equal;

cf_resp_name = ksmbd_casefold_sharename(um, resp->share_name);
if (IS_ERR(cf_resp_name))
goto out;
equal = !strcmp(cf_resp_name, name);
kfree(cf_resp_name);
if (!equal)
goto out;
}

share = kzalloc(sizeof(struct ksmbd_share_config), GFP_KERNEL);
if (!share)
goto out;
Expand Down Expand Up @@ -190,20 +205,11 @@ static struct ksmbd_share_config *share_config_request(char *name)
return share;
}

static void strtolower(char *share_name)
{
while (*share_name) {
*share_name = tolower(*share_name);
share_name++;
}
}

struct ksmbd_share_config *ksmbd_share_config_get(char *name)
struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um,
const char *name)
{
struct ksmbd_share_config *share;

strtolower(name);

down_read(&shares_table_lock);
share = __share_lookup(name);
if (share)
Expand All @@ -212,7 +218,7 @@ struct ksmbd_share_config *ksmbd_share_config_get(char *name)

if (share)
return share;
return share_config_request(name);
return share_config_request(um, name);
}

bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
Expand Down
4 changes: 3 additions & 1 deletion fs/ksmbd/mgmt/share_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <linux/workqueue.h>
#include <linux/hashtable.h>
#include <linux/path.h>
#include <linux/unicode.h>

struct ksmbd_share_config {
char *name;
Expand Down Expand Up @@ -74,7 +75,8 @@ static inline void ksmbd_share_config_put(struct ksmbd_share_config *share)
__ksmbd_share_config_put(share);
}

struct ksmbd_share_config *ksmbd_share_config_get(char *name);
struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um,
const char *name);
bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
const char *filename);
#endif /* __SHARE_CONFIG_MANAGEMENT_H__ */
6 changes: 3 additions & 3 deletions fs/ksmbd/mgmt/tree_connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

struct ksmbd_tree_conn_status
ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
char *share_name)
const char *share_name)
{
struct ksmbd_tree_conn_status status = {-ENOENT, NULL};
struct ksmbd_tree_connect_response *resp = NULL;
Expand All @@ -26,7 +26,7 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
struct sockaddr *peer_addr;
int ret;

sc = ksmbd_share_config_get(share_name);
sc = ksmbd_share_config_get(conn->um, share_name);
if (!sc)
return status;

Expand Down Expand Up @@ -61,7 +61,7 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
struct ksmbd_share_config *new_sc;

ksmbd_share_config_del(sc);
new_sc = ksmbd_share_config_get(share_name);
new_sc = ksmbd_share_config_get(conn->um, share_name);
if (!new_sc) {
pr_err("Failed to update stale share config\n");
status.ret = -ESTALE;
Expand Down
2 changes: 1 addition & 1 deletion fs/ksmbd/mgmt/tree_connect.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ struct ksmbd_session;

struct ksmbd_tree_conn_status
ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
char *share_name);
const char *share_name);

int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
struct ksmbd_tree_connect *tree_conn);
Expand Down
46 changes: 37 additions & 9 deletions fs/ksmbd/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/xattr.h>
#include <linux/fs.h>
#include <linux/unicode.h>

#include "misc.h"
#include "smb_common.h"
Expand Down Expand Up @@ -159,7 +160,7 @@ int parse_stream_name(char *filename, char **stream_name, int *s_type)
*/

char *convert_to_nt_pathname(struct ksmbd_share_config *share,
struct path *path)
const struct path *path)
{
char *pathname, *ab_pathname, *nt_pathname;
int share_path_len = share->path_sz;
Expand Down Expand Up @@ -226,26 +227,53 @@ void ksmbd_conv_path_to_windows(char *path)
strreplace(path, '/', '\\');
}

char *ksmbd_casefold_sharename(struct unicode_map *um, const char *name)
{
char *cf_name;
int cf_len;

cf_name = kzalloc(KSMBD_REQ_MAX_SHARE_NAME, GFP_KERNEL);
if (!cf_name)
return ERR_PTR(-ENOMEM);

if (IS_ENABLED(CONFIG_UNICODE) && um) {
const struct qstr q_name = {.name = name, .len = strlen(name)};

cf_len = utf8_casefold(um, &q_name, cf_name,
KSMBD_REQ_MAX_SHARE_NAME);
if (cf_len < 0)
goto out_ascii;

return cf_name;
}

out_ascii:
cf_len = strscpy(cf_name, name, KSMBD_REQ_MAX_SHARE_NAME);
if (cf_len < 0) {
kfree(cf_name);
return ERR_PTR(-E2BIG);
}

for (; *cf_name; ++cf_name)
*cf_name = isascii(*cf_name) ? tolower(*cf_name) : *cf_name;
return cf_name - cf_len;
}

/**
* ksmbd_extract_sharename() - get share name from tree connect request
* @treename: buffer containing tree name and share name
*
* Return: share name on success, otherwise error
*/
char *ksmbd_extract_sharename(char *treename)
char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename)
{
char *name = treename;
char *dst;
char *pos = strrchr(name, '\\');
const char *name = treename, *pos = strrchr(name, '\\');

if (pos)
name = (pos + 1);

/* caller has to free the memory */
dst = kstrdup(name, GFP_KERNEL);
if (!dst)
return ERR_PTR(-ENOMEM);
return dst;
return ksmbd_casefold_sharename(um, name);
}

/**
Expand Down
Loading

0 comments on commit 9f4b9be

Please sign in to comment.