Commit 9f4b9bee authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '6.1-rc-ksmbd-fixes' of git://git.samba.org/ksmbd

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
  ...
parents 4c861141 f5ba1cda
...@@ -118,26 +118,44 @@ ksmbd/nfsd interoperability Planned for future. The features that ksmbd ...@@ -118,26 +118,44 @@ ksmbd/nfsd interoperability Planned for future. The features that ksmbd
How to run How to run
========== ==========
1. Download ksmbd-tools and compile them. 1. Download ksmbd-tools(https://github.com/cifsd-team/ksmbd-tools/releases) and
- https://github.com/cifsd-team/ksmbd-tools 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/ $ ./autogen.sh
# ksmbd.adduser -a <Enter USERNAME for SMB share access> $ ./configure --with-rundir=/run
$ make && sudo make install
3. Create /etc/ksmbd/smb.conf file, add SMB share in smb.conf file 2. Create /usr/local/etc/ksmbd/ksmbd.conf file, add SMB share in ksmbd.conf file.
- Refer smb.conf.example and
https://github.com/cifsd-team/ksmbd-tools/blob/master/Documentation/configuration.txt
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 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 Shutdown KSMBD
============== ==============
......
...@@ -11101,8 +11101,8 @@ F: tools/testing/selftests/ ...@@ -11101,8 +11101,8 @@ F: tools/testing/selftests/
KERNEL SMB3 SERVER (KSMBD) KERNEL SMB3 SERVER (KSMBD)
M: Namjae Jeon <linkinjeon@kernel.org> M: Namjae Jeon <linkinjeon@kernel.org>
M: Steve French <sfrench@samba.org> M: Steve French <sfrench@samba.org>
M: Hyunchul Lee <hyc.lee@gmail.com>
R: Sergey Senozhatsky <senozhatsky@chromium.org> R: Sergey Senozhatsky <senozhatsky@chromium.org>
R: Tom Talpey <tom@talpey.com>
L: linux-cifs@vger.kernel.org L: linux-cifs@vger.kernel.org
S: Maintained S: Maintained
T: git git://git.samba.org/ksmbd.git T: git git://git.samba.org/ksmbd.git
......
...@@ -424,6 +424,9 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob, ...@@ -424,6 +424,9 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
NTLMSSP_NEGOTIATE_56); NTLMSSP_NEGOTIATE_56);
} }
if (cflags & NTLMSSP_NEGOTIATE_SEAL && smb3_encryption_negotiated(conn))
flags |= NTLMSSP_NEGOTIATE_SEAL;
if (cflags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) if (cflags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN)
flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
...@@ -984,13 +987,16 @@ int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len, ...@@ -984,13 +987,16 @@ int ksmbd_gen_sd_hash(struct ksmbd_conn *conn, char *sd_buf, int len,
return rc; 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) int enc, u8 *key)
{ {
struct ksmbd_session *sess; struct ksmbd_session *sess;
u8 *ses_enc_key; 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) if (!sess)
return -EINVAL; return -EINVAL;
...@@ -1078,9 +1084,10 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec, ...@@ -1078,9 +1084,10 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
return sg; 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) unsigned int nvec, int enc)
{ {
struct ksmbd_conn *conn = work->conn;
struct smb2_transform_hdr *tr_hdr = smb2_get_msg(iov[0].iov_base); struct smb2_transform_hdr *tr_hdr = smb2_get_msg(iov[0].iov_base);
unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20; unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
int rc; int rc;
...@@ -1094,7 +1101,7 @@ int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov, ...@@ -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); unsigned int crypt_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
struct ksmbd_crypto_ctx *ctx; struct ksmbd_crypto_ctx *ctx;
rc = ksmbd_get_encryption_key(conn, rc = ksmbd_get_encryption_key(work,
le64_to_cpu(tr_hdr->SessionId), le64_to_cpu(tr_hdr->SessionId),
enc, enc,
key); key);
......
...@@ -33,9 +33,10 @@ ...@@ -33,9 +33,10 @@
struct ksmbd_session; struct ksmbd_session;
struct ksmbd_conn; struct ksmbd_conn;
struct ksmbd_work;
struct kvec; 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); unsigned int nvec, int enc);
void ksmbd_copy_gss_neg_header(void *buf); void ksmbd_copy_gss_neg_header(void *buf);
int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess, int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
......
...@@ -60,6 +60,12 @@ struct ksmbd_conn *ksmbd_conn_alloc(void) ...@@ -60,6 +60,12 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
conn->local_nls = load_nls("utf8"); conn->local_nls = load_nls("utf8");
if (!conn->local_nls) if (!conn->local_nls)
conn->local_nls = load_nls_default(); 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->req_running, 0);
atomic_set(&conn->r_count, 0); atomic_set(&conn->r_count, 0);
conn->total_credits = 1; conn->total_credits = 1;
...@@ -350,6 +356,8 @@ int ksmbd_conn_handler_loop(void *p) ...@@ -350,6 +356,8 @@ int ksmbd_conn_handler_loop(void *p)
wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0); 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); unload_nls(conn->local_nls);
if (default_conn_ops.terminate_fn) if (default_conn_ops.terminate_fn)
default_conn_ops.terminate_fn(conn); default_conn_ops.terminate_fn(conn);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <net/request_sock.h> #include <net/request_sock.h>
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/nls.h> #include <linux/nls.h>
#include <linux/unicode.h>
#include "smb_common.h" #include "smb_common.h"
#include "ksmbd_work.h" #include "ksmbd_work.h"
...@@ -46,6 +47,7 @@ struct ksmbd_conn { ...@@ -46,6 +47,7 @@ struct ksmbd_conn {
char *request_buf; char *request_buf;
struct ksmbd_transport *transport; struct ksmbd_transport *transport;
struct nls_table *local_nls; struct nls_table *local_nls;
struct unicode_map *um;
struct list_head conns_list; struct list_head conns_list;
/* smb session 1 per user */ /* smb session 1 per user */
struct xarray sessions; struct xarray sessions;
......
...@@ -163,7 +163,8 @@ struct ksmbd_share_config_response { ...@@ -163,7 +163,8 @@ struct ksmbd_share_config_response {
__u16 force_directory_mode; __u16 force_directory_mode;
__u16 force_uid; __u16 force_uid;
__u16 force_gid; __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; __u32 veto_list_sz;
__s8 ____payload[]; __s8 ____payload[];
}; };
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "user_config.h" #include "user_config.h"
#include "user_session.h" #include "user_session.h"
#include "../transport_ipc.h" #include "../transport_ipc.h"
#include "../misc.h"
#define SHARE_HASH_BITS 3 #define SHARE_HASH_BITS 3
static DEFINE_HASHTABLE(shares_table, SHARE_HASH_BITS); static DEFINE_HASHTABLE(shares_table, SHARE_HASH_BITS);
...@@ -26,7 +27,7 @@ struct ksmbd_veto_pattern { ...@@ -26,7 +27,7 @@ struct ksmbd_veto_pattern {
struct list_head list; 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); return jhash(name, strlen(name), 0);
} }
...@@ -72,7 +73,7 @@ __get_share_config(struct ksmbd_share_config *share) ...@@ -72,7 +73,7 @@ __get_share_config(struct ksmbd_share_config *share)
return 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; struct ksmbd_share_config *share;
unsigned int key = share_name_hash(name); unsigned int key = share_name_hash(name);
...@@ -119,7 +120,8 @@ static int parse_veto_list(struct ksmbd_share_config *share, ...@@ -119,7 +120,8 @@ static int parse_veto_list(struct ksmbd_share_config *share,
return 0; 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_response *resp;
struct ksmbd_share_config *share = NULL; struct ksmbd_share_config *share = NULL;
...@@ -133,6 +135,19 @@ static struct ksmbd_share_config *share_config_request(char *name) ...@@ -133,6 +135,19 @@ static struct ksmbd_share_config *share_config_request(char *name)
if (resp->flags == KSMBD_SHARE_FLAG_INVALID) if (resp->flags == KSMBD_SHARE_FLAG_INVALID)
goto out; 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); share = kzalloc(sizeof(struct ksmbd_share_config), GFP_KERNEL);
if (!share) if (!share)
goto out; goto out;
...@@ -190,20 +205,11 @@ static struct ksmbd_share_config *share_config_request(char *name) ...@@ -190,20 +205,11 @@ static struct ksmbd_share_config *share_config_request(char *name)
return share; return share;
} }
static void strtolower(char *share_name) struct ksmbd_share_config *ksmbd_share_config_get(struct unicode_map *um,
{ const char *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 *share; struct ksmbd_share_config *share;
strtolower(name);
down_read(&shares_table_lock); down_read(&shares_table_lock);
share = __share_lookup(name); share = __share_lookup(name);
if (share) if (share)
...@@ -212,7 +218,7 @@ struct ksmbd_share_config *ksmbd_share_config_get(char *name) ...@@ -212,7 +218,7 @@ struct ksmbd_share_config *ksmbd_share_config_get(char *name)
if (share) if (share)
return share; return share;
return share_config_request(name); return share_config_request(um, name);
} }
bool ksmbd_share_veto_filename(struct ksmbd_share_config *share, bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <linux/hashtable.h> #include <linux/hashtable.h>
#include <linux/path.h> #include <linux/path.h>
#include <linux/unicode.h>
struct ksmbd_share_config { struct ksmbd_share_config {
char *name; char *name;
...@@ -74,7 +75,8 @@ static inline void ksmbd_share_config_put(struct ksmbd_share_config *share) ...@@ -74,7 +75,8 @@ static inline void ksmbd_share_config_put(struct ksmbd_share_config *share)
__ksmbd_share_config_put(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, bool ksmbd_share_veto_filename(struct ksmbd_share_config *share,
const char *filename); const char *filename);
#endif /* __SHARE_CONFIG_MANAGEMENT_H__ */ #endif /* __SHARE_CONFIG_MANAGEMENT_H__ */
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
struct ksmbd_tree_conn_status struct ksmbd_tree_conn_status
ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, 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_conn_status status = {-ENOENT, NULL};
struct ksmbd_tree_connect_response *resp = NULL; struct ksmbd_tree_connect_response *resp = NULL;
...@@ -26,7 +26,7 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, ...@@ -26,7 +26,7 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
struct sockaddr *peer_addr; struct sockaddr *peer_addr;
int ret; int ret;
sc = ksmbd_share_config_get(share_name); sc = ksmbd_share_config_get(conn->um, share_name);
if (!sc) if (!sc)
return status; return status;
...@@ -61,7 +61,7 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, ...@@ -61,7 +61,7 @@ ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess,
struct ksmbd_share_config *new_sc; struct ksmbd_share_config *new_sc;
ksmbd_share_config_del(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) { if (!new_sc) {
pr_err("Failed to update stale share config\n"); pr_err("Failed to update stale share config\n");
status.ret = -ESTALE; status.ret = -ESTALE;
......
...@@ -42,7 +42,7 @@ struct ksmbd_session; ...@@ -42,7 +42,7 @@ struct ksmbd_session;
struct ksmbd_tree_conn_status struct ksmbd_tree_conn_status
ksmbd_tree_conn_connect(struct ksmbd_conn *conn, struct ksmbd_session *sess, 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, int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
struct ksmbd_tree_connect *tree_conn); struct ksmbd_tree_connect *tree_conn);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/xattr.h> #include <linux/xattr.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/unicode.h>
#include "misc.h" #include "misc.h"
#include "smb_common.h" #include "smb_common.h"
...@@ -159,7 +160,7 @@ int parse_stream_name(char *filename, char **stream_name, int *s_type) ...@@ -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, char *convert_to_nt_pathname(struct ksmbd_share_config *share,
struct path *path) const struct path *path)
{ {
char *pathname, *ab_pathname, *nt_pathname; char *pathname, *ab_pathname, *nt_pathname;
int share_path_len = share->path_sz; int share_path_len = share->path_sz;
...@@ -226,26 +227,53 @@ void ksmbd_conv_path_to_windows(char *path) ...@@ -226,26 +227,53 @@ void ksmbd_conv_path_to_windows(char *path)
strreplace(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 * ksmbd_extract_sharename() - get share name from tree connect request
* @treename: buffer containing tree name and share name * @treename: buffer containing tree name and share name
* *
* Return: share name on success, otherwise error * 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; const char *name = treename, *pos = strrchr(name, '\\');
char *dst;
char *pos = strrchr(name, '\\');
if (pos) if (pos)
name = (pos + 1); name = (pos + 1);
/* caller has to free the memory */ /* caller has to free the memory */
dst = kstrdup(name, GFP_KERNEL); return ksmbd_casefold_sharename(um, name);
if (!dst)
return ERR_PTR(-ENOMEM);
return dst;
} }
/** /**
......
...@@ -15,12 +15,13 @@ int match_pattern(const char *str, size_t len, const char *pattern); ...@@ -15,12 +15,13 @@ int match_pattern(const char *str, size_t len, const char *pattern);
int ksmbd_validate_filename(char *filename); int ksmbd_validate_filename(char *filename);
int parse_stream_name(char *filename, char **stream_name, int *s_type); int parse_stream_name(char *filename, char **stream_name, int *s_type);
char *convert_to_nt_pathname(struct ksmbd_share_config *share, char *convert_to_nt_pathname(struct ksmbd_share_config *share,
struct path *path); const struct path *path);
int get_nlink(struct kstat *st); int get_nlink(struct kstat *st);
void ksmbd_conv_path_to_unix(char *path); void ksmbd_conv_path_to_unix(char *path);
void ksmbd_strip_last_slash(char *path); void ksmbd_strip_last_slash(char *path);
void ksmbd_conv_path_to_windows(char *path); void ksmbd_conv_path_to_windows(char *path);
char *ksmbd_extract_sharename(char *treename); char *ksmbd_casefold_sharename(struct unicode_map *um, const char *name);
char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);
char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name); char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name);
#define KSMBD_DIR_INFO_ALIGNMENT 8 #define KSMBD_DIR_INFO_ALIGNMENT 8
......
...@@ -345,6 +345,8 @@ int ndr_encode_posix_acl(struct ndr *n, ...@@ -345,6 +345,8 @@ int ndr_encode_posix_acl(struct ndr *n,
{ {
unsigned int ref_id = 0x00020000; unsigned int ref_id = 0x00020000;
int ret; int ret;
vfsuid_t vfsuid;
vfsgid_t vfsgid;
n->offset = 0; n->offset = 0;
n->length = 1024; n->length = 1024;
...@@ -372,10 +374,12 @@ int ndr_encode_posix_acl(struct ndr *n, ...@@ -372,10 +374,12 @@ int ndr_encode_posix_acl(struct ndr *n,
if (ret) if (ret)
return ret; return ret;
ret = ndr_write_int64(n, from_kuid(&init_user_ns, i_uid_into_mnt(user_ns, inode))); vfsuid = i_uid_into_vfsuid(user_ns, inode);
ret = ndr_write_int64(n, from_kuid(&init_user_ns, vfsuid_into_kuid(vfsuid)));
if (ret) if (ret)
return ret; return ret;
ret = ndr_write_int64(n, from_kgid(&init_user_ns, i_gid_into_mnt(user_ns, inode))); vfsgid = i_gid_into_vfsgid(user_ns, inode);
ret = ndr_write_int64(n, from_kgid(&init_user_ns, vfsgid_into_kgid(vfsgid)));
if (ret) if (ret)
return ret; return ret;
ret = ndr_write_int32(n, inode->i_mode); ret = ndr_write_int32(n, inode->i_mode);
......
...@@ -1609,12 +1609,18 @@ void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp) ...@@ -1609,12 +1609,18 @@ void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp)
struct create_posix_rsp *buf; struct create_posix_rsp *buf;
struct inode *inode = file_inode(fp->filp); struct inode *inode = file_inode(fp->filp);
struct user_namespace *user_ns = file_mnt_user_ns(fp->filp); struct user_namespace *user_ns = file_mnt_user_ns(fp->filp);
vfsuid_t vfsuid = i_uid_into_vfsuid(user_ns, inode);
vfsgid_t vfsgid = i_gid_into_vfsgid(user_ns, inode);
buf = (struct create_posix_rsp *)cc; buf = (struct create_posix_rsp *)cc;
memset(buf, 0, sizeof(struct create_posix_rsp)); memset(buf, 0, sizeof(struct create_posix_rsp));
buf->ccontext.DataOffset = cpu_to_le16(offsetof buf->ccontext.DataOffset = cpu_to_le16(offsetof
(struct create_posix_rsp, nlink)); (struct create_posix_rsp, nlink));
buf->ccontext.DataLength = cpu_to_le32(52); /*
* DataLength = nlink(4) + reparse_tag(4) + mode(4) +
* domain sid(28) + unix group sid(16).
*/
buf->ccontext.DataLength = cpu_to_le32(56);
buf->ccontext.NameOffset = cpu_to_le16(offsetof buf->ccontext.NameOffset = cpu_to_le16(offsetof
(struct create_posix_rsp, Name)); (struct create_posix_rsp, Name));
buf->ccontext.NameLength = cpu_to_le16(POSIX_CTXT_DATA_LEN); buf->ccontext.NameLength = cpu_to_le16(POSIX_CTXT_DATA_LEN);
...@@ -1638,13 +1644,18 @@ void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp) ...@@ -1638,13 +1644,18 @@ void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp)
buf->nlink = cpu_to_le32(inode->i_nlink); buf->nlink = cpu_to_le32(inode->i_nlink);
buf->reparse_tag = cpu_to_le32(fp->volatile_id); buf->reparse_tag = cpu_to_le32(fp->volatile_id);
buf->mode = cpu_to_le32(inode->i_mode); buf->mode = cpu_to_le32(inode->i_mode & 0777);
id_to_sid(from_kuid_munged(&init_user_ns, /*
i_uid_into_mnt(user_ns, inode)), * SidBuffer(44) contain two sids(Domain sid(28), UNIX group sid(16)).
SIDNFS_USER, (struct smb_sid *)&buf->SidBuffer[0]); * Domain sid(28) = revision(1) + num_subauth(1) + authority(6) +
id_to_sid(from_kgid_munged(&init_user_ns, * sub_auth(4 * 4(num_subauth)) + RID(4).
i_gid_into_mnt(user_ns, inode)), * UNIX group id(16) = revision(1) + num_subauth(1) + authority(6) +
SIDNFS_GROUP, (struct smb_sid *)&buf->SidBuffer[20]); * sub_auth(4 * 1(num_subauth)) + RID(4).
*/
id_to_sid(from_kuid_munged(&init_user_ns, vfsuid_into_kuid(vfsuid)),
SIDOWNER, (struct smb_sid *)&buf->SidBuffer[0]);
id_to_sid(from_kgid_munged(&init_user_ns, vfsgid_into_kgid(vfsgid)),
SIDUNIX_GROUP, (struct smb_sid *)&buf->SidBuffer[28]);
} }
/* /*
......
...@@ -235,10 +235,8 @@ static void __handle_ksmbd_work(struct ksmbd_work *work, ...@@ -235,10 +235,8 @@ static void __handle_ksmbd_work(struct ksmbd_work *work,
if (work->sess && work->sess->enc && work->encrypted && if (work->sess && work->sess->enc && work->encrypted &&
conn->ops->encrypt_resp) { conn->ops->encrypt_resp) {
rc = conn->ops->encrypt_resp(work); rc = conn->ops->encrypt_resp(work);
if (rc < 0) { if (rc < 0)
conn->ops->set_rsp_status(work, STATUS_DATA_ERROR); conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
goto send;
}
} }
ksmbd_conn_write(work); ksmbd_conn_write(work);
......
This diff is collapsed.
...@@ -158,7 +158,8 @@ struct create_posix_rsp { ...@@ -158,7 +158,8 @@ struct create_posix_rsp {
__le32 nlink; __le32 nlink;
__le32 reparse_tag; __le32 reparse_tag;
__le32 mode; __le32 mode;
u8 SidBuffer[40]; /* SidBuffer contain two sids(Domain sid(28), UNIX group sid(16)) */
u8 SidBuffer[44];
} __packed; } __packed;
struct smb2_buffer_desc_v1 { struct smb2_buffer_desc_v1 {
...@@ -439,7 +440,8 @@ struct smb2_posix_info { ...@@ -439,7 +440,8 @@ struct smb2_posix_info {
__le32 HardLinks; __le32 HardLinks;
__le32 ReparseTag; __le32 ReparseTag;
__le32 Mode; __le32 Mode;
u8 SidBuffer[40]; /* SidBuffer contain two sids (UNIX user sid(16), UNIX group sid(16)) */
u8 SidBuffer[32];
__le32 name_len; __le32 name_len;
u8 name[1]; u8 name[1];
/* /*
...@@ -492,6 +494,7 @@ int smb3_decrypt_req(struct ksmbd_work *work); ...@@ -492,6 +494,7 @@ int smb3_decrypt_req(struct ksmbd_work *work);
int smb3_encrypt_resp(struct ksmbd_work *work); int smb3_encrypt_resp(struct ksmbd_work *work);
bool smb3_11_final_sess_setup_resp(struct ksmbd_work *work); bool smb3_11_final_sess_setup_resp(struct ksmbd_work *work);
int smb2_set_rsp_credits(struct ksmbd_work *work); int smb2_set_rsp_credits(struct ksmbd_work *work);
bool smb3_encryption_negotiated(struct ksmbd_conn *conn);
/* smb2 misc functions */ /* smb2 misc functions */
int ksmbd_smb2_check_message(struct ksmbd_work *work); int ksmbd_smb2_check_message(struct ksmbd_work *work);
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
* Copyright (C) 2018 Namjae Jeon <linkinjeon@kernel.org> * Copyright (C) 2018 Namjae Jeon <linkinjeon@kernel.org>
*/ */
#include <linux/user_namespace.h>
#include "smb_common.h" #include "smb_common.h"
#include "server.h" #include "server.h"
#include "misc.h" #include "misc.h"
...@@ -625,8 +627,8 @@ int ksmbd_override_fsids(struct ksmbd_work *work) ...@@ -625,8 +627,8 @@ int ksmbd_override_fsids(struct ksmbd_work *work)
if (!cred) if (!cred)
return -ENOMEM; return -ENOMEM;
cred->fsuid = make_kuid(current_user_ns(), uid); cred->fsuid = make_kuid(&init_user_ns, uid);
cred->fsgid = make_kgid(current_user_ns(), gid); cred->fsgid = make_kgid(&init_user_ns, gid);
gi = groups_alloc(0); gi = groups_alloc(0);
if (!gi) { if (!gi) {
......
...@@ -275,7 +275,8 @@ static int sid_to_id(struct user_namespace *user_ns, ...@@ -275,7 +275,8 @@ static int sid_to_id(struct user_namespace *user_ns,
uid_t id; uid_t id;
id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]); id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
uid = mapped_kuid_user(user_ns, &init_user_ns, KUIDT_INIT(id)); uid = KUIDT_INIT(id);
uid = from_vfsuid(user_ns, &init_user_ns, VFSUIDT_INIT(uid));
if (uid_valid(uid)) { if (uid_valid(uid)) {
fattr->cf_uid = uid; fattr->cf_uid = uid;
rc = 0; rc = 0;
...@@ -285,7 +286,8 @@ static int sid_to_id(struct user_namespace *user_ns, ...@@ -285,7 +286,8 @@ static int sid_to_id(struct user_namespace *user_ns,
gid_t id; gid_t id;
id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]); id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
gid = mapped_kgid_user(user_ns, &init_user_ns, KGIDT_INIT(id)); gid = KGIDT_INIT(id);
gid = from_vfsgid(user_ns, &init_user_ns, VFSGIDT_INIT(gid));
if (gid_valid(gid)) { if (gid_valid(gid)) {
fattr->cf_gid = gid; fattr->cf_gid = gid;
rc = 0; rc = 0;
...@@ -991,7 +993,7 @@ static void smb_set_ace(struct smb_ace *ace, const struct smb_sid *sid, u8 type, ...@@ -991,7 +993,7 @@ static void smb_set_ace(struct smb_ace *ace, const struct smb_sid *sid, u8 type,
} }
int smb_inherit_dacl(struct ksmbd_conn *conn, int smb_inherit_dacl(struct ksmbd_conn *conn,
struct path *path, const struct path *path,
unsigned int uid, unsigned int gid) unsigned int uid, unsigned int gid)
{ {
const struct smb_sid *psid, *creator = NULL; const struct smb_sid *psid, *creator = NULL;
...@@ -1185,7 +1187,7 @@ bool smb_inherit_flags(int flags, bool is_dir) ...@@ -1185,7 +1187,7 @@ bool smb_inherit_flags(int flags, bool is_dir)
return false; return false;
} }
int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path, int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
__le32 *pdaccess, int uid) __le32 *pdaccess, int uid)
{ {
struct user_namespace *user_ns = mnt_user_ns(path->mnt); struct user_namespace *user_ns = mnt_user_ns(path->mnt);
...@@ -1352,7 +1354,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path, ...@@ -1352,7 +1354,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path,
} }
int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon, int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
struct path *path, struct smb_ntsd *pntsd, int ntsd_len, const struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
bool type_check) bool type_check)
{ {
int rc; int rc;
......
...@@ -201,12 +201,12 @@ void posix_state_to_acl(struct posix_acl_state *state, ...@@ -201,12 +201,12 @@ void posix_state_to_acl(struct posix_acl_state *state,
struct posix_acl_entry *pace); struct posix_acl_entry *pace);
int compare_sids(const struct smb_sid *ctsid, const struct smb_sid *cwsid); int compare_sids(const struct smb_sid *ctsid, const struct smb_sid *cwsid);
bool smb_inherit_flags(int flags, bool is_dir); bool smb_inherit_flags(int flags, bool is_dir);
int smb_inherit_dacl(struct ksmbd_conn *conn, struct path *path, int smb_inherit_dacl(struct ksmbd_conn *conn, const struct path *path,
unsigned int uid, unsigned int gid); unsigned int uid, unsigned int gid);
int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path, int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
__le32 *pdaccess, int uid); __le32 *pdaccess, int uid);
int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon, int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
struct path *path, struct smb_ntsd *pntsd, int ntsd_len, const struct path *path, struct smb_ntsd *pntsd, int ntsd_len,
bool type_check); bool type_check);
void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid); void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid);
void ksmbd_init_domain(u32 *sub_auth); void ksmbd_init_domain(u32 *sub_auth);
...@@ -214,25 +214,25 @@ void ksmbd_init_domain(u32 *sub_auth); ...@@ -214,25 +214,25 @@ void ksmbd_init_domain(u32 *sub_auth);
static inline uid_t posix_acl_uid_translate(struct user_namespace *mnt_userns, static inline uid_t posix_acl_uid_translate(struct user_namespace *mnt_userns,
struct posix_acl_entry *pace) struct posix_acl_entry *pace)
{ {
kuid_t kuid; vfsuid_t vfsuid;
/* If this is an idmapped mount, apply the idmapping. */ /* If this is an idmapped mount, apply the idmapping. */
kuid = mapped_kuid_fs(mnt_userns, &init_user_ns, pace->e_uid); vfsuid = make_vfsuid(mnt_userns, &init_user_ns, pace->e_uid);
/* Translate the kuid into a userspace id ksmbd would see. */ /* Translate the kuid into a userspace id ksmbd would see. */
return from_kuid(&init_user_ns, kuid); return from_kuid(&init_user_ns, vfsuid_into_kuid(vfsuid));
} }
static inline gid_t posix_acl_gid_translate(struct user_namespace *mnt_userns, static inline gid_t posix_acl_gid_translate(struct user_namespace *mnt_userns,
struct posix_acl_entry *pace) struct posix_acl_entry *pace)
{ {
kgid_t kgid; vfsgid_t vfsgid;
/* If this is an idmapped mount, apply the idmapping. */ /* If this is an idmapped mount, apply the idmapping. */
kgid = mapped_kgid_fs(mnt_userns, &init_user_ns, pace->e_gid); vfsgid = make_vfsgid(mnt_userns, &init_user_ns, pace->e_gid);
/* Translate the kgid into a userspace id ksmbd would see. */ /* Translate the kgid into a userspace id ksmbd would see. */
return from_kgid(&init_user_ns, kgid); return from_kgid(&init_user_ns, vfsgid_into_kgid(vfsgid));
} }
#endif /* _SMBACL_H */ #endif /* _SMBACL_H */
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
/* SMB_DIRECT negotiation timeout in seconds */ /* SMB_DIRECT negotiation timeout in seconds */
#define SMB_DIRECT_NEGOTIATE_TIMEOUT 120 #define SMB_DIRECT_NEGOTIATE_TIMEOUT 120
#define SMB_DIRECT_MAX_SEND_SGES 8 #define SMB_DIRECT_MAX_SEND_SGES 6
#define SMB_DIRECT_MAX_RECV_SGES 1 #define SMB_DIRECT_MAX_RECV_SGES 1
/* /*
...@@ -62,13 +62,13 @@ static int smb_direct_receive_credit_max = 255; ...@@ -62,13 +62,13 @@ static int smb_direct_receive_credit_max = 255;
static int smb_direct_send_credit_target = 255; static int smb_direct_send_credit_target = 255;
/* The maximum single message size can be sent to remote peer */ /* The maximum single message size can be sent to remote peer */
static int smb_direct_max_send_size = 8192; static int smb_direct_max_send_size = 1364;
/* The maximum fragmented upper-layer payload receive size supported */ /* The maximum fragmented upper-layer payload receive size supported */
static int smb_direct_max_fragmented_recv_size = 1024 * 1024; static int smb_direct_max_fragmented_recv_size = 1024 * 1024;
/* The maximum single-message size which can be received */ /* The maximum single-message size which can be received */
static int smb_direct_max_receive_size = 8192; static int smb_direct_max_receive_size = 1364;
static int smb_direct_max_read_write_size = SMBD_DEFAULT_IOSIZE; static int smb_direct_max_read_write_size = SMBD_DEFAULT_IOSIZE;
...@@ -1527,6 +1527,8 @@ static int smb_direct_cm_handler(struct rdma_cm_id *cm_id, ...@@ -1527,6 +1527,8 @@ static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
} }
case RDMA_CM_EVENT_DEVICE_REMOVAL: case RDMA_CM_EVENT_DEVICE_REMOVAL:
case RDMA_CM_EVENT_DISCONNECTED: { case RDMA_CM_EVENT_DISCONNECTED: {
ib_drain_qp(t->qp);
t->status = SMB_DIRECT_CS_DISCONNECTED; t->status = SMB_DIRECT_CS_DISCONNECTED;
wake_up_interruptible(&t->wait_status); wake_up_interruptible(&t->wait_status);
wake_up_interruptible(&t->wait_reassembly_queue); wake_up_interruptible(&t->wait_reassembly_queue);
......
...@@ -399,7 +399,8 @@ static int create_socket(struct interface *iface) ...@@ -399,7 +399,8 @@ static int create_socket(struct interface *iface)
ret = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &ksmbd_socket); ret = sock_create(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &ksmbd_socket);
if (ret) { if (ret) {
pr_err("Can't create socket for ipv6, try ipv4: %d\n", ret); if (ret != -EAFNOSUPPORT)
pr_err("Can't create socket for ipv6, fallback to ipv4: %d\n", ret);
ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP,
&ksmbd_socket); &ksmbd_socket);
if (ret) { if (ret) {
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/nls.h> #include <linux/nls.h>
#include <linux/unicode.h>
#define UNIUPR_NOLOWER /* Example to not expand lower case tables */ #define UNIUPR_NOLOWER /* Example to not expand lower case tables */
...@@ -69,7 +70,7 @@ char *smb_strndup_from_utf16(const char *src, const int maxlen, ...@@ -69,7 +70,7 @@ char *smb_strndup_from_utf16(const char *src, const int maxlen,
const struct nls_table *codepage); const struct nls_table *codepage);
int smbConvertToUTF16(__le16 *target, const char *source, int srclen, int smbConvertToUTF16(__le16 *target, const char *source, int srclen,
const struct nls_table *cp, int mapchars); const struct nls_table *cp, int mapchars);
char *ksmbd_extract_sharename(char *treename); char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);
#endif #endif
/* /*
......
...@@ -377,8 +377,7 @@ int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count, ...@@ -377,8 +377,7 @@ int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, size_t count,
if (work->conn->connection_type) { if (work->conn->connection_type) {
if (!(fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) { if (!(fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
pr_err("no right to read(%pd)\n", pr_err("no right to read(%pD)\n", fp->filp);
fp->filp->f_path.dentry);
return -EACCES; return -EACCES;
} }
} }
...@@ -487,8 +486,7 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp, ...@@ -487,8 +486,7 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
if (work->conn->connection_type) { if (work->conn->connection_type) {
if (!(fp->daccess & FILE_WRITE_DATA_LE)) { if (!(fp->daccess & FILE_WRITE_DATA_LE)) {
pr_err("no right to write(%pd)\n", pr_err("no right to write(%pD)\n", fp->filp);
fp->filp->f_path.dentry);
err = -EACCES; err = -EACCES;
goto out; goto out;
} }
...@@ -527,8 +525,8 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp, ...@@ -527,8 +525,8 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
if (sync) { if (sync) {
err = vfs_fsync_range(filp, offset, offset + *written, 0); err = vfs_fsync_range(filp, offset, offset + *written, 0);
if (err < 0) if (err < 0)
pr_err("fsync failed for filename = %pd, err = %d\n", pr_err("fsync failed for filename = %pD, err = %d\n",
fp->filp->f_path.dentry, err); fp->filp, err);
} }
out: out:
...@@ -543,7 +541,7 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp, ...@@ -543,7 +541,7 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
* *
* Return: 0 on success, otherwise error * Return: 0 on success, otherwise error
*/ */
int ksmbd_vfs_getattr(struct path *path, struct kstat *stat) int ksmbd_vfs_getattr(const struct path *path, struct kstat *stat)
{ {
int err; int err;
...@@ -1145,12 +1143,23 @@ static bool __caseless_lookup(struct dir_context *ctx, const char *name, ...@@ -1145,12 +1143,23 @@ static bool __caseless_lookup(struct dir_context *ctx, const char *name,
unsigned int d_type) unsigned int d_type)
{ {
struct ksmbd_readdir_data *buf; struct ksmbd_readdir_data *buf;
int cmp = -EINVAL;
buf = container_of(ctx, struct ksmbd_readdir_data, ctx); buf = container_of(ctx, struct ksmbd_readdir_data, ctx);
if (buf->used != namlen) if (buf->used != namlen)
return true; return true;
if (!strncasecmp((char *)buf->private, name, namlen)) { if (IS_ENABLED(CONFIG_UNICODE) && buf->um) {
const struct qstr q_buf = {.name = buf->private,
.len = buf->used};
const struct qstr q_name = {.name = name,
.len = namlen};
cmp = utf8_strncasecmp(buf->um, &q_buf, &q_name);
}
if (cmp < 0)
cmp = strncasecmp((char *)buf->private, name, namlen);
if (!cmp) {
memcpy((char *)buf->private, name, namlen); memcpy((char *)buf->private, name, namlen);
buf->dirent_count = 1; buf->dirent_count = 1;
return false; return false;
...@@ -1166,7 +1175,8 @@ static bool __caseless_lookup(struct dir_context *ctx, const char *name, ...@@ -1166,7 +1175,8 @@ static bool __caseless_lookup(struct dir_context *ctx, const char *name,
* *
* Return: 0 on success, otherwise error * Return: 0 on success, otherwise error
*/ */
static int ksmbd_vfs_lookup_in_dir(struct path *dir, char *name, size_t namelen) static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
size_t namelen, struct unicode_map *um)
{ {
int ret; int ret;
struct file *dfilp; struct file *dfilp;
...@@ -1176,6 +1186,7 @@ static int ksmbd_vfs_lookup_in_dir(struct path *dir, char *name, size_t namelen) ...@@ -1176,6 +1186,7 @@ static int ksmbd_vfs_lookup_in_dir(struct path *dir, char *name, size_t namelen)
.private = name, .private = name,
.used = namelen, .used = namelen,
.dirent_count = 0, .dirent_count = 0,
.um = um,
}; };
dfilp = dentry_open(dir, flags, current_cred()); dfilp = dentry_open(dir, flags, current_cred());
...@@ -1238,7 +1249,8 @@ int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name, ...@@ -1238,7 +1249,8 @@ int ksmbd_vfs_kern_path(struct ksmbd_work *work, char *name,
break; break;
err = ksmbd_vfs_lookup_in_dir(&parent, filename, err = ksmbd_vfs_lookup_in_dir(&parent, filename,
filename_len); filename_len,
work->conn->um);
path_put(&parent); path_put(&parent);
if (err) if (err)
goto out; goto out;
...@@ -1741,11 +1753,11 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work, ...@@ -1741,11 +1753,11 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
*total_size_written = 0; *total_size_written = 0;
if (!(src_fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) { if (!(src_fp->daccess & (FILE_READ_DATA_LE | FILE_EXECUTE_LE))) {
pr_err("no right to read(%pd)\n", src_fp->filp->f_path.dentry); pr_err("no right to read(%pD)\n", src_fp->filp);
return -EACCES; return -EACCES;
} }
if (!(dst_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE))) { if (!(dst_fp->daccess & (FILE_WRITE_DATA_LE | FILE_APPEND_DATA_LE))) {
pr_err("no right to write(%pd)\n", dst_fp->filp->f_path.dentry); pr_err("no right to write(%pD)\n", dst_fp->filp);
return -EACCES; return -EACCES;
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/namei.h> #include <linux/namei.h>
#include <uapi/linux/xattr.h> #include <uapi/linux/xattr.h>
#include <linux/posix_acl.h> #include <linux/posix_acl.h>
#include <linux/unicode.h>
#include "smbacl.h" #include "smbacl.h"
#include "xattr.h" #include "xattr.h"
...@@ -60,6 +61,7 @@ struct ksmbd_readdir_data { ...@@ -60,6 +61,7 @@ struct ksmbd_readdir_data {
unsigned int used; unsigned int used;
unsigned int dirent_count; unsigned int dirent_count;
unsigned int file_attr; unsigned int file_attr;
struct unicode_map *um;
}; };
/* ksmbd kstat wrapper to get valid create time when reading dir entry */ /* ksmbd kstat wrapper to get valid create time when reading dir entry */
...@@ -85,7 +87,7 @@ int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id); ...@@ -85,7 +87,7 @@ int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id);
int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name); int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name);
int ksmbd_vfs_link(struct ksmbd_work *work, int ksmbd_vfs_link(struct ksmbd_work *work,
const char *oldname, const char *newname); const char *oldname, const char *newname);
int ksmbd_vfs_getattr(struct path *path, struct kstat *stat); int ksmbd_vfs_getattr(const struct path *path, struct kstat *stat);
int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp, int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
char *newname); char *newname);
int ksmbd_vfs_truncate(struct ksmbd_work *work, int ksmbd_vfs_truncate(struct ksmbd_work *work,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment