Forty four smb client and server changesets

-----BEGIN PGP SIGNATURE-----
 
 iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmktxl0ACgkQiiy9cAdy
 T1HI7AwAtnKyyIWfKwSnsGNTTc3LrT6ucx0DpCw1tqU7TBDLJtNPbQlgzL2rNCiv
 cL6TTxn+qWTLfgJChQnypsCpoiQXwtqNBpfxQaoCOcwG+fUaa9G1JXxEmgv/Ob7j
 KTrYHrnPS6YCQMDLMrEJh8tnI9jHcTgLtYCtDC+psYRzcbs/8Wfgs1Ek/vKW5Ui1
 u0nKYf189KZA9UErTY7NhizyYNkifKD0n+DQPzR1FH6JWusWNRtj9MZPgoEsexXK
 NxfDoc8krWwM7O+6X10ER7Snzd9EUtnbgwIqCFhDS6igfz+w+7Hm/XevOhK+DQqX
 ApmFZL3n6yEUCnOZTQCqHutlChu1j8gWmEAnoGSmBJ3y99NvNqxBfedGDA8DGgFM
 wkX6bxCJjpBMrMeLqVv0QXaXLkRycZASz5zVgb/ly3Zu6DnDlFzRYFUBNvXHb+M/
 WFMtzV2Jzd4I09J460b0qU18iuSVxxyJNGVp6xzo++zdNUSt07UYXK/R7NCIaCXO
 buCHlQll
 =QmyI
 -----END PGP SIGNATURE-----

Merge tag 'v6.19-rc-smb-fixes' of git://git.samba.org/ksmbd

Pull smb client and server updates from Steve French:

 - server fixes:
     - IPC use after free locking fix
     - fix locking bug in delete paths
     - fix use after free in disconnect
     - fix underflow in locking check
     - error mapping improvement
     - socket listening improvement
     - return code mapping fixes
     - crypto improvements (use default libraries)

 - cleanup patches:
     - netfs
     - client checkpatch cleanup
     - server cleanup
     - move server/client duplicate code to common code
     - fix some defines to better match protocol specification

  - smbdirect (RDMA) fixes

  - client debugging improvements for leases

* tag 'v6.19-rc-smb-fixes' of git://git.samba.org/ksmbd: (44 commits)
  cifs: Use netfs_alloc/free_folioq_buffer()
  smb: client: show smb lease key in open_dirs output
  smb: client: show smb lease key in open_files output
  ksmbd: ipc: fix use-after-free in ipc_msg_send_request
  smb: client: relax WARN_ON_ONCE(SMBDIRECT_SOCKET_*) checks in recv_done() and smbd_conn_upcall()
  smb: server: relax WARN_ON_ONCE(SMBDIRECT_SOCKET_*) checks in recv_done() and smb_direct_cm_handler()
  smb: smbdirect: introduce SMBDIRECT_CHECK_STATUS_{WARN,DISCONNECT}()
  smb: smbdirect: introduce SMBDIRECT_DEBUG_ERR_PTR() helper
  ksmbd: vfs: fix race on m_flags in vfs_cache
  ksmbd: Replace strcpy + strcat to improve convert_to_nt_pathname
  smb: move FILE_SYSTEM_ATTRIBUTE_INFO to common/fscc.h
  ksmbd: implement error handling for STATUS_INFO_LENGTH_MISMATCH in smb server
  ksmbd: fix use-after-free in ksmbd_tree_connect_put under concurrency
  ksmbd: server: avoid busy polling in accept loop
  smb: move create_durable_reconn to common/smb2pdu.h
  smb: fix some warnings reported by scripts/checkpatch.pl
  smb: do some cleanups
  smb: move FILE_SYSTEM_SIZE_INFO to common/fscc.h
  smb: move some duplicate struct definitions to common/fscc.h
  smb: move list of FileSystemAttributes to common/fscc.h
  ...
This commit is contained in:
Linus Torvalds 2025-12-03 20:23:41 -08:00
commit 869737543b
44 changed files with 1194 additions and 1743 deletions

View File

@ -249,9 +249,9 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
seq_puts(m, "# Format:\n"); seq_puts(m, "# Format:\n");
seq_puts(m, "# <tree id> <ses id> <persistent fid> <flags> <count> <pid> <uid>"); seq_puts(m, "# <tree id> <ses id> <persistent fid> <flags> <count> <pid> <uid>");
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
seq_puts(m, " <filename> <lease> <mid>\n"); seq_puts(m, " <filename> <lease> <lease-key> <mid>\n");
#else #else
seq_puts(m, " <filename> <lease>\n"); seq_puts(m, " <filename> <lease> <lease-key>\n");
#endif /* CIFS_DEBUG2 */ #endif /* CIFS_DEBUG2 */
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) { list_for_each_entry(server, &cifs_tcp_ses_list, tcp_ses_list) {
@ -274,6 +274,7 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
/* Append lease/oplock caching state as RHW letters */ /* Append lease/oplock caching state as RHW letters */
inode = d_inode(cfile->dentry); inode = d_inode(cfile->dentry);
cinode = NULL;
n = 0; n = 0;
if (inode) { if (inode) {
cinode = CIFS_I(inode); cinode = CIFS_I(inode);
@ -291,6 +292,12 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
else else
seq_puts(m, "NONE"); seq_puts(m, "NONE");
seq_puts(m, " ");
if (cinode && cinode->lease_granted)
seq_printf(m, "%pUl", cinode->lease_key);
else
seq_puts(m, "-");
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
seq_printf(m, " %llu", cfile->fid.mid); seq_printf(m, " %llu", cfile->fid.mid);
#endif /* CONFIG_CIFS_DEBUG2 */ #endif /* CONFIG_CIFS_DEBUG2 */
@ -317,7 +324,7 @@ static int cifs_debug_dirs_proc_show(struct seq_file *m, void *v)
seq_puts(m, "# Version:1\n"); seq_puts(m, "# Version:1\n");
seq_puts(m, "# Format:\n"); seq_puts(m, "# Format:\n");
seq_puts(m, "# <tree id> <sess id> <persistent fid> <path>\n"); seq_puts(m, "# <tree id> <sess id> <persistent fid> <lease-key> <path>\n");
spin_lock(&cifs_tcp_ses_lock); spin_lock(&cifs_tcp_ses_lock);
list_for_each(stmp, &cifs_tcp_ses_list) { list_for_each(stmp, &cifs_tcp_ses_list) {
@ -336,11 +343,15 @@ static int cifs_debug_dirs_proc_show(struct seq_file *m, void *v)
(unsigned long)atomic_long_read(&cfids->total_dirents_entries), (unsigned long)atomic_long_read(&cfids->total_dirents_entries),
(unsigned long long)atomic64_read(&cfids->total_dirents_bytes)); (unsigned long long)atomic64_read(&cfids->total_dirents_bytes));
list_for_each_entry(cfid, &cfids->entries, entry) { list_for_each_entry(cfid, &cfids->entries, entry) {
seq_printf(m, "0x%x 0x%llx 0x%llx %s", seq_printf(m, "0x%x 0x%llx 0x%llx ",
tcon->tid, tcon->tid,
ses->Suid, ses->Suid,
cfid->fid.persistent_fid, cfid->fid.persistent_fid);
cfid->path); if (cfid->has_lease)
seq_printf(m, "%pUl ", cfid->fid.lease_key);
else
seq_puts(m, "- ");
seq_printf(m, "%s", cfid->path);
if (cfid->file_all_info_is_valid) if (cfid->file_all_info_is_valid)
seq_printf(m, "\tvalid file info"); seq_printf(m, "\tvalid file info");
if (cfid->dirents.is_valid) if (cfid->dirents.is_valid)

View File

@ -24,8 +24,9 @@
#include "cifsacl.h" #include "cifsacl.h"
#include <crypto/internal/hash.h> #include <crypto/internal/hash.h>
#include <uapi/linux/cifs/cifs_mount.h> #include <uapi/linux/cifs/cifs_mount.h>
#include "../common/cifsglob.h" #include "../common/smbglob.h"
#include "../common/smb2pdu.h" #include "../common/smb2pdu.h"
#include "../common/fscc.h"
#include "smb2pdu.h" #include "smb2pdu.h"
#include <linux/filelock.h> #include <linux/filelock.h>
@ -633,28 +634,6 @@ struct smb_version_operations {
struct kvec *xattr_iov); struct kvec *xattr_iov);
}; };
struct smb_version_values {
char *version_string;
__u16 protocol_id;
__u32 req_capabilities;
__u32 large_lock_type;
__u32 exclusive_lock_type;
__u32 shared_lock_type;
__u32 unlock_lock_type;
size_t header_preamble_size;
size_t header_size;
size_t max_header_size;
size_t read_rsp_size;
__le16 lock_cmd;
unsigned int cap_unix;
unsigned int cap_nt_find;
unsigned int cap_large_files;
unsigned int cap_unicode;
__u16 signing_enabled;
__u16 signing_required;
size_t create_lease_size;
};
#define HEADER_SIZE(server) (server->vals->header_size) #define HEADER_SIZE(server) (server->vals->header_size)
#define MAX_HEADER_SIZE(server) (server->vals->max_header_size) #define MAX_HEADER_SIZE(server) (server->vals->max_header_size)
#define HEADER_PREAMBLE_SIZE(server) (server->vals->header_preamble_size) #define HEADER_PREAMBLE_SIZE(server) (server->vals->header_preamble_size)
@ -692,12 +671,6 @@ struct cifs_mnt_data {
int flags; int flags;
}; };
static inline unsigned int
get_rfc1002_length(void *buf)
{
return be32_to_cpu(*((__be32 *)buf)) & 0xffffff;
}
struct TCP_Server_Info { struct TCP_Server_Info {
struct list_head tcp_ses_list; struct list_head tcp_ses_list;
struct list_head smb_ses_list; struct list_head smb_ses_list;

File diff suppressed because it is too large Load Diff

View File

@ -361,7 +361,7 @@ static int validate_t2(struct smb_t2_rsp *pSMB)
} }
static int static int
decode_ext_sec_blob(struct cifs_ses *ses, NEGOTIATE_RSP *pSMBr) decode_ext_sec_blob(struct cifs_ses *ses, SMB_NEGOTIATE_RSP *pSMBr)
{ {
int rc = 0; int rc = 0;
u16 count; u16 count;
@ -419,8 +419,8 @@ CIFSSMBNegotiate(const unsigned int xid,
struct cifs_ses *ses, struct cifs_ses *ses,
struct TCP_Server_Info *server) struct TCP_Server_Info *server)
{ {
NEGOTIATE_REQ *pSMB; SMB_NEGOTIATE_REQ *pSMB;
NEGOTIATE_RSP *pSMBr; SMB_NEGOTIATE_RSP *pSMBr;
int rc = 0; int rc = 0;
int bytes_returned; int bytes_returned;
int i; int i;
@ -614,7 +614,7 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
iov[0].iov_len = 4; iov[0].iov_len = 4;
iov[0].iov_base = smb; iov[0].iov_base = smb;
iov[1].iov_len = get_rfc1002_length(smb); iov[1].iov_len = get_rfc1002_len(smb);
iov[1].iov_base = (char *)smb + 4; iov[1].iov_base = (char *)smb + 4;
rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL, rc = cifs_call_async(server, &rqst, NULL, cifs_echo_callback, NULL,
@ -1458,7 +1458,7 @@ cifs_async_readv(struct cifs_io_subrequest *rdata)
rdata->iov[0].iov_base = smb; rdata->iov[0].iov_base = smb;
rdata->iov[0].iov_len = 4; rdata->iov[0].iov_len = 4;
rdata->iov[1].iov_base = (char *)smb + 4; rdata->iov[1].iov_base = (char *)smb + 4;
rdata->iov[1].iov_len = get_rfc1002_length(smb); rdata->iov[1].iov_len = get_rfc1002_len(smb);
trace_smb3_read_enter(rdata->rreq->debug_id, trace_smb3_read_enter(rdata->rreq->debug_id,
rdata->subreq.debug_index, rdata->subreq.debug_index,
@ -1830,7 +1830,7 @@ cifs_async_writev(struct cifs_io_subrequest *wdata)
/* 4 for RFC1001 length + 1 for BCC */ /* 4 for RFC1001 length + 1 for BCC */
iov[0].iov_len = 4; iov[0].iov_len = 4;
iov[0].iov_base = smb; iov[0].iov_base = smb;
iov[1].iov_len = get_rfc1002_length(smb) + 1; iov[1].iov_len = get_rfc1002_len(smb) + 1;
iov[1].iov_base = (char *)smb + 4; iov[1].iov_base = (char *)smb + 4;
rqst.rq_iov = iov; rqst.rq_iov = iov;
@ -4746,7 +4746,7 @@ CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */ /* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
TRANSACTION2_QFSI_REQ *pSMB = NULL; TRANSACTION2_QFSI_REQ *pSMB = NULL;
TRANSACTION2_QFSI_RSP *pSMBr = NULL; TRANSACTION2_QFSI_RSP *pSMBr = NULL;
FILE_SYSTEM_INFO *response_data; FILE_SYSTEM_SIZE_INFO *response_data;
int rc = 0; int rc = 0;
int bytes_returned = 0; int bytes_returned = 0;
__u16 params, byte_count; __u16 params, byte_count;
@ -4794,7 +4794,7 @@ CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset); __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
response_data = response_data =
(FILE_SYSTEM_INFO (FILE_SYSTEM_SIZE_INFO
*) (((char *) &pSMBr->hdr.Protocol) + *) (((char *) &pSMBr->hdr.Protocol) +
data_offset); data_offset);
FSData->f_bsize = FSData->f_bsize =
@ -4811,7 +4811,7 @@ CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
FSData->f_blocks = FSData->f_blocks =
le64_to_cpu(response_data->TotalAllocationUnits); le64_to_cpu(response_data->TotalAllocationUnits);
FSData->f_bfree = FSData->f_bavail = FSData->f_bfree = FSData->f_bavail =
le64_to_cpu(response_data->FreeAllocationUnits); le64_to_cpu(response_data->AvailableAllocationUnits);
cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n", cifs_dbg(FYI, "Blocks: %lld Free: %lld Block size %ld\n",
(unsigned long long)FSData->f_blocks, (unsigned long long)FSData->f_blocks,
(unsigned long long)FSData->f_bfree, (unsigned long long)FSData->f_bfree,

View File

@ -165,7 +165,7 @@ SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
int resp_buf_type; int resp_buf_type;
iov[0].iov_base = in_buf; iov[0].iov_base = in_buf;
iov[0].iov_len = get_rfc1002_length(in_buf) + 4; iov[0].iov_len = get_rfc1002_len(in_buf) + 4;
flags |= CIFS_NO_RSP_BUF; flags |= CIFS_NO_RSP_BUF;
rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov); rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov);
cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc); cifs_dbg(NOISY, "SendRcvNoRsp flags %d rc %d\n", flags, rc);
@ -177,7 +177,7 @@ int
cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
bool log_error) bool log_error)
{ {
unsigned int len = get_rfc1002_length(mid->resp_buf) + 4; unsigned int len = get_rfc1002_len(mid->resp_buf) + 4;
dump_smb(mid->resp_buf, min_t(u32, 92, len)); dump_smb(mid->resp_buf, min_t(u32, 92, len));
@ -370,7 +370,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
goto out; goto out;
} }
*pbytes_returned = get_rfc1002_length(midQ->resp_buf); *pbytes_returned = get_rfc1002_len(midQ->resp_buf);
memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
rc = cifs_check_receive(midQ, server, 0); rc = cifs_check_receive(midQ, server, 0);
out: out:
@ -554,7 +554,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
goto out; goto out;
} }
*pbytes_returned = get_rfc1002_length(midQ->resp_buf); *pbytes_returned = get_rfc1002_len(midQ->resp_buf);
memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4);
rc = cifs_check_receive(midQ, server, 0); rc = cifs_check_receive(midQ, server, 0);
out: out:

View File

@ -1295,7 +1295,7 @@ cifs_demultiplex_thread(void *p)
* The right amount was read from socket - 4 bytes, * The right amount was read from socket - 4 bytes,
* so we can now interpret the length field. * so we can now interpret the length field.
*/ */
pdu_length = get_rfc1002_length(buf); pdu_length = get_rfc1002_len(buf);
cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length); cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
if (!is_smb_response(server, buf[0])) if (!is_smb_response(server, buf[0]))
@ -2312,8 +2312,8 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses)
} }
#else /* ! CONFIG_KEYS */ #else /* ! CONFIG_KEYS */
static inline int static inline int
cifs_set_cifscreds(struct smb3_fs_context *ctx __attribute__((unused)), cifs_set_cifscreds(struct smb3_fs_context *ctx __maybe_unused,
struct cifs_ses *ses __attribute__((unused))) struct cifs_ses *ses __maybe_unused)
{ {
return -ENOSYS; return -ENOSYS;
} }

View File

@ -1329,7 +1329,7 @@ static int cifs_get_fattr(struct cifs_open_info_data *data,
/* for easier reading */ /* for easier reading */
FILE_ALL_INFO *fi; FILE_ALL_INFO *fi;
FILE_DIRECTORY_INFO *fdi; FILE_DIRECTORY_INFO *fdi;
SEARCH_ID_FULL_DIR_INFO *si; FILE_ID_FULL_DIR_INFO *si;
rc = cifs_backup_query_path_info(xid, tcon, sb, rc = cifs_backup_query_path_info(xid, tcon, sb,
full_path, full_path,
@ -1340,7 +1340,7 @@ static int cifs_get_fattr(struct cifs_open_info_data *data,
move_cifs_info_to_smb2(&data->fi, fi); move_cifs_info_to_smb2(&data->fi, fi);
fdi = (FILE_DIRECTORY_INFO *)fi; fdi = (FILE_DIRECTORY_INFO *)fi;
si = (SEARCH_ID_FULL_DIR_INFO *)fi; si = (FILE_ID_FULL_DIR_INFO *)fi;
cifs_dir_info_to_fattr(fattr, fdi, cifs_sb); cifs_dir_info_to_fattr(fattr, fdi, cifs_sb);
fattr->cf_uniqueid = le64_to_cpu(si->UniqueId); fattr->cf_uniqueid = le64_to_cpu(si->UniqueId);

View File

@ -318,7 +318,7 @@ static int
check_smb_hdr(struct smb_hdr *smb) check_smb_hdr(struct smb_hdr *smb)
{ {
/* does it have the right SMB "signature" ? */ /* does it have the right SMB "signature" ? */
if (*(__le32 *) smb->Protocol != cpu_to_le32(0x424d53ff)) { if (*(__le32 *) smb->Protocol != SMB1_PROTO_NUMBER) {
cifs_dbg(VFS, "Bad protocol string signature header 0x%x\n", cifs_dbg(VFS, "Bad protocol string signature header 0x%x\n",
*(unsigned int *)smb->Protocol); *(unsigned int *)smb->Protocol);
return 1; return 1;

View File

@ -73,7 +73,7 @@ typedef struct _SECURITY_BUFFER {
__le16 Length; __le16 Length;
__le16 MaximumLength; __le16 MaximumLength;
__le32 BufferOffset; /* offset to buffer */ __le32 BufferOffset; /* offset to buffer */
} __attribute__((packed)) SECURITY_BUFFER; } __packed SECURITY_BUFFER;
typedef struct _NEGOTIATE_MESSAGE { typedef struct _NEGOTIATE_MESSAGE {
__u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
@ -85,7 +85,7 @@ typedef struct _NEGOTIATE_MESSAGE {
do not set the version is present flag */ do not set the version is present flag */
char DomainString[]; char DomainString[];
/* followed by WorkstationString */ /* followed by WorkstationString */
} __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE; } __packed NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
#define NTLMSSP_REVISION_W2K3 0x0F #define NTLMSSP_REVISION_W2K3 0x0F
@ -121,7 +121,7 @@ typedef struct _CHALLENGE_MESSAGE {
SECURITY_BUFFER TargetInfoArray; SECURITY_BUFFER TargetInfoArray;
/* SECURITY_BUFFER for version info not present since we /* SECURITY_BUFFER for version info not present since we
do not set the version is present flag */ do not set the version is present flag */
} __attribute__((packed)) CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE; } __packed CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
typedef struct _AUTHENTICATE_MESSAGE { typedef struct _AUTHENTICATE_MESSAGE {
__u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
@ -136,7 +136,7 @@ typedef struct _AUTHENTICATE_MESSAGE {
struct ntlmssp_version Version; struct ntlmssp_version Version;
/* SECURITY_BUFFER */ /* SECURITY_BUFFER */
char UserString[]; char UserString[];
} __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE; } __packed AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
/* /*
* Size of the session key (crypto key encrypted with the password * Size of the session key (crypto key encrypted with the password

View File

@ -98,7 +98,7 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
default: default:
break; break;
} }
} else if (fattr->cf_cifsattrs & ATTR_REPARSE) { } else if (fattr->cf_cifsattrs & ATTR_REPARSE_POINT) {
reparse_need_reval = true; reparse_need_reval = true;
} }
@ -138,7 +138,7 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
* reparse tag and ctime haven't changed. * reparse tag and ctime haven't changed.
*/ */
rc = 0; rc = 0;
if (fattr->cf_cifsattrs & ATTR_REPARSE) { if (fattr->cf_cifsattrs & ATTR_REPARSE_POINT) {
if (likely(reparse_inode_match(inode, fattr))) { if (likely(reparse_inode_match(inode, fattr))) {
fattr->cf_mode = inode->i_mode; fattr->cf_mode = inode->i_mode;
fattr->cf_rdev = inode->i_rdev; fattr->cf_rdev = inode->i_rdev;
@ -190,7 +190,7 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
* TODO: go through all documented reparse tags to see if we can * TODO: go through all documented reparse tags to see if we can
* reasonably map some of them to directories vs. files vs. symlinks * reasonably map some of them to directories vs. files vs. symlinks
*/ */
if ((fattr->cf_cifsattrs & ATTR_REPARSE) && if ((fattr->cf_cifsattrs & ATTR_REPARSE_POINT) &&
cifs_reparse_point_to_fattr(cifs_sb, fattr, &data)) cifs_reparse_point_to_fattr(cifs_sb, fattr, &data))
goto out_reparse; goto out_reparse;
@ -258,7 +258,7 @@ cifs_posix_to_fattr(struct cifs_fattr *fattr, struct smb2_posix_info *info,
fattr->cf_nlink = le32_to_cpu(info->HardLinks); fattr->cf_nlink = le32_to_cpu(info->HardLinks);
fattr->cf_cifsattrs = le32_to_cpu(info->DosAttributes); fattr->cf_cifsattrs = le32_to_cpu(info->DosAttributes);
if (fattr->cf_cifsattrs & ATTR_REPARSE) if (fattr->cf_cifsattrs & ATTR_REPARSE_POINT)
fattr->cf_cifstag = le32_to_cpu(info->ReparseTag); fattr->cf_cifstag = le32_to_cpu(info->ReparseTag);
/* The Mode field in the response can now include the file type as well */ /* The Mode field in the response can now include the file type as well */
@ -316,7 +316,7 @@ static void cifs_fulldir_info_to_fattr(struct cifs_fattr *fattr,
__dir_info_to_fattr(fattr, info); __dir_info_to_fattr(fattr, info);
/* See MS-FSCC 2.4.14, 2.4.19 */ /* See MS-FSCC 2.4.14, 2.4.19 */
if (fattr->cf_cifsattrs & ATTR_REPARSE) if (fattr->cf_cifsattrs & ATTR_REPARSE_POINT)
fattr->cf_cifstag = le32_to_cpu(di->EaSize); fattr->cf_cifstag = le32_to_cpu(di->EaSize);
cifs_fill_common_info(fattr, cifs_sb); cifs_fill_common_info(fattr, cifs_sb);
} }
@ -548,7 +548,7 @@ static void cifs_fill_dirent_full(struct cifs_dirent *de,
} }
static void cifs_fill_dirent_search(struct cifs_dirent *de, static void cifs_fill_dirent_search(struct cifs_dirent *de,
const SEARCH_ID_FULL_DIR_INFO *info) const FILE_ID_FULL_DIR_INFO *info)
{ {
de->name = &info->FileName[0]; de->name = &info->FileName[0];
de->namelen = le32_to_cpu(info->FileNameLength); de->namelen = le32_to_cpu(info->FileNameLength);

View File

@ -93,7 +93,7 @@ static inline bool reparse_inode_match(struct inode *inode,
if (cinode->reparse_tag != IO_REPARSE_TAG_INTERNAL && if (cinode->reparse_tag != IO_REPARSE_TAG_INTERNAL &&
cinode->reparse_tag != fattr->cf_cifstag) cinode->reparse_tag != fattr->cf_cifstag)
return false; return false;
return (cinode->cifsAttrs & ATTR_REPARSE) && return (cinode->cifsAttrs & ATTR_REPARSE_POINT) &&
timespec64_equal(&ctime, &fattr->cf_ctime); timespec64_equal(&ctime, &fattr->cf_ctime);
} }
@ -107,7 +107,7 @@ static inline bool cifs_open_data_reparse(struct cifs_open_info_data *data)
attrs = le32_to_cpu(fi->DosAttributes); attrs = le32_to_cpu(fi->DosAttributes);
if (data->reparse_point) { if (data->reparse_point) {
attrs |= ATTR_REPARSE; attrs |= ATTR_REPARSE_POINT;
fi->DosAttributes = cpu_to_le32(attrs); fi->DosAttributes = cpu_to_le32(attrs);
} }
@ -116,12 +116,12 @@ static inline bool cifs_open_data_reparse(struct cifs_open_info_data *data)
attrs = le32_to_cpu(fi->Attributes); attrs = le32_to_cpu(fi->Attributes);
if (data->reparse_point) { if (data->reparse_point) {
attrs |= ATTR_REPARSE; attrs |= ATTR_REPARSE_POINT;
fi->Attributes = cpu_to_le32(attrs); fi->Attributes = cpu_to_le32(attrs);
} }
} }
ret = attrs & ATTR_REPARSE; ret = attrs & ATTR_REPARSE_POINT;
return ret; return ret;
} }

View File

@ -33,17 +33,17 @@ struct rfc1002_session_packet {
__u8 calling_len; __u8 calling_len;
__u8 calling_name[32]; __u8 calling_name[32];
__u8 scope2; /* null */ __u8 scope2; /* null */
} __attribute__((packed)) session_req; } __packed session_req;
struct { struct {
__be32 retarget_ip_addr; __be32 retarget_ip_addr;
__be16 port; __be16 port;
} __attribute__((packed)) retarget_resp; } __packed retarget_resp;
__u8 neg_ses_resp_error_code; __u8 neg_ses_resp_error_code;
/* POSITIVE_SESSION_RESPONSE packet does not include trailer. /* POSITIVE_SESSION_RESPONSE packet does not include trailer.
SESSION_KEEP_ALIVE packet also does not include a trailer. SESSION_KEEP_ALIVE packet also does not include a trailer.
Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */ Trailer for the SESSION_MESSAGE packet is SMB/CIFS header */
} __attribute__((packed)) trailer; } __packed trailer;
} __attribute__((packed)); } __packed;
/* Negative Session Response error codes */ /* Negative Session Response error codes */
#define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */ #define RFC1002_NOT_LISTENING_CALLED 0x80 /* not listening on called name */

View File

@ -648,7 +648,7 @@ static int cifs_query_path_info(const unsigned int xid,
if (!rc) { if (!rc) {
move_cifs_info_to_smb2(&data->fi, &fi); move_cifs_info_to_smb2(&data->fi, &fi);
data->reparse_point = le32_to_cpu(fi.Attributes) & ATTR_REPARSE; data->reparse_point = le32_to_cpu(fi.Attributes) & ATTR_REPARSE_POINT;
} }
#ifdef CONFIG_CIFS_XATTR #ifdef CONFIG_CIFS_XATTR

View File

@ -50,7 +50,7 @@ static inline __u32 file_create_options(struct dentry *dentry)
if (dentry) { if (dentry) {
ci = CIFS_I(d_inode(dentry)); ci = CIFS_I(d_inode(dentry));
if (ci->cifsAttrs & ATTR_REPARSE) if (ci->cifsAttrs & ATTR_REPARSE_POINT)
return OPEN_REPARSE_POINT; return OPEN_REPARSE_POINT;
} }
return 0; return 0;

View File

@ -624,8 +624,8 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
struct network_interface_info_ioctl_rsp *p; struct network_interface_info_ioctl_rsp *p;
struct sockaddr_in *addr4; struct sockaddr_in *addr4;
struct sockaddr_in6 *addr6; struct sockaddr_in6 *addr6;
struct iface_info_ipv4 *p4; struct smb_sockaddr_in *p4;
struct iface_info_ipv6 *p6; struct smb_sockaddr_in6 *p6;
struct cifs_server_iface *info = NULL, *iface = NULL, *niface = NULL; struct cifs_server_iface *info = NULL, *iface = NULL, *niface = NULL;
struct cifs_server_iface tmp_iface; struct cifs_server_iface tmp_iface;
ssize_t bytes_left; ssize_t bytes_left;
@ -685,7 +685,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
*/ */
case INTERNETWORK: case INTERNETWORK:
addr4 = (struct sockaddr_in *)&tmp_iface.sockaddr; addr4 = (struct sockaddr_in *)&tmp_iface.sockaddr;
p4 = (struct iface_info_ipv4 *)p->Buffer; p4 = (struct smb_sockaddr_in *)p->Buffer;
addr4->sin_family = AF_INET; addr4->sin_family = AF_INET;
memcpy(&addr4->sin_addr, &p4->IPv4Address, 4); memcpy(&addr4->sin_addr, &p4->IPv4Address, 4);
@ -697,7 +697,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
break; break;
case INTERNETWORKV6: case INTERNETWORKV6:
addr6 = (struct sockaddr_in6 *)&tmp_iface.sockaddr; addr6 = (struct sockaddr_in6 *)&tmp_iface.sockaddr;
p6 = (struct iface_info_ipv6 *)p->Buffer; p6 = (struct smb_sockaddr_in6 *)p->Buffer;
addr6->sin6_family = AF_INET6; addr6->sin6_family = AF_INET6;
memcpy(&addr6->sin6_addr, &p6->IPv6Address, 16); memcpy(&addr6->sin6_addr, &p6->IPv6Address, 16);
@ -1524,11 +1524,11 @@ smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon,
static int static int
SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon, SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, u64 persistent_fid, u64 volatile_fid,
struct copychunk_ioctl *pcchunk) struct copychunk_ioctl_req *pcchunk)
{ {
int rc; int rc;
unsigned int ret_data_len; unsigned int ret_data_len;
struct resume_key_req *res_key; struct resume_key_ioctl_rsp *res_key;
rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid, rc = SMB2_ioctl(xid, tcon, persistent_fid, volatile_fid,
FSCTL_SRV_REQUEST_RESUME_KEY, NULL, 0 /* no input */, FSCTL_SRV_REQUEST_RESUME_KEY, NULL, 0 /* no input */,
@ -1541,7 +1541,7 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
cifs_tcon_dbg(VFS, "refcpy ioctl error %d getting resume key\n", rc); cifs_tcon_dbg(VFS, "refcpy ioctl error %d getting resume key\n", rc);
goto req_res_key_exit; goto req_res_key_exit;
} }
if (ret_data_len < sizeof(struct resume_key_req)) { if (ret_data_len < sizeof(struct resume_key_ioctl_rsp)) {
cifs_tcon_dbg(VFS, "Invalid refcopy resume key length\n"); cifs_tcon_dbg(VFS, "Invalid refcopy resume key length\n");
rc = -EINVAL; rc = -EINVAL;
goto req_res_key_exit; goto req_res_key_exit;
@ -1857,10 +1857,10 @@ smb2_copychunk_range(const unsigned int xid,
{ {
int rc = 0; int rc = 0;
unsigned int ret_data_len = 0; unsigned int ret_data_len = 0;
struct copychunk_ioctl *cc_req = NULL; struct copychunk_ioctl_req *cc_req = NULL;
struct copychunk_ioctl_rsp *cc_rsp = NULL; struct copychunk_ioctl_rsp *cc_rsp = NULL;
struct cifs_tcon *tcon; struct cifs_tcon *tcon;
struct copychunk *chunk; struct srv_copychunk *chunk;
u32 chunks, chunk_count, chunk_bytes; u32 chunks, chunk_count, chunk_bytes;
u32 copy_bytes, copy_bytes_left; u32 copy_bytes, copy_bytes_left;
u32 chunks_written, bytes_written; u32 chunks_written, bytes_written;
@ -4484,61 +4484,6 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
return rc; return rc;
} }
/*
* Clear a read buffer, discarding the folios which have the 1st mark set.
*/
static void cifs_clear_folioq_buffer(struct folio_queue *buffer)
{
struct folio_queue *folioq;
while ((folioq = buffer)) {
for (int s = 0; s < folioq_count(folioq); s++)
if (folioq_is_marked(folioq, s))
folio_put(folioq_folio(folioq, s));
buffer = folioq->next;
kfree(folioq);
}
}
/*
* Allocate buffer space into a folio queue.
*/
static struct folio_queue *cifs_alloc_folioq_buffer(ssize_t size)
{
struct folio_queue *buffer = NULL, *tail = NULL, *p;
struct folio *folio;
unsigned int slot;
do {
if (!tail || folioq_full(tail)) {
p = kmalloc(sizeof(*p), GFP_NOFS);
if (!p)
goto nomem;
folioq_init(p, 0);
if (tail) {
tail->next = p;
p->prev = tail;
} else {
buffer = p;
}
tail = p;
}
folio = folio_alloc(GFP_KERNEL|__GFP_HIGHMEM, 0);
if (!folio)
goto nomem;
slot = folioq_append_mark(tail, folio);
size -= folioq_folio_size(tail, slot);
} while (size > 0);
return buffer;
nomem:
cifs_clear_folioq_buffer(buffer);
return NULL;
}
/* /*
* Copy data from an iterator to the folios in a folio queue buffer. * Copy data from an iterator to the folios in a folio queue buffer.
*/ */
@ -4564,7 +4509,7 @@ void
smb3_free_compound_rqst(int num_rqst, struct smb_rqst *rqst) smb3_free_compound_rqst(int num_rqst, struct smb_rqst *rqst)
{ {
for (int i = 0; i < num_rqst; i++) for (int i = 0; i < num_rqst; i++)
cifs_clear_folioq_buffer(rqst[i].rq_buffer); netfs_free_folioq_buffer(rqst[i].rq_buffer);
} }
/* /*
@ -4599,8 +4544,10 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, int num_rqst,
new->rq_nvec = old->rq_nvec; new->rq_nvec = old->rq_nvec;
if (size > 0) { if (size > 0) {
buffer = cifs_alloc_folioq_buffer(size); size_t cur_size = 0;
if (!buffer) rc = netfs_alloc_folioq_buffer(NULL, &buffer, &cur_size,
size, GFP_NOFS);
if (rc < 0)
goto err_free; goto err_free;
new->rq_buffer = buffer; new->rq_buffer = buffer;
@ -4932,7 +4879,7 @@ static void smb2_decrypt_offload(struct work_struct *work)
} }
free_pages: free_pages:
cifs_clear_folioq_buffer(dw->buffer); netfs_free_folioq_buffer(dw->buffer);
cifs_small_buf_release(dw->buf); cifs_small_buf_release(dw->buf);
kfree(dw); kfree(dw);
} }
@ -4970,9 +4917,9 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid,
dw->len = len; dw->len = len;
len = round_up(dw->len, PAGE_SIZE); len = round_up(dw->len, PAGE_SIZE);
rc = -ENOMEM; size_t cur_size = 0;
dw->buffer = cifs_alloc_folioq_buffer(len); rc = netfs_alloc_folioq_buffer(NULL, &dw->buffer, &cur_size, len, GFP_NOFS);
if (!dw->buffer) if (rc < 0)
goto discard_data; goto discard_data;
iov_iter_folio_queue(&iter, ITER_DEST, dw->buffer, 0, 0, len); iov_iter_folio_queue(&iter, ITER_DEST, dw->buffer, 0, 0, len);
@ -5033,7 +4980,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid,
} }
free_pages: free_pages:
cifs_clear_folioq_buffer(dw->buffer); netfs_free_folioq_buffer(dw->buffer);
free_dw: free_dw:
kfree(dw); kfree(dw);
return rc; return rc;

View File

@ -2229,21 +2229,20 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
return rc; return rc;
} }
static create_durable_req_t *
static struct create_durable *
create_durable_buf(void) create_durable_buf(void)
{ {
struct create_durable *buf; create_durable_req_t *buf;
buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL); buf = kzalloc(sizeof(create_durable_req_t), GFP_KERNEL);
if (!buf) if (!buf)
return NULL; return NULL;
buf->ccontext.DataOffset = cpu_to_le16(offsetof buf->ccontext.DataOffset = cpu_to_le16(offsetof
(struct create_durable, Data)); (create_durable_req_t, Data));
buf->ccontext.DataLength = cpu_to_le32(16); buf->ccontext.DataLength = cpu_to_le32(16);
buf->ccontext.NameOffset = cpu_to_le16(offsetof buf->ccontext.NameOffset = cpu_to_le16(offsetof
(struct create_durable, Name)); (create_durable_req_t, Name));
buf->ccontext.NameLength = cpu_to_le16(4); buf->ccontext.NameLength = cpu_to_le16(4);
/* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DHnQ" */ /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DHnQ" */
buf->Name[0] = 'D'; buf->Name[0] = 'D';
@ -2253,20 +2252,20 @@ create_durable_buf(void)
return buf; return buf;
} }
static struct create_durable * static create_durable_req_t *
create_reconnect_durable_buf(struct cifs_fid *fid) create_reconnect_durable_buf(struct cifs_fid *fid)
{ {
struct create_durable *buf; create_durable_req_t *buf;
buf = kzalloc(sizeof(struct create_durable), GFP_KERNEL); buf = kzalloc(sizeof(create_durable_req_t), GFP_KERNEL);
if (!buf) if (!buf)
return NULL; return NULL;
buf->ccontext.DataOffset = cpu_to_le16(offsetof buf->ccontext.DataOffset = cpu_to_le16(offsetof
(struct create_durable, Data)); (create_durable_req_t, Data));
buf->ccontext.DataLength = cpu_to_le32(16); buf->ccontext.DataLength = cpu_to_le32(16);
buf->ccontext.NameOffset = cpu_to_le16(offsetof buf->ccontext.NameOffset = cpu_to_le16(offsetof
(struct create_durable, Name)); (create_durable_req_t, Name));
buf->ccontext.NameLength = cpu_to_le16(4); buf->ccontext.NameLength = cpu_to_le16(4);
buf->Data.Fid.PersistentFileId = fid->persistent_fid; buf->Data.Fid.PersistentFileId = fid->persistent_fid;
buf->Data.Fid.VolatileFileId = fid->volatile_fid; buf->Data.Fid.VolatileFileId = fid->volatile_fid;
@ -2424,21 +2423,21 @@ add_lease_context(struct TCP_Server_Info *server,
return 0; return 0;
} }
static struct create_durable_v2 * static struct create_durable_req_v2 *
create_durable_v2_buf(struct cifs_open_parms *oparms) create_durable_v2_buf(struct cifs_open_parms *oparms)
{ {
struct cifs_fid *pfid = oparms->fid; struct cifs_fid *pfid = oparms->fid;
struct create_durable_v2 *buf; struct create_durable_req_v2 *buf;
buf = kzalloc(sizeof(struct create_durable_v2), GFP_KERNEL); buf = kzalloc(sizeof(struct create_durable_req_v2), GFP_KERNEL);
if (!buf) if (!buf)
return NULL; return NULL;
buf->ccontext.DataOffset = cpu_to_le16(offsetof buf->ccontext.DataOffset = cpu_to_le16(offsetof
(struct create_durable_v2, dcontext)); (struct create_durable_req_v2, dcontext));
buf->ccontext.DataLength = cpu_to_le32(sizeof(struct durable_context_v2)); buf->ccontext.DataLength = cpu_to_le32(sizeof(struct durable_context_v2_req));
buf->ccontext.NameOffset = cpu_to_le16(offsetof buf->ccontext.NameOffset = cpu_to_le16(offsetof
(struct create_durable_v2, Name)); (struct create_durable_req_v2, Name));
buf->ccontext.NameLength = cpu_to_le16(4); buf->ccontext.NameLength = cpu_to_le16(4);
/* /*
@ -2508,7 +2507,7 @@ add_durable_v2_context(struct kvec *iov, unsigned int *num_iovec,
iov[num].iov_base = create_durable_v2_buf(oparms); iov[num].iov_base = create_durable_v2_buf(oparms);
if (iov[num].iov_base == NULL) if (iov[num].iov_base == NULL)
return -ENOMEM; return -ENOMEM;
iov[num].iov_len = sizeof(struct create_durable_v2); iov[num].iov_len = sizeof(struct create_durable_req_v2);
*num_iovec = num + 1; *num_iovec = num + 1;
return 0; return 0;
} }
@ -2552,7 +2551,7 @@ add_durable_context(struct kvec *iov, unsigned int *num_iovec,
iov[num].iov_base = create_durable_buf(); iov[num].iov_base = create_durable_buf();
if (iov[num].iov_base == NULL) if (iov[num].iov_base == NULL)
return -ENOMEM; return -ENOMEM;
iov[num].iov_len = sizeof(struct create_durable); iov[num].iov_len = sizeof(create_durable_req_t);
*num_iovec = num + 1; *num_iovec = num + 1;
return 0; return 0;
} }
@ -5454,7 +5453,7 @@ smb2_parse_query_directory(struct cifs_tcon *tcon,
info_buf_size = sizeof(FILE_DIRECTORY_INFO); info_buf_size = sizeof(FILE_DIRECTORY_INFO);
break; break;
case SMB_FIND_FILE_ID_FULL_DIR_INFO: case SMB_FIND_FILE_ID_FULL_DIR_INFO:
info_buf_size = sizeof(SEARCH_ID_FULL_DIR_INFO); info_buf_size = sizeof(FILE_ID_FULL_DIR_INFO);
break; break;
case SMB_FIND_FILE_POSIX_INFO: case SMB_FIND_FILE_POSIX_INFO:
/* note that posix payload are variable size */ /* note that posix payload are variable size */
@ -5982,8 +5981,8 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
max_len = sizeof(FILE_SYSTEM_DEVICE_INFO); max_len = sizeof(FILE_SYSTEM_DEVICE_INFO);
min_len = sizeof(FILE_SYSTEM_DEVICE_INFO); min_len = sizeof(FILE_SYSTEM_DEVICE_INFO);
} else if (level == FS_ATTRIBUTE_INFORMATION) { } else if (level == FS_ATTRIBUTE_INFORMATION) {
max_len = sizeof(FILE_SYSTEM_ATTRIBUTE_INFO); max_len = sizeof(FILE_SYSTEM_ATTRIBUTE_INFO) + MAX_FS_NAME_LEN;
min_len = MIN_FS_ATTR_INFO_SIZE; min_len = sizeof(FILE_SYSTEM_ATTRIBUTE_INFO);
} else if (level == FS_SECTOR_SIZE_INFORMATION) { } else if (level == FS_SECTOR_SIZE_INFORMATION) {
max_len = sizeof(struct smb3_fs_ss_info); max_len = sizeof(struct smb3_fs_ss_info);
min_len = sizeof(struct smb3_fs_ss_info); min_len = sizeof(struct smb3_fs_ss_info);
@ -6029,7 +6028,7 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
if (level == FS_ATTRIBUTE_INFORMATION) if (level == FS_ATTRIBUTE_INFORMATION)
memcpy(&tcon->fsAttrInfo, offset memcpy(&tcon->fsAttrInfo, offset
+ (char *)rsp, min_t(unsigned int, + (char *)rsp, min_t(unsigned int,
rsp_len, max_len)); rsp_len, min_len));
else if (level == FS_DEVICE_INFORMATION) else if (level == FS_DEVICE_INFORMATION)
memcpy(&tcon->fsDevInfo, offset memcpy(&tcon->fsDevInfo, offset
+ (char *)rsp, sizeof(FILE_SYSTEM_DEVICE_INFO)); + (char *)rsp, sizeof(FILE_SYSTEM_DEVICE_INFO));

View File

@ -133,46 +133,6 @@ struct share_redirect_error_context_rsp {
#define SMB2_LEASE_HANDLE_CACHING_HE 0x02 #define SMB2_LEASE_HANDLE_CACHING_HE 0x02
#define SMB2_LEASE_WRITE_CACHING_HE 0x04 #define SMB2_LEASE_WRITE_CACHING_HE 0x04
/* See MS-SMB2 2.2.13.2.11 */
/* Flags */
#define SMB2_DHANDLE_FLAG_PERSISTENT 0x00000002
struct durable_context_v2 {
__le32 Timeout;
__le32 Flags;
__u64 Reserved;
__u8 CreateGuid[16];
} __packed;
struct create_durable_v2 {
struct create_context_hdr ccontext;
__u8 Name[8];
struct durable_context_v2 dcontext;
} __packed;
/* See MS-SMB2 2.2.13.2.12 */
struct durable_reconnect_context_v2 {
struct {
__u64 PersistentFileId;
__u64 VolatileFileId;
} Fid;
__u8 CreateGuid[16];
__le32 Flags; /* see above DHANDLE_FLAG_PERSISTENT */
} __packed;
/* See MS-SMB2 2.2.14.2.12 */
struct durable_reconnect_context_v2_rsp {
__le32 Timeout;
__le32 Flags; /* see above DHANDLE_FLAG_PERSISTENT */
} __packed;
struct create_durable_handle_reconnect_v2 {
struct create_context_hdr ccontext;
__u8 Name[8];
struct durable_reconnect_context_v2 dcontext;
__u8 Pad[4];
} __packed;
/* See MS-SMB2 2.2.13.2.5 */ /* See MS-SMB2 2.2.13.2.5 */
struct crt_twarp_ctxt { struct crt_twarp_ctxt {
struct create_context_hdr ccontext; struct create_context_hdr ccontext;
@ -193,36 +153,6 @@ struct crt_sd_ctxt {
struct smb3_sd sd; struct smb3_sd sd;
} __packed; } __packed;
#define COPY_CHUNK_RES_KEY_SIZE 24
struct resume_key_req {
char ResumeKey[COPY_CHUNK_RES_KEY_SIZE];
__le32 ContextLength; /* MBZ */
char Context[]; /* ignored, Windows sets to 4 bytes of zero */
} __packed;
struct copychunk {
__le64 SourceOffset;
__le64 TargetOffset;
__le32 Length;
__le32 Reserved;
} __packed;
/* this goes in the ioctl buffer when doing a copychunk request */
struct copychunk_ioctl {
char SourceKey[COPY_CHUNK_RES_KEY_SIZE];
__le32 ChunkCount;
__le32 Reserved;
struct copychunk Chunks[];
} __packed;
struct copychunk_ioctl_rsp {
__le32 ChunksWritten;
__le32 ChunkBytesWritten;
__le32 TotalBytesWritten;
} __packed;
/* See MS-FSCC 2.3.29 and 2.3.30 */ /* See MS-FSCC 2.3.29 and 2.3.30 */
struct get_retrieval_pointer_count_req { struct get_retrieval_pointer_count_req {
__le64 StartingVcn; /* virtual cluster number (signed) */ __le64 StartingVcn; /* virtual cluster number (signed) */
@ -263,35 +193,6 @@ struct network_resiliency_req {
} __packed; } __packed;
/* There is no buffer for the response ie no struct network_resiliency_rsp */ /* There is no buffer for the response ie no struct network_resiliency_rsp */
#define RSS_CAPABLE cpu_to_le32(0x00000001)
#define RDMA_CAPABLE cpu_to_le32(0x00000002)
#define INTERNETWORK cpu_to_le16(0x0002)
#define INTERNETWORKV6 cpu_to_le16(0x0017)
struct network_interface_info_ioctl_rsp {
__le32 Next; /* next interface. zero if this is last one */
__le32 IfIndex;
__le32 Capability; /* RSS or RDMA Capable */
__le32 Reserved;
__le64 LinkSpeed;
__le16 Family;
__u8 Buffer[126];
} __packed;
struct iface_info_ipv4 {
__be16 Port;
__be32 IPv4Address;
__be64 Reserved;
} __packed;
struct iface_info_ipv6 {
__be16 Port;
__be32 FlowInfo;
__u8 IPv6Address[16];
__be32 ScopeId;
} __packed;
#define NO_FILE_ID 0xFFFFFFFFFFFFFFFFULL /* general ioctls to srv not to file */ #define NO_FILE_ID 0xFFFFFFFFFFFFFFFFULL /* general ioctls to srv not to file */
struct compress_ioctl { struct compress_ioctl {
@ -323,19 +224,6 @@ struct smb2_file_reparse_point_info {
__le32 Tag; __le32 Tag;
} __packed; } __packed;
struct smb2_file_network_open_info {
struct_group_attr(network_open_info, __packed,
__le64 CreationTime;
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le64 AllocationSize;
__le64 EndOfFile;
__le32 Attributes;
);
__le32 Reserved;
} __packed; /* level 34 Query also similar returned in close rsp and open rsp */
/* See MS-FSCC 2.4.21 */ /* See MS-FSCC 2.4.21 */
struct smb2_file_id_information { struct smb2_file_id_information {
__le64 VolumeSerialNumber; __le64 VolumeSerialNumber;

View File

@ -7,6 +7,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/highmem.h> #include <linux/highmem.h>
#include <linux/folio_queue.h> #include <linux/folio_queue.h>
#define __SMBDIRECT_SOCKET_DISCONNECT(__sc) smbd_disconnect_rdma_connection(__sc)
#include "../common/smbdirect/smbdirect_pdu.h" #include "../common/smbdirect/smbdirect_pdu.h"
#include "smbdirect.h" #include "smbdirect.h"
#include "cifs_debug.h" #include "cifs_debug.h"
@ -186,6 +187,9 @@ static void smbd_disconnect_rdma_work(struct work_struct *work)
struct smbdirect_socket *sc = struct smbdirect_socket *sc =
container_of(work, struct smbdirect_socket, disconnect_work); container_of(work, struct smbdirect_socket, disconnect_work);
if (sc->first_error == 0)
sc->first_error = -ECONNABORTED;
/* /*
* make sure this and other work is not queued again * make sure this and other work is not queued again
* but here we don't block and avoid * but here we don't block and avoid
@ -197,9 +201,6 @@ static void smbd_disconnect_rdma_work(struct work_struct *work)
disable_work(&sc->idle.immediate_work); disable_work(&sc->idle.immediate_work);
disable_delayed_work(&sc->idle.timer_work); disable_delayed_work(&sc->idle.timer_work);
if (sc->first_error == 0)
sc->first_error = -ECONNABORTED;
switch (sc->status) { switch (sc->status) {
case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED: case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED:
case SMBDIRECT_SOCKET_NEGOTIATE_RUNNING: case SMBDIRECT_SOCKET_NEGOTIATE_RUNNING:
@ -242,6 +243,9 @@ static void smbd_disconnect_rdma_work(struct work_struct *work)
static void smbd_disconnect_rdma_connection(struct smbdirect_socket *sc) static void smbd_disconnect_rdma_connection(struct smbdirect_socket *sc)
{ {
if (sc->first_error == 0)
sc->first_error = -ECONNABORTED;
/* /*
* make sure other work (than disconnect_work) is * make sure other work (than disconnect_work) is
* not queued again but here we don't block and avoid * not queued again but here we don't block and avoid
@ -252,9 +256,6 @@ static void smbd_disconnect_rdma_connection(struct smbdirect_socket *sc)
disable_work(&sc->idle.immediate_work); disable_work(&sc->idle.immediate_work);
disable_delayed_work(&sc->idle.timer_work); disable_delayed_work(&sc->idle.timer_work);
if (sc->first_error == 0)
sc->first_error = -ECONNABORTED;
switch (sc->status) { switch (sc->status) {
case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED: case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED:
case SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED: case SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED:
@ -322,27 +323,27 @@ static int smbd_conn_upcall(
switch (event->event) { switch (event->event) {
case RDMA_CM_EVENT_ADDR_RESOLVED: case RDMA_CM_EVENT_ADDR_RESOLVED:
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING); if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING))
break;
sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED; sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_NEEDED;
wake_up(&sc->status_wait); wake_up(&sc->status_wait);
break; break;
case RDMA_CM_EVENT_ROUTE_RESOLVED: case RDMA_CM_EVENT_ROUTE_RESOLVED:
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING); if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING))
break;
sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED; sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_NEEDED;
wake_up(&sc->status_wait); wake_up(&sc->status_wait);
break; break;
case RDMA_CM_EVENT_ADDR_ERROR: case RDMA_CM_EVENT_ADDR_ERROR:
log_rdma_event(ERR, "connecting failed event=%s\n", event_name); log_rdma_event(ERR, "connecting failed event=%s\n", event_name);
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ADDR_RUNNING);
sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED; sc->status = SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED;
smbd_disconnect_rdma_work(&sc->disconnect_work); smbd_disconnect_rdma_work(&sc->disconnect_work);
break; break;
case RDMA_CM_EVENT_ROUTE_ERROR: case RDMA_CM_EVENT_ROUTE_ERROR:
log_rdma_event(ERR, "connecting failed event=%s\n", event_name); log_rdma_event(ERR, "connecting failed event=%s\n", event_name);
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RESOLVE_ROUTE_RUNNING);
sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED; sc->status = SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED;
smbd_disconnect_rdma_work(&sc->disconnect_work); smbd_disconnect_rdma_work(&sc->disconnect_work);
break; break;
@ -428,7 +429,8 @@ static int smbd_conn_upcall(
min_t(u8, sp->responder_resources, min_t(u8, sp->responder_resources,
peer_responder_resources); peer_responder_resources);
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING); if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING))
break;
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED; sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED;
wake_up(&sc->status_wait); wake_up(&sc->status_wait);
break; break;
@ -437,7 +439,6 @@ static int smbd_conn_upcall(
case RDMA_CM_EVENT_UNREACHABLE: case RDMA_CM_EVENT_UNREACHABLE:
case RDMA_CM_EVENT_REJECTED: case RDMA_CM_EVENT_REJECTED:
log_rdma_event(ERR, "connecting failed event=%s\n", event_name); log_rdma_event(ERR, "connecting failed event=%s\n", event_name);
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING);
sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED; sc->status = SMBDIRECT_SOCKET_RDMA_CONNECT_FAILED;
smbd_disconnect_rdma_work(&sc->disconnect_work); smbd_disconnect_rdma_work(&sc->disconnect_work);
break; break;
@ -699,7 +700,8 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
negotiate_done = negotiate_done =
process_negotiation_response(response, wc->byte_len); process_negotiation_response(response, wc->byte_len);
put_receive_buffer(sc, response); put_receive_buffer(sc, response);
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_NEGOTIATE_RUNNING); if (SMBDIRECT_CHECK_STATUS_WARN(sc, SMBDIRECT_SOCKET_NEGOTIATE_RUNNING))
negotiate_done = false;
if (!negotiate_done) { if (!negotiate_done) {
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED; sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED;
smbd_disconnect_rdma_connection(sc); smbd_disconnect_rdma_connection(sc);

View File

@ -1,30 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1 */
/*
*
* Copyright (C) International Business Machines Corp., 2002,2008
* Author(s): Steve French (sfrench@us.ibm.com)
* Jeremy Allison (jra@samba.org)
*
*/
#ifndef _COMMON_CIFS_GLOB_H
#define _COMMON_CIFS_GLOB_H
static inline void inc_rfc1001_len(void *buf, int count)
{
be32_add_cpu((__be32 *)buf, count);
}
#define SMB1_VERSION_STRING "1.0"
#define SMB20_VERSION_STRING "2.0"
#define SMB21_VERSION_STRING "2.1"
#define SMBDEFAULT_VERSION_STRING "default"
#define SMB3ANY_VERSION_STRING "3"
#define SMB30_VERSION_STRING "3.0"
#define SMB302_VERSION_STRING "3.02"
#define ALT_SMB302_VERSION_STRING "3.0.2"
#define SMB311_VERSION_STRING "3.1.1"
#define ALT_SMB311_VERSION_STRING "3.11"
#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
#endif /* _COMMON_CIFS_GLOB_H */

174
fs/smb/common/fscc.h Normal file
View File

@ -0,0 +1,174 @@
/* SPDX-License-Identifier: LGPL-2.1 */
/*
*
* Copyright (c) International Business Machines Corp., 2009, 2013
* Etersoft, 2012
* 2018 Samsung Electronics Co., Ltd.
* Author(s): Steve French (sfrench@us.ibm.com)
* Pavel Shilovsky (pshilovsky@samba.org) 2012
* Namjae Jeon (linkinjeon@kernel.org)
*
*/
#ifndef _COMMON_SMB_FSCC_H
#define _COMMON_SMB_FSCC_H
/* See MS-FSCC 2.4.8 */
typedef struct {
__le32 NextEntryOffset;
__u32 FileIndex;
__le64 CreationTime;
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le64 EndOfFile;
__le64 AllocationSize;
__le32 ExtFileAttributes;
__le32 FileNameLength;
__le32 EaSize; /* length of the xattrs */
__u8 ShortNameLength;
__u8 Reserved;
__u8 ShortName[24];
char FileName[];
} __packed FILE_BOTH_DIRECTORY_INFO; /* level 0x104 FFrsp data */
/* See MS-FSCC 2.4.10 */
typedef struct {
__le32 NextEntryOffset;
__u32 FileIndex;
__le64 CreationTime;
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le64 EndOfFile;
__le64 AllocationSize;
__le32 ExtFileAttributes;
__le32 FileNameLength;
char FileName[];
} __packed FILE_DIRECTORY_INFO; /* level 0x101 FF resp data */
/* See MS-FSCC 2.4.14 */
typedef struct {
__le32 NextEntryOffset;
__u32 FileIndex;
__le64 CreationTime;
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le64 EndOfFile;
__le64 AllocationSize;
__le32 ExtFileAttributes;
__le32 FileNameLength;
__le32 EaSize; /* length of the xattrs */
char FileName[];
} __packed FILE_FULL_DIRECTORY_INFO; /* level 0x102 rsp data */
/* See MS-FSCC 2.4.24 */
typedef struct {
__le32 NextEntryOffset;
__u32 FileIndex;
__le64 CreationTime;
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le64 EndOfFile;
__le64 AllocationSize;
__le32 ExtFileAttributes;
__le32 FileNameLength;
__le32 EaSize; /* EA size */
__le32 Reserved;
__le64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
char FileName[];
} __packed FILE_ID_FULL_DIR_INFO; /* level 0x105 FF rsp data */
/* See MS-FSCC 2.4.34 */
struct smb2_file_network_open_info {
struct_group_attr(network_open_info, __packed,
__le64 CreationTime;
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le64 AllocationSize;
__le64 EndOfFile;
__le32 Attributes;
);
__le32 Reserved;
} __packed; /* level 34 Query also similar returned in close rsp and open rsp */
/* See MS-FSCC 2.5.1 */
#define MAX_FS_NAME_LEN 52
typedef struct {
__le32 Attributes;
__le32 MaxPathNameComponentLength;
__le32 FileSystemNameLen;
__le16 FileSystemName[]; /* do not have to save this - get subset? */
} __packed FILE_SYSTEM_ATTRIBUTE_INFO;
/* List of FileSystemAttributes - see MS-FSCC 2.5.1 */
#define FILE_SUPPORTS_SPARSE_VDL 0x10000000 /* faster nonsparse extend */
#define FILE_SUPPORTS_BLOCK_REFCOUNTING 0x08000000 /* allow ioctl dup extents */
#define FILE_SUPPORT_INTEGRITY_STREAMS 0x04000000
#define FILE_SUPPORTS_USN_JOURNAL 0x02000000
#define FILE_SUPPORTS_OPEN_BY_FILE_ID 0x01000000
#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES 0x00800000
#define FILE_SUPPORTS_HARD_LINKS 0x00400000
#define FILE_SUPPORTS_TRANSACTIONS 0x00200000
#define FILE_SEQUENTIAL_WRITE_ONCE 0x00100000
#define FILE_READ_ONLY_VOLUME 0x00080000
#define FILE_NAMED_STREAMS 0x00040000
#define FILE_SUPPORTS_ENCRYPTION 0x00020000
#define FILE_SUPPORTS_OBJECT_IDS 0x00010000
#define FILE_VOLUME_IS_COMPRESSED 0x00008000
#define FILE_SUPPORTS_POSIX_UNLINK_RENAME 0x00000400
#define FILE_RETURNS_CLEANUP_RESULT_INFO 0x00000200
#define FILE_SUPPORTS_REMOTE_STORAGE 0x00000100
#define FILE_SUPPORTS_REPARSE_POINTS 0x00000080
#define FILE_SUPPORTS_SPARSE_FILES 0x00000040
#define FILE_VOLUME_QUOTAS 0x00000020
#define FILE_FILE_COMPRESSION 0x00000010
#define FILE_PERSISTENT_ACLS 0x00000008
#define FILE_UNICODE_ON_DISK 0x00000004
#define FILE_CASE_PRESERVED_NAMES 0x00000002
#define FILE_CASE_SENSITIVE_SEARCH 0x00000001
/* See MS-FSCC 2.5.8 */
typedef struct {
__le64 TotalAllocationUnits;
__le64 AvailableAllocationUnits;
__le32 SectorsPerAllocationUnit;
__le32 BytesPerSector;
} __packed FILE_SYSTEM_SIZE_INFO; /* size info, level 0x103 */
/* See MS-FSCC 2.5.10 */
typedef struct {
__le32 DeviceType;
__le32 DeviceCharacteristics;
} __packed FILE_SYSTEM_DEVICE_INFO; /* device info level 0x104 */
/*
* See POSIX Extensions to MS-FSCC 2.3.2.1
* Link: https://gitlab.com/samba-team/smb3-posix-spec/-/blob/master/fscc_posix_extensions.md
*/
typedef struct {
/* For undefined recommended transfer size return -1 in that field */
__le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
__le32 BlockSize;
/* The next three fields are in terms of the block size.
* (above). If block size is unknown, 4096 would be a
* reasonable block size for a server to report.
* Note that returning the blocks/blocksavail removes need
* to make a second call (to QFSInfo level 0x103 to get this info.
* UserBlockAvail is typically less than or equal to BlocksAvail,
* if no distinction is made return the same value in each
*/
__le64 TotalBlocks;
__le64 BlocksAvail; /* bfree */
__le64 UserBlocksAvail; /* bavail */
/* For undefined Node fields or FSID return -1 */
__le64 TotalFileNodes;
__le64 FreeFileNodes;
__le64 FileSysIdentifier; /* fsid */
/* NB Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call */
/* NB flags can come from FILE_SYSTEM_DEVICE_INFO call */
} __packed FILE_SYSTEM_POSIX_INFO;
#endif /* _COMMON_SMB_FSCC_H */

View File

@ -1149,12 +1149,6 @@ struct smb2_server_client_notification {
#define FILE_OVERWRITE_IF_LE cpu_to_le32(0x00000005) #define FILE_OVERWRITE_IF_LE cpu_to_le32(0x00000005)
#define FILE_CREATE_MASK_LE cpu_to_le32(0x00000007) #define FILE_CREATE_MASK_LE cpu_to_le32(0x00000007)
#define FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA \
| FILE_READ_ATTRIBUTES)
#define FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
| FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
#define FILE_EXEC_RIGHTS (FILE_EXECUTE)
/* CreateOptions Flags */ /* CreateOptions Flags */
#define FILE_DIRECTORY_FILE_LE cpu_to_le32(0x00000001) #define FILE_DIRECTORY_FILE_LE cpu_to_le32(0x00000001)
/* same as #define CREATE_NOT_FILE_LE cpu_to_le32(0x00000001) */ /* same as #define CREATE_NOT_FILE_LE cpu_to_le32(0x00000001) */
@ -1271,7 +1265,7 @@ struct create_posix {
} __packed; } __packed;
/* See MS-SMB2 2.2.13.2.3 and MS-SMB2 2.2.13.2.4 */ /* See MS-SMB2 2.2.13.2.3 and MS-SMB2 2.2.13.2.4 */
struct create_durable { typedef struct {
struct create_context_hdr ccontext; struct create_context_hdr ccontext;
__u8 Name[8]; __u8 Name[8];
union { union {
@ -1281,7 +1275,7 @@ struct create_durable {
__u64 VolatileFileId; __u64 VolatileFileId;
} Fid; } Fid;
} Data; } Data;
} __packed; } __packed create_durable_req_t, create_durable_reconn_t;
/* See MS-SMB2 2.2.13.2.5 */ /* See MS-SMB2 2.2.13.2.5 */
struct create_mxac_req { struct create_mxac_req {
@ -1290,6 +1284,56 @@ struct create_mxac_req {
__le64 Timestamp; __le64 Timestamp;
} __packed; } __packed;
/*
* Flags
* See MS-SMB2 2.2.13.2.11
* MS-SMB2 2.2.13.2.12
* MS-SMB2 2.2.14.2.12
*/
#define SMB2_DHANDLE_FLAG_PERSISTENT 0x00000002
/* See MS-SMB2 2.2.13.2.11 */
struct durable_context_v2_req {
__le32 Timeout;
__le32 Flags; /* see SMB2_DHANDLE_FLAG_PERSISTENT */
__u64 Reserved;
__u8 CreateGuid[16];
} __packed;
struct create_durable_req_v2 {
struct create_context_hdr ccontext;
__u8 Name[8];
struct durable_context_v2_req dcontext;
} __packed;
/* See MS-SMB2 2.2.13.2.12 */
struct durable_reconnect_context_v2 {
struct {
__u64 PersistentFileId;
__u64 VolatileFileId;
} Fid;
__u8 CreateGuid[16];
__le32 Flags; /* see SMB2_DHANDLE_FLAG_PERSISTENT */
} __packed;
struct create_durable_handle_reconnect_v2 {
struct create_context_hdr ccontext;
__u8 Name[8];
struct durable_reconnect_context_v2 dcontext;
} __packed;
/* See MS-SMB2 2.2.14.2.12 */
struct durable_context_v2_rsp {
__le32 Timeout;
__le32 Flags; /* see SMB2_DHANDLE_FLAG_PERSISTENT */
} __packed;
struct create_durable_rsp_v2 {
struct create_context_hdr ccontext;
__u8 Name[8];
struct durable_context_v2_rsp dcontext;
} __packed;
/* See MS-SMB2 2.2.14.2.5 */ /* See MS-SMB2 2.2.14.2.5 */
struct create_mxac_rsp { struct create_mxac_rsp {
struct create_context_hdr ccontext; struct create_context_hdr ccontext;
@ -1388,6 +1432,45 @@ struct smb2_ioctl_req {
__u8 Buffer[]; __u8 Buffer[];
} __packed; } __packed;
/* See MS-SMB2 2.2.31.1.1 */
struct srv_copychunk {
__le64 SourceOffset;
__le64 TargetOffset;
__le32 Length;
__le32 Reserved;
} __packed;
#define COPY_CHUNK_RES_KEY_SIZE 24
/* See MS-SMB2 2.2.31.1 */
/* this goes in the ioctl buffer when doing a copychunk request */
struct copychunk_ioctl_req {
union {
char SourceKey[COPY_CHUNK_RES_KEY_SIZE];
__le64 SourceKeyU64[3];
};
__le32 ChunkCount;
__le32 Reserved;
struct srv_copychunk Chunks[] __counted_by_le(ChunkCount);
} __packed;
/* See MS-SMB2 2.2.32.1 */
struct copychunk_ioctl_rsp {
__le32 ChunksWritten;
__le32 ChunkBytesWritten;
__le32 TotalBytesWritten;
} __packed;
/* See MS-SMB2 2.2.32.3 */
struct resume_key_ioctl_rsp {
union {
char ResumeKey[COPY_CHUNK_RES_KEY_SIZE];
__u64 ResumeKeyU64[3];
};
__le32 ContextLength; /* MBZ */
char Context[]; /* ignored, Windows sets to 4 bytes of zero */
} __packed;
struct smb2_ioctl_rsp { struct smb2_ioctl_rsp {
struct smb2_hdr hdr; struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 49 */ __le16 StructureSize; /* Must be 49 */
@ -1404,6 +1487,41 @@ struct smb2_ioctl_rsp {
__u8 Buffer[]; __u8 Buffer[];
} __packed; } __packed;
/* See MS-SMB2 2.2.32.5.1.1 */
struct smb_sockaddr_in {
__be16 Port;
__be32 IPv4Address;
__u8 Reserved[8];
} __packed;
/* See MS-SMB2 2.2.32.5.1.2 */
struct smb_sockaddr_in6 {
__be16 Port;
__be32 FlowInfo;
__u8 IPv6Address[16];
__be32 ScopeId;
} __packed;
/* See MS-SMB2 2.2.32.5 and MS-SMB2 2.2.32.5.1 */
#define RSS_CAPABLE cpu_to_le32(0x00000001)
#define RDMA_CAPABLE cpu_to_le32(0x00000002)
#define INTERNETWORK cpu_to_le16(0x0002)
#define INTERNETWORKV6 cpu_to_le16(0x0017)
struct network_interface_info_ioctl_rsp {
__le32 Next; /* next interface. zero if this is last one */
__le32 IfIndex;
__le32 Capability; /* RSS or RDMA Capable */
__le32 Reserved;
__le64 LinkSpeed;
union {
char SockAddr_Storage[128];
struct {
__le16 Family;
__u8 Buffer[126];
};
};
} __packed;
/* this goes in the ioctl buffer when doing FSCTL_SET_ZERO_DATA */ /* this goes in the ioctl buffer when doing FSCTL_SET_ZERO_DATA */
struct file_zero_data_information { struct file_zero_data_information {
__le64 FileOffset; __le64 FileOffset;
@ -1893,6 +2011,151 @@ struct smb2_lease_ack {
__le64 LeaseDuration; __le64 LeaseDuration;
} __packed; } __packed;
/*
* See MS-CIFS 2.2.3.1
* MS-SMB 2.2.3.1
*/
struct smb_hdr {
__be32 smb_buf_length; /* BB length is only two (rarely three) bytes,
with one or two byte "type" preceding it that will be
zero - we could mask the type byte off */
__u8 Protocol[4];
__u8 Command;
union {
struct {
__u8 ErrorClass;
__u8 Reserved;
__le16 Error;
} __packed DosError;
__le32 CifsError;
} __packed Status;
__u8 Flags;
__le16 Flags2; /* note: le */
__le16 PidHigh;
union {
struct {
__le32 SequenceNumber; /* le */
__u32 Reserved; /* zero */
} __packed Sequence;
__u8 SecuritySignature[8]; /* le */
} __packed Signature;
__u8 pad[2];
__u16 Tid;
__le16 Pid;
__u16 Uid;
__le16 Mid;
__u8 WordCount;
} __packed;
#define OP_BREAK_STRUCT_SIZE_20 24 #define OP_BREAK_STRUCT_SIZE_20 24
#define OP_BREAK_STRUCT_SIZE_21 36 #define OP_BREAK_STRUCT_SIZE_21 36
/*
* See MS-SMB2 2.2.13.1.1
* MS-SMB 2.2.1.4.1
* These are the file access permission bits defined in CIFS for the
* NTCreateAndX as well as the level 0x107
* TRANS2_QUERY_PATH_INFORMATION API. The level 0x107, SMB_QUERY_FILE_ALL_INFO
* responds with the AccessFlags.
* The AccessFlags specifies the access permissions a caller has to the
* file and can have any suitable combination of the following values:
*/
#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
/* or directory child entries can */
/* be listed together with the */
/* associated child attributes */
/* (so the FILE_READ_ATTRIBUTES on */
/* the child entry is not needed) */
#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
/* or new file can be created in */
/* the directory */
#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
/* (for non-local files over SMB it */
/* is same as FILE_WRITE_DATA) */
/* or new subdirectory can be */
/* created in the directory */
#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
/* with the file can be read */
#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
/* with the file can be written */
#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
/* the file using system paging I/O */
/* for executing the file / script */
/* or right to traverse directory */
/* (but by default all users have */
/* directory bypass traverse */
/* privilege and do not need this */
/* permission on directories at all)*/
#define FILE_DELETE_CHILD 0x00000040 /* Child entry can be deleted from */
/* the directory (so the DELETE on */
/* the child entry is not needed) */
#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
/* file or directory can be read */
#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
/* file or directory can be written */
#define DELETE 0x00010000 /* The file or dir can be deleted */
#define READ_CONTROL 0x00020000 /* The discretionary access control */
/* list and ownership associated */
/* with the file or dir can be read */
#define WRITE_DAC 0x00040000 /* The discretionary access control */
/* list associated with the file or */
/* directory can be written */
#define WRITE_OWNER 0x00080000 /* Ownership information associated */
/* with the file/dir can be written */
#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
/* synchronize with the completion */
/* of an input/output request */
#define SYSTEM_SECURITY 0x01000000 /* The system access control list */
/* associated with the file or */
/* directory can be read or written */
/* (cannot be in DACL, can in SACL) */
#define MAXIMUM_ALLOWED 0x02000000 /* Maximal subset of GENERIC_ALL */
/* permissions which can be granted */
/* (cannot be in DACL nor SACL) */
#define GENERIC_ALL 0x10000000 /* Same as: GENERIC_EXECUTE | */
/* GENERIC_WRITE | */
/* GENERIC_READ | */
/* FILE_DELETE_CHILD | */
/* DELETE | */
/* WRITE_DAC | */
/* WRITE_OWNER */
/* So GENERIC_ALL contains all bits */
/* mentioned above except these two */
/* SYSTEM_SECURITY MAXIMUM_ALLOWED */
#define GENERIC_EXECUTE 0x20000000 /* Same as: FILE_EXECUTE | */
/* FILE_READ_ATTRIBUTES | */
/* READ_CONTROL | */
/* SYNCHRONIZE */
#define GENERIC_WRITE 0x40000000 /* Same as: FILE_WRITE_DATA | */
/* FILE_APPEND_DATA | */
/* FILE_WRITE_EA | */
/* FILE_WRITE_ATTRIBUTES | */
/* READ_CONTROL | */
/* SYNCHRONIZE */
#define GENERIC_READ 0x80000000 /* Same as: FILE_READ_DATA | */
/* FILE_READ_EA | */
/* FILE_READ_ATTRIBUTES | */
/* READ_CONTROL | */
/* SYNCHRONIZE */
/* Combinations of file access permission bits */
#define FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA | FILE_READ_ATTRIBUTES)
#define FILE_WRITE_RIGHTS (FILE_WRITE_DATA | FILE_APPEND_DATA \
| FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
#define FILE_EXEC_RIGHTS (FILE_EXECUTE)
#define SET_FILE_EXEC_RIGHTS (FILE_READ_EA | FILE_WRITE_EA | FILE_EXECUTE \
| FILE_READ_ATTRIBUTES \
| FILE_WRITE_ATTRIBUTES \
| DELETE | READ_CONTROL | WRITE_DAC \
| WRITE_OWNER | SYNCHRONIZE)
#define SET_MINIMUM_RIGHTS (FILE_READ_EA | FILE_READ_ATTRIBUTES \
| READ_CONTROL | SYNCHRONIZE)
/* See MS-CIFS 2.2.4.52.1 */
typedef struct smb_negotiate_req {
struct smb_hdr hdr; /* wct = 0 */
__le16 ByteCount;
unsigned char DialectsArray[];
} __packed SMB_NEGOTIATE_REQ;
#endif /* _COMMON_SMB2PDU_H */ #endif /* _COMMON_SMB2PDU_H */

View File

@ -92,14 +92,14 @@ struct smb_ntsd {
__le32 gsidoffset; __le32 gsidoffset;
__le32 sacloffset; __le32 sacloffset;
__le32 dacloffset; __le32 dacloffset;
} __attribute__((packed)); } __packed;
struct smb_sid { struct smb_sid {
__u8 revision; /* revision level */ __u8 revision; /* revision level */
__u8 num_subauth; __u8 num_subauth;
__u8 authority[NUM_AUTHS]; __u8 authority[NUM_AUTHS];
__le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */ __le32 sub_auth[SID_MAX_SUB_AUTHORITIES]; /* sub_auth[num_subauth] */
} __attribute__((packed)); } __packed;
/* size of a struct smb_sid, sans sub_auth array */ /* size of a struct smb_sid, sans sub_auth array */
#define CIFS_SID_BASE_SIZE (1 + 1 + NUM_AUTHS) #define CIFS_SID_BASE_SIZE (1 + 1 + NUM_AUTHS)
@ -109,7 +109,7 @@ struct smb_acl {
__le16 size; __le16 size;
__le16 num_aces; __le16 num_aces;
__le16 reserved; __le16 reserved;
} __attribute__((packed)); } __packed;
struct smb_ace { struct smb_ace {
__u8 type; /* see above and MS-DTYP 2.4.4.1 */ __u8 type; /* see above and MS-DTYP 2.4.4.1 */
@ -117,6 +117,6 @@ struct smb_ace {
__le16 size; __le16 size;
__le32 access_req; __le32 access_req;
struct smb_sid sid; /* ie UUID of user or group who gets these perms */ struct smb_sid sid; /* ie UUID of user or group who gets these perms */
} __attribute__((packed)); } __packed;
#endif /* _COMMON_SMBACL_H */ #endif /* _COMMON_SMBACL_H */

View File

@ -74,6 +74,19 @@ const char *smbdirect_socket_status_string(enum smbdirect_socket_status status)
return "<unknown>"; return "<unknown>";
} }
/*
* This can be used with %1pe to print errors as strings or '0'
* And it avoids warnings like: warn: passing zero to 'ERR_PTR'
* from smatch -p=kernel --pedantic
*/
static __always_inline
const void * __must_check SMBDIRECT_DEBUG_ERR_PTR(long error)
{
if (error == 0)
return NULL;
return ERR_PTR(error);
}
enum smbdirect_keepalive_status { enum smbdirect_keepalive_status {
SMBDIRECT_KEEPALIVE_NONE, SMBDIRECT_KEEPALIVE_NONE,
SMBDIRECT_KEEPALIVE_PENDING, SMBDIRECT_KEEPALIVE_PENDING,
@ -381,6 +394,44 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
init_waitqueue_head(&sc->mr_io.cleanup.wait_queue); init_waitqueue_head(&sc->mr_io.cleanup.wait_queue);
} }
#define __SMBDIRECT_CHECK_STATUS_FAILED(__sc, __expected_status, __error_cmd, __unexpected_cmd) ({ \
bool __failed = false; \
if (unlikely((__sc)->first_error)) { \
__failed = true; \
__error_cmd \
} else if (unlikely((__sc)->status != (__expected_status))) { \
__failed = true; \
__unexpected_cmd \
} \
__failed; \
})
#define __SMBDIRECT_CHECK_STATUS_WARN(__sc, __expected_status, __unexpected_cmd) \
__SMBDIRECT_CHECK_STATUS_FAILED(__sc, __expected_status, \
, \
{ \
const struct sockaddr_storage *__src = NULL; \
const struct sockaddr_storage *__dst = NULL; \
if ((__sc)->rdma.cm_id) { \
__src = &(__sc)->rdma.cm_id->route.addr.src_addr; \
__dst = &(__sc)->rdma.cm_id->route.addr.dst_addr; \
} \
WARN_ONCE(1, \
"expected[%s] != %s first_error=%1pe local=%pISpsfc remote=%pISpsfc\n", \
smbdirect_socket_status_string(__expected_status), \
smbdirect_socket_status_string((__sc)->status), \
SMBDIRECT_DEBUG_ERR_PTR((__sc)->first_error), \
__src, __dst); \
__unexpected_cmd \
})
#define SMBDIRECT_CHECK_STATUS_WARN(__sc, __expected_status) \
__SMBDIRECT_CHECK_STATUS_WARN(__sc, __expected_status, /* nothing */)
#define SMBDIRECT_CHECK_STATUS_DISCONNECT(__sc, __expected_status) \
__SMBDIRECT_CHECK_STATUS_WARN(__sc, __expected_status, \
__SMBDIRECT_SOCKET_DISCONNECT(__sc);)
struct smbdirect_send_io { struct smbdirect_send_io {
struct smbdirect_socket *socket; struct smbdirect_socket *socket;
struct ib_cqe cqe; struct ib_cqe cqe;

72
fs/smb/common/smbglob.h Normal file
View File

@ -0,0 +1,72 @@
/* SPDX-License-Identifier: LGPL-2.1 */
/*
*
* Copyright (C) International Business Machines Corp., 2002,2008
* 2018 Samsung Electronics Co., Ltd.
* Author(s): Steve French (sfrench@us.ibm.com)
* Jeremy Allison (jra@samba.org)
* Namjae Jeon (linkinjeon@kernel.org)
*
*/
#ifndef _COMMON_SMB_GLOB_H
#define _COMMON_SMB_GLOB_H
#define SMB1_PROTO_NUMBER cpu_to_le32(0x424d53ff)
struct smb_version_values {
char *version_string;
__u16 protocol_id;
__le16 lock_cmd;
__u32 req_capabilities;
__u32 max_read_size;
__u32 max_write_size;
__u32 max_trans_size;
__u32 max_credits;
__u32 large_lock_type;
__u32 exclusive_lock_type;
__u32 shared_lock_type;
__u32 unlock_lock_type;
size_t header_preamble_size;
size_t header_size;
size_t max_header_size;
size_t read_rsp_size;
unsigned int cap_unix;
unsigned int cap_nt_find;
unsigned int cap_large_files;
unsigned int cap_unicode;
__u16 signing_enabled;
__u16 signing_required;
size_t create_lease_size;
size_t create_durable_size;
size_t create_durable_v2_size;
size_t create_mxac_size;
size_t create_disk_id_size;
size_t create_posix_size;
};
static inline unsigned int get_rfc1002_len(void *buf)
{
return be32_to_cpu(*((__be32 *)buf)) & 0xffffff;
}
static inline void inc_rfc1001_len(void *buf, int count)
{
be32_add_cpu((__be32 *)buf, count);
}
#define SMB1_VERSION_STRING "1.0"
#define SMB20_VERSION_STRING "2.0"
#define SMB21_VERSION_STRING "2.1"
#define SMBDEFAULT_VERSION_STRING "default"
#define SMB3ANY_VERSION_STRING "3"
#define SMB30_VERSION_STRING "3.0"
#define SMB302_VERSION_STRING "3.02"
#define ALT_SMB302_VERSION_STRING "3.0.2"
#define SMB311_VERSION_STRING "3.1.1"
#define ALT_SMB311_VERSION_STRING "3.11"
#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
#endif /* _COMMON_SMB_GLOB_H */

View File

@ -7,15 +7,13 @@ config SMB_SERVER
select NLS_UTF8 select NLS_UTF8
select NLS_UCS2_UTILS select NLS_UCS2_UTILS
select CRYPTO select CRYPTO
select CRYPTO_MD5
select CRYPTO_HMAC
select CRYPTO_ECB select CRYPTO_ECB
select CRYPTO_LIB_ARC4 select CRYPTO_LIB_ARC4
select CRYPTO_LIB_DES select CRYPTO_LIB_DES
select CRYPTO_LIB_MD5
select CRYPTO_LIB_SHA256 select CRYPTO_LIB_SHA256
select CRYPTO_SHA256 select CRYPTO_LIB_SHA512
select CRYPTO_CMAC select CRYPTO_CMAC
select CRYPTO_SHA512
select CRYPTO_AEAD2 select CRYPTO_AEAD2
select CRYPTO_CCM select CRYPTO_CCM
select CRYPTO_GCM select CRYPTO_GCM

View File

@ -13,6 +13,8 @@
#include <linux/xattr.h> #include <linux/xattr.h>
#include <crypto/hash.h> #include <crypto/hash.h>
#include <crypto/aead.h> #include <crypto/aead.h>
#include <crypto/md5.h>
#include <crypto/sha2.h>
#include <linux/random.h> #include <linux/random.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
@ -69,85 +71,16 @@ void ksmbd_copy_gss_neg_header(void *buf)
memcpy(buf, NEGOTIATE_GSS_HEADER, AUTH_GSS_LENGTH); memcpy(buf, NEGOTIATE_GSS_HEADER, AUTH_GSS_LENGTH);
} }
/**
* ksmbd_gen_sess_key() - function to generate session key
* @sess: session of connection
* @hash: source hash value to be used for find session key
* @hmac: source hmac value to be used for finding session key
*
*/
static int ksmbd_gen_sess_key(struct ksmbd_session *sess, char *hash,
char *hmac)
{
struct ksmbd_crypto_ctx *ctx;
int rc;
ctx = ksmbd_crypto_ctx_find_hmacmd5();
if (!ctx) {
ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
return -ENOMEM;
}
rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
hash,
CIFS_HMAC_MD5_HASH_SIZE);
if (rc) {
ksmbd_debug(AUTH, "hmacmd5 set key fail error %d\n", rc);
goto out;
}
rc = crypto_shash_init(CRYPTO_HMACMD5(ctx));
if (rc) {
ksmbd_debug(AUTH, "could not init hmacmd5 error %d\n", rc);
goto out;
}
rc = crypto_shash_update(CRYPTO_HMACMD5(ctx),
hmac,
SMB2_NTLMV2_SESSKEY_SIZE);
if (rc) {
ksmbd_debug(AUTH, "Could not update with response error %d\n", rc);
goto out;
}
rc = crypto_shash_final(CRYPTO_HMACMD5(ctx), sess->sess_key);
if (rc) {
ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n", rc);
goto out;
}
out:
ksmbd_release_crypto_ctx(ctx);
return rc;
}
static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess, static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess,
char *ntlmv2_hash, char *dname) char *ntlmv2_hash, char *dname)
{ {
int ret, len, conv_len; int ret, len, conv_len;
wchar_t *domain = NULL; wchar_t *domain = NULL;
__le16 *uniname = NULL; __le16 *uniname = NULL;
struct ksmbd_crypto_ctx *ctx; struct hmac_md5_ctx ctx;
ctx = ksmbd_crypto_ctx_find_hmacmd5(); hmac_md5_init_usingrawkey(&ctx, user_passkey(sess->user),
if (!ctx) {
ksmbd_debug(AUTH, "can't generate ntlmv2 hash\n");
return -ENOMEM;
}
ret = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
user_passkey(sess->user),
CIFS_ENCPWD_SIZE); CIFS_ENCPWD_SIZE);
if (ret) {
ksmbd_debug(AUTH, "Could not set NT Hash as a key\n");
goto out;
}
ret = crypto_shash_init(CRYPTO_HMACMD5(ctx));
if (ret) {
ksmbd_debug(AUTH, "could not init hmacmd5\n");
goto out;
}
/* convert user_name to unicode */ /* convert user_name to unicode */
len = strlen(user_name(sess->user)); len = strlen(user_name(sess->user));
@ -165,13 +98,7 @@ static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess,
} }
UniStrupr(uniname); UniStrupr(uniname);
ret = crypto_shash_update(CRYPTO_HMACMD5(ctx), hmac_md5_update(&ctx, (const u8 *)uniname, UNICODE_LEN(conv_len));
(char *)uniname,
UNICODE_LEN(conv_len));
if (ret) {
ksmbd_debug(AUTH, "Could not update with user\n");
goto out;
}
/* Convert domain name or conn name to unicode and uppercase */ /* Convert domain name or conn name to unicode and uppercase */
len = strlen(dname); len = strlen(dname);
@ -188,21 +115,12 @@ static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess,
goto out; goto out;
} }
ret = crypto_shash_update(CRYPTO_HMACMD5(ctx), hmac_md5_update(&ctx, (const u8 *)domain, UNICODE_LEN(conv_len));
(char *)domain, hmac_md5_final(&ctx, ntlmv2_hash);
UNICODE_LEN(conv_len)); ret = 0;
if (ret) {
ksmbd_debug(AUTH, "Could not update with domain\n");
goto out;
}
ret = crypto_shash_final(CRYPTO_HMACMD5(ctx), ntlmv2_hash);
if (ret)
ksmbd_debug(AUTH, "Could not generate md5 hash\n");
out: out:
kfree(uniname); kfree(uniname);
kfree(domain); kfree(domain);
ksmbd_release_crypto_ctx(ctx);
return ret; return ret;
} }
@ -223,73 +141,33 @@ int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
{ {
char ntlmv2_hash[CIFS_ENCPWD_SIZE]; char ntlmv2_hash[CIFS_ENCPWD_SIZE];
char ntlmv2_rsp[CIFS_HMAC_MD5_HASH_SIZE]; char ntlmv2_rsp[CIFS_HMAC_MD5_HASH_SIZE];
struct ksmbd_crypto_ctx *ctx = NULL; struct hmac_md5_ctx ctx;
char *construct = NULL; int rc;
int rc, len;
if (fips_enabled) {
ksmbd_debug(AUTH, "NTLMv2 support is disabled due to FIPS\n");
return -EOPNOTSUPP;
}
rc = calc_ntlmv2_hash(conn, sess, ntlmv2_hash, domain_name); rc = calc_ntlmv2_hash(conn, sess, ntlmv2_hash, domain_name);
if (rc) { if (rc) {
ksmbd_debug(AUTH, "could not get v2 hash rc %d\n", rc); ksmbd_debug(AUTH, "could not get v2 hash rc %d\n", rc);
goto out; return rc;
} }
ctx = ksmbd_crypto_ctx_find_hmacmd5(); hmac_md5_init_usingrawkey(&ctx, ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
if (!ctx) { hmac_md5_update(&ctx, cryptkey, CIFS_CRYPTO_KEY_SIZE);
ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n"); hmac_md5_update(&ctx, (const u8 *)&ntlmv2->blob_signature, blen);
return -ENOMEM; hmac_md5_final(&ctx, ntlmv2_rsp);
}
rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx), /* Generate the session key */
ntlmv2_hash, hmac_md5_usingrawkey(ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE,
CIFS_HMAC_MD5_HASH_SIZE); ntlmv2_rsp, CIFS_HMAC_MD5_HASH_SIZE,
if (rc) { sess->sess_key);
ksmbd_debug(AUTH, "Could not set NTLMV2 Hash as a key\n");
goto out;
}
rc = crypto_shash_init(CRYPTO_HMACMD5(ctx));
if (rc) {
ksmbd_debug(AUTH, "Could not init hmacmd5\n");
goto out;
}
len = CIFS_CRYPTO_KEY_SIZE + blen;
construct = kzalloc(len, KSMBD_DEFAULT_GFP);
if (!construct) {
rc = -ENOMEM;
goto out;
}
memcpy(construct, cryptkey, CIFS_CRYPTO_KEY_SIZE);
memcpy(construct + CIFS_CRYPTO_KEY_SIZE, &ntlmv2->blob_signature, blen);
rc = crypto_shash_update(CRYPTO_HMACMD5(ctx), construct, len);
if (rc) {
ksmbd_debug(AUTH, "Could not update with response\n");
goto out;
}
rc = crypto_shash_final(CRYPTO_HMACMD5(ctx), ntlmv2_rsp);
if (rc) {
ksmbd_debug(AUTH, "Could not generate md5 hash\n");
goto out;
}
ksmbd_release_crypto_ctx(ctx);
ctx = NULL;
rc = ksmbd_gen_sess_key(sess, ntlmv2_hash, ntlmv2_rsp);
if (rc) {
ksmbd_debug(AUTH, "Could not generate sess key\n");
goto out;
}
if (memcmp(ntlmv2->ntlmv2_hash, ntlmv2_rsp, CIFS_HMAC_MD5_HASH_SIZE) != 0) if (memcmp(ntlmv2->ntlmv2_hash, ntlmv2_rsp, CIFS_HMAC_MD5_HASH_SIZE) != 0)
rc = -EINVAL; return -EINVAL;
out: return 0;
if (ctx)
ksmbd_release_crypto_ctx(ctx);
kfree(construct);
return rc;
} }
/** /**
@ -589,46 +467,16 @@ int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
* @sig: signature value generated for client request packet * @sig: signature value generated for client request packet
* *
*/ */
int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov, void ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
int n_vec, char *sig) int n_vec, char *sig)
{ {
struct ksmbd_crypto_ctx *ctx; struct hmac_sha256_ctx ctx;
int rc, i; int i;
ctx = ksmbd_crypto_ctx_find_hmacsha256(); hmac_sha256_init_usingrawkey(&ctx, key, SMB2_NTLMV2_SESSKEY_SIZE);
if (!ctx) { for (i = 0; i < n_vec; i++)
ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n"); hmac_sha256_update(&ctx, iov[i].iov_base, iov[i].iov_len);
return -ENOMEM; hmac_sha256_final(&ctx, sig);
}
rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx),
key,
SMB2_NTLMV2_SESSKEY_SIZE);
if (rc)
goto out;
rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx));
if (rc) {
ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc);
goto out;
}
for (i = 0; i < n_vec; i++) {
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
iov[i].iov_base,
iov[i].iov_len);
if (rc) {
ksmbd_debug(AUTH, "hmacsha256 update error %d\n", rc);
goto out;
}
}
rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), sig);
if (rc)
ksmbd_debug(AUTH, "hmacsha256 generation error %d\n", rc);
out:
ksmbd_release_crypto_ctx(ctx);
return rc;
} }
/** /**
@ -688,98 +536,39 @@ struct derivation {
bool binding; bool binding;
}; };
static int generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess, static void generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
struct kvec label, struct kvec context, __u8 *key, struct kvec label, struct kvec context, __u8 *key,
unsigned int key_size) unsigned int key_size)
{ {
unsigned char zero = 0x0; unsigned char zero = 0x0;
__u8 i[4] = {0, 0, 0, 1}; __u8 i[4] = {0, 0, 0, 1};
__u8 L128[4] = {0, 0, 0, 128}; __u8 L128[4] = {0, 0, 0, 128};
__u8 L256[4] = {0, 0, 1, 0}; __u8 L256[4] = {0, 0, 1, 0};
int rc;
unsigned char prfhash[SMB2_HMACSHA256_SIZE]; unsigned char prfhash[SMB2_HMACSHA256_SIZE];
unsigned char *hashptr = prfhash; struct hmac_sha256_ctx ctx;
struct ksmbd_crypto_ctx *ctx;
memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE); hmac_sha256_init_usingrawkey(&ctx, sess->sess_key,
memset(key, 0x0, key_size); SMB2_NTLMV2_SESSKEY_SIZE);
hmac_sha256_update(&ctx, i, 4);
ctx = ksmbd_crypto_ctx_find_hmacsha256(); hmac_sha256_update(&ctx, label.iov_base, label.iov_len);
if (!ctx) { hmac_sha256_update(&ctx, &zero, 1);
ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n"); hmac_sha256_update(&ctx, context.iov_base, context.iov_len);
return -ENOMEM;
}
rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx),
sess->sess_key,
SMB2_NTLMV2_SESSKEY_SIZE);
if (rc)
goto smb3signkey_ret;
rc = crypto_shash_init(CRYPTO_HMACSHA256(ctx));
if (rc) {
ksmbd_debug(AUTH, "hmacsha256 init error %d\n", rc);
goto smb3signkey_ret;
}
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), i, 4);
if (rc) {
ksmbd_debug(AUTH, "could not update with n\n");
goto smb3signkey_ret;
}
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
label.iov_base,
label.iov_len);
if (rc) {
ksmbd_debug(AUTH, "could not update with label\n");
goto smb3signkey_ret;
}
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), &zero, 1);
if (rc) {
ksmbd_debug(AUTH, "could not update with zero\n");
goto smb3signkey_ret;
}
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx),
context.iov_base,
context.iov_len);
if (rc) {
ksmbd_debug(AUTH, "could not update with context\n");
goto smb3signkey_ret;
}
if (key_size == SMB3_ENC_DEC_KEY_SIZE && if (key_size == SMB3_ENC_DEC_KEY_SIZE &&
(conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM || (conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM)) conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4); hmac_sha256_update(&ctx, L256, 4);
else else
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4); hmac_sha256_update(&ctx, L128, 4);
if (rc) {
ksmbd_debug(AUTH, "could not update with L\n");
goto smb3signkey_ret;
}
rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), hashptr); hmac_sha256_final(&ctx, prfhash);
if (rc) { memcpy(key, prfhash, key_size);
ksmbd_debug(AUTH, "Could not generate hmacmd5 hash error %d\n",
rc);
goto smb3signkey_ret;
}
memcpy(key, hashptr, key_size);
smb3signkey_ret:
ksmbd_release_crypto_ctx(ctx);
return rc;
} }
static int generate_smb3signingkey(struct ksmbd_session *sess, static int generate_smb3signingkey(struct ksmbd_session *sess,
struct ksmbd_conn *conn, struct ksmbd_conn *conn,
const struct derivation *signing) const struct derivation *signing)
{ {
int rc;
struct channel *chann; struct channel *chann;
char *key; char *key;
@ -792,10 +581,8 @@ static int generate_smb3signingkey(struct ksmbd_session *sess,
else else
key = sess->smb3signingkey; key = sess->smb3signingkey;
rc = generate_key(conn, sess, signing->label, signing->context, key, generate_key(conn, sess, signing->label, signing->context, key,
SMB3_SIGN_KEY_SIZE); SMB3_SIGN_KEY_SIZE);
if (rc)
return rc;
if (!(conn->dialect >= SMB30_PROT_ID && signing->binding)) if (!(conn->dialect >= SMB30_PROT_ID && signing->binding))
memcpy(chann->smb3signingkey, key, SMB3_SIGN_KEY_SIZE); memcpy(chann->smb3signingkey, key, SMB3_SIGN_KEY_SIZE);
@ -851,23 +638,17 @@ struct derivation_twin {
struct derivation decryption; struct derivation decryption;
}; };
static int generate_smb3encryptionkey(struct ksmbd_conn *conn, static void generate_smb3encryptionkey(struct ksmbd_conn *conn,
struct ksmbd_session *sess, struct ksmbd_session *sess,
const struct derivation_twin *ptwin) const struct derivation_twin *ptwin)
{ {
int rc; generate_key(conn, sess, ptwin->encryption.label,
ptwin->encryption.context, sess->smb3encryptionkey,
SMB3_ENC_DEC_KEY_SIZE);
rc = generate_key(conn, sess, ptwin->encryption.label, generate_key(conn, sess, ptwin->decryption.label,
ptwin->encryption.context, sess->smb3encryptionkey, ptwin->decryption.context,
SMB3_ENC_DEC_KEY_SIZE); sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE);
if (rc)
return rc;
rc = generate_key(conn, sess, ptwin->decryption.label,
ptwin->decryption.context,
sess->smb3decryptionkey, SMB3_ENC_DEC_KEY_SIZE);
if (rc)
return rc;
ksmbd_debug(AUTH, "dumping generated AES encryption keys\n"); ksmbd_debug(AUTH, "dumping generated AES encryption keys\n");
ksmbd_debug(AUTH, "Cipher type %d\n", conn->cipher_type); ksmbd_debug(AUTH, "Cipher type %d\n", conn->cipher_type);
@ -886,11 +667,10 @@ static int generate_smb3encryptionkey(struct ksmbd_conn *conn,
ksmbd_debug(AUTH, "ServerOut Key %*ph\n", ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3decryptionkey); SMB3_GCM128_CRYPTKEY_SIZE, sess->smb3decryptionkey);
} }
return 0;
} }
int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn, void ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
struct ksmbd_session *sess) struct ksmbd_session *sess)
{ {
struct derivation_twin twin; struct derivation_twin twin;
struct derivation *d; struct derivation *d;
@ -907,11 +687,11 @@ int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
d->context.iov_base = "ServerIn "; d->context.iov_base = "ServerIn ";
d->context.iov_len = 10; d->context.iov_len = 10;
return generate_smb3encryptionkey(conn, sess, &twin); generate_smb3encryptionkey(conn, sess, &twin);
} }
int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn, void ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
struct ksmbd_session *sess) struct ksmbd_session *sess)
{ {
struct derivation_twin twin; struct derivation_twin twin;
struct derivation *d; struct derivation *d;
@ -928,54 +708,26 @@ int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
d->context.iov_base = sess->Preauth_HashValue; d->context.iov_base = sess->Preauth_HashValue;
d->context.iov_len = 64; d->context.iov_len = 64;
return generate_smb3encryptionkey(conn, sess, &twin); generate_smb3encryptionkey(conn, sess, &twin);
} }
int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf, int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
__u8 *pi_hash) __u8 *pi_hash)
{ {
int rc;
struct smb2_hdr *rcv_hdr = smb2_get_msg(buf); struct smb2_hdr *rcv_hdr = smb2_get_msg(buf);
char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId; char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId;
int msg_size = get_rfc1002_len(buf); int msg_size = get_rfc1002_len(buf);
struct ksmbd_crypto_ctx *ctx = NULL; struct sha512_ctx sha_ctx;
if (conn->preauth_info->Preauth_HashId != if (conn->preauth_info->Preauth_HashId !=
SMB2_PREAUTH_INTEGRITY_SHA512) SMB2_PREAUTH_INTEGRITY_SHA512)
return -EINVAL; return -EINVAL;
ctx = ksmbd_crypto_ctx_find_sha512(); sha512_init(&sha_ctx);
if (!ctx) { sha512_update(&sha_ctx, pi_hash, 64);
ksmbd_debug(AUTH, "could not alloc sha512\n"); sha512_update(&sha_ctx, all_bytes_msg, msg_size);
return -ENOMEM; sha512_final(&sha_ctx, pi_hash);
} return 0;
rc = crypto_shash_init(CRYPTO_SHA512(ctx));
if (rc) {
ksmbd_debug(AUTH, "could not init shashn");
goto out;
}
rc = crypto_shash_update(CRYPTO_SHA512(ctx), pi_hash, 64);
if (rc) {
ksmbd_debug(AUTH, "could not update with n\n");
goto out;
}
rc = crypto_shash_update(CRYPTO_SHA512(ctx), all_bytes_msg, msg_size);
if (rc) {
ksmbd_debug(AUTH, "could not update with n\n");
goto out;
}
rc = crypto_shash_final(CRYPTO_SHA512(ctx), pi_hash);
if (rc) {
ksmbd_debug(AUTH, "Could not generate hash err : %d\n", rc);
goto out;
}
out:
ksmbd_release_crypto_ctx(ctx);
return rc;
} }
static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id, static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,

View File

@ -52,18 +52,18 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
struct ksmbd_conn *conn); struct ksmbd_conn *conn);
int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob, int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
int in_len, char *out_blob, int *out_len); int in_len, char *out_blob, int *out_len);
int ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov, void ksmbd_sign_smb2_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
int n_vec, char *sig); int n_vec, char *sig);
int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov, int ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
int n_vec, char *sig); int n_vec, char *sig);
int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess, int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
struct ksmbd_conn *conn); struct ksmbd_conn *conn);
int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess, int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
struct ksmbd_conn *conn); struct ksmbd_conn *conn);
int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn, void ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
struct ksmbd_session *sess);
int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
struct ksmbd_session *sess); struct ksmbd_session *sess);
void ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
struct ksmbd_session *sess);
int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf, int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
__u8 *pi_hash); __u8 *pi_hash);
#endif #endif

View File

@ -66,18 +66,9 @@ static struct shash_desc *alloc_shash_desc(int id)
struct shash_desc *shash; struct shash_desc *shash;
switch (id) { switch (id) {
case CRYPTO_SHASH_HMACMD5:
tfm = crypto_alloc_shash("hmac(md5)", 0, 0);
break;
case CRYPTO_SHASH_HMACSHA256:
tfm = crypto_alloc_shash("hmac(sha256)", 0, 0);
break;
case CRYPTO_SHASH_CMACAES: case CRYPTO_SHASH_CMACAES:
tfm = crypto_alloc_shash("cmac(aes)", 0, 0); tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
break; break;
case CRYPTO_SHASH_SHA512:
tfm = crypto_alloc_shash("sha512", 0, 0);
break;
default: default:
return NULL; return NULL;
} }
@ -180,26 +171,11 @@ static struct ksmbd_crypto_ctx *____crypto_shash_ctx_find(int id)
return NULL; return NULL;
} }
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacmd5(void)
{
return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACMD5);
}
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void)
{
return ____crypto_shash_ctx_find(CRYPTO_SHASH_HMACSHA256);
}
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void) struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void)
{ {
return ____crypto_shash_ctx_find(CRYPTO_SHASH_CMACAES); return ____crypto_shash_ctx_find(CRYPTO_SHASH_CMACAES);
} }
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void)
{
return ____crypto_shash_ctx_find(CRYPTO_SHASH_SHA512);
}
static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id) static struct ksmbd_crypto_ctx *____crypto_aead_ctx_find(int id)
{ {
struct ksmbd_crypto_ctx *ctx; struct ksmbd_crypto_ctx *ctx;

View File

@ -10,10 +10,7 @@
#include <crypto/aead.h> #include <crypto/aead.h>
enum { enum {
CRYPTO_SHASH_HMACMD5 = 0, CRYPTO_SHASH_CMACAES = 0,
CRYPTO_SHASH_HMACSHA256,
CRYPTO_SHASH_CMACAES,
CRYPTO_SHASH_SHA512,
CRYPTO_SHASH_MAX, CRYPTO_SHASH_MAX,
}; };
@ -35,25 +32,15 @@ struct ksmbd_crypto_ctx {
struct crypto_aead *ccmaes[CRYPTO_AEAD_MAX]; struct crypto_aead *ccmaes[CRYPTO_AEAD_MAX];
}; };
#define CRYPTO_HMACMD5(c) ((c)->desc[CRYPTO_SHASH_HMACMD5])
#define CRYPTO_HMACSHA256(c) ((c)->desc[CRYPTO_SHASH_HMACSHA256])
#define CRYPTO_CMACAES(c) ((c)->desc[CRYPTO_SHASH_CMACAES]) #define CRYPTO_CMACAES(c) ((c)->desc[CRYPTO_SHASH_CMACAES])
#define CRYPTO_SHA512(c) ((c)->desc[CRYPTO_SHASH_SHA512])
#define CRYPTO_HMACMD5_TFM(c) ((c)->desc[CRYPTO_SHASH_HMACMD5]->tfm)
#define CRYPTO_HMACSHA256_TFM(c)\
((c)->desc[CRYPTO_SHASH_HMACSHA256]->tfm)
#define CRYPTO_CMACAES_TFM(c) ((c)->desc[CRYPTO_SHASH_CMACAES]->tfm) #define CRYPTO_CMACAES_TFM(c) ((c)->desc[CRYPTO_SHASH_CMACAES]->tfm)
#define CRYPTO_SHA512_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA512]->tfm)
#define CRYPTO_GCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_GCM]) #define CRYPTO_GCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_GCM])
#define CRYPTO_CCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_CCM]) #define CRYPTO_CCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_CCM])
void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx); void ksmbd_release_crypto_ctx(struct ksmbd_crypto_ctx *ctx);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacmd5(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_hmacsha256(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void); struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_cmacaes(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_sha512(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void); struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void); struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void);
void ksmbd_crypto_destroy(void); void ksmbd_crypto_destroy(void);

View File

@ -78,7 +78,6 @@ ksmbd_tree_conn_connect(struct ksmbd_work *work, const char *share_name)
tree_conn->t_state = TREE_NEW; tree_conn->t_state = TREE_NEW;
status.tree_conn = tree_conn; status.tree_conn = tree_conn;
atomic_set(&tree_conn->refcount, 1); atomic_set(&tree_conn->refcount, 1);
init_waitqueue_head(&tree_conn->refcount_q);
ret = xa_err(xa_store(&sess->tree_conns, tree_conn->id, tree_conn, ret = xa_err(xa_store(&sess->tree_conns, tree_conn->id, tree_conn,
KSMBD_DEFAULT_GFP)); KSMBD_DEFAULT_GFP));
@ -100,14 +99,8 @@ ksmbd_tree_conn_connect(struct ksmbd_work *work, const char *share_name)
void ksmbd_tree_connect_put(struct ksmbd_tree_connect *tcon) void ksmbd_tree_connect_put(struct ksmbd_tree_connect *tcon)
{ {
/* if (atomic_dec_and_test(&tcon->refcount))
* Checking waitqueue to releasing tree connect on kfree(tcon);
* tree disconnect. waitqueue_active is safe because it
* uses atomic operation for condition.
*/
if (!atomic_dec_return(&tcon->refcount) &&
waitqueue_active(&tcon->refcount_q))
wake_up(&tcon->refcount_q);
} }
int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess, int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
@ -119,14 +112,11 @@ int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
xa_erase(&sess->tree_conns, tree_conn->id); xa_erase(&sess->tree_conns, tree_conn->id);
write_unlock(&sess->tree_conns_lock); write_unlock(&sess->tree_conns_lock);
if (!atomic_dec_and_test(&tree_conn->refcount))
wait_event(tree_conn->refcount_q,
atomic_read(&tree_conn->refcount) == 0);
ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id); ret = ksmbd_ipc_tree_disconnect_request(sess->id, tree_conn->id);
ksmbd_release_tree_conn_id(sess, tree_conn->id); ksmbd_release_tree_conn_id(sess, tree_conn->id);
ksmbd_share_config_put(tree_conn->share_conf); ksmbd_share_config_put(tree_conn->share_conf);
kfree(tree_conn); if (atomic_dec_and_test(&tree_conn->refcount))
kfree(tree_conn);
return ret; return ret;
} }

View File

@ -33,7 +33,6 @@ struct ksmbd_tree_connect {
int maximal_access; int maximal_access;
bool posix_extensions; bool posix_extensions;
atomic_t refcount; atomic_t refcount;
wait_queue_head_t refcount_q;
unsigned int t_state; unsigned int t_state;
}; };

View File

@ -164,6 +164,8 @@ char *convert_to_nt_pathname(struct ksmbd_share_config *share,
{ {
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;
size_t ab_pathname_len;
int prefix;
pathname = kmalloc(PATH_MAX, KSMBD_DEFAULT_GFP); pathname = kmalloc(PATH_MAX, KSMBD_DEFAULT_GFP);
if (!pathname) if (!pathname)
@ -180,15 +182,18 @@ char *convert_to_nt_pathname(struct ksmbd_share_config *share,
goto free_pathname; goto free_pathname;
} }
nt_pathname = kzalloc(strlen(&ab_pathname[share_path_len]) + 2, ab_pathname_len = strlen(&ab_pathname[share_path_len]);
KSMBD_DEFAULT_GFP); prefix = ab_pathname[share_path_len] == '\0' ? 1 : 0;
nt_pathname = kmalloc(prefix + ab_pathname_len + 1, KSMBD_DEFAULT_GFP);
if (!nt_pathname) { if (!nt_pathname) {
nt_pathname = ERR_PTR(-ENOMEM); nt_pathname = ERR_PTR(-ENOMEM);
goto free_pathname; goto free_pathname;
} }
if (ab_pathname[share_path_len] == '\0')
strcpy(nt_pathname, "/"); if (prefix)
strcat(nt_pathname, &ab_pathname[share_path_len]); *nt_pathname = '/';
memcpy(nt_pathname + prefix, &ab_pathname[share_path_len],
ab_pathname_len + 1);
ksmbd_conv_path_to_windows(nt_pathname); ksmbd_conv_path_to_windows(nt_pathname);

View File

@ -1617,9 +1617,9 @@ void create_durable_rsp_buf(char *cc)
*/ */
void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp) void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp)
{ {
struct create_durable_v2_rsp *buf; struct create_durable_rsp_v2 *buf;
buf = (struct create_durable_v2_rsp *)cc; buf = (struct create_durable_rsp_v2 *)cc;
memset(buf, 0, sizeof(struct create_durable_rsp)); memset(buf, 0, sizeof(struct create_durable_rsp));
buf->ccontext.DataOffset = cpu_to_le16(offsetof buf->ccontext.DataOffset = cpu_to_le16(offsetof
(struct create_durable_rsp, Data)); (struct create_durable_rsp, Data));
@ -1633,9 +1633,9 @@ void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp)
buf->Name[2] = '2'; buf->Name[2] = '2';
buf->Name[3] = 'Q'; buf->Name[3] = 'Q';
buf->Timeout = cpu_to_le32(fp->durable_timeout); buf->dcontext.Timeout = cpu_to_le32(fp->durable_timeout);
if (fp->is_persistent) if (fp->is_persistent)
buf->Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT); buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
} }
/** /**

View File

@ -622,13 +622,9 @@ MODULE_AUTHOR("Namjae Jeon <linkinjeon@kernel.org>");
MODULE_DESCRIPTION("Linux kernel CIFS/SMB SERVER"); MODULE_DESCRIPTION("Linux kernel CIFS/SMB SERVER");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_SOFTDEP("pre: ecb"); MODULE_SOFTDEP("pre: ecb");
MODULE_SOFTDEP("pre: hmac");
MODULE_SOFTDEP("pre: md5");
MODULE_SOFTDEP("pre: nls"); MODULE_SOFTDEP("pre: nls");
MODULE_SOFTDEP("pre: aes"); MODULE_SOFTDEP("pre: aes");
MODULE_SOFTDEP("pre: cmac"); MODULE_SOFTDEP("pre: cmac");
MODULE_SOFTDEP("pre: sha256");
MODULE_SOFTDEP("pre: sha512");
MODULE_SOFTDEP("pre: aead2"); MODULE_SOFTDEP("pre: aead2");
MODULE_SOFTDEP("pre: ccm"); MODULE_SOFTDEP("pre: ccm");
MODULE_SOFTDEP("pre: gcm"); MODULE_SOFTDEP("pre: gcm");

View File

@ -460,7 +460,7 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
} }
validate_credit: validate_credit:
if ((work->conn->vals->capabilities & SMB2_GLOBAL_CAP_LARGE_MTU) && if ((work->conn->vals->req_capabilities & SMB2_GLOBAL_CAP_LARGE_MTU) &&
smb2_validate_credit_charge(work->conn, hdr)) smb2_validate_credit_charge(work->conn, hdr))
return 1; return 1;

View File

@ -15,7 +15,7 @@
static struct smb_version_values smb21_server_values = { static struct smb_version_values smb21_server_values = {
.version_string = SMB21_VERSION_STRING, .version_string = SMB21_VERSION_STRING,
.protocol_id = SMB21_PROT_ID, .protocol_id = SMB21_PROT_ID,
.capabilities = SMB2_GLOBAL_CAP_LARGE_MTU, .req_capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
.max_read_size = SMB21_DEFAULT_IOSIZE, .max_read_size = SMB21_DEFAULT_IOSIZE,
.max_write_size = SMB21_DEFAULT_IOSIZE, .max_write_size = SMB21_DEFAULT_IOSIZE,
.max_trans_size = SMB21_DEFAULT_IOSIZE, .max_trans_size = SMB21_DEFAULT_IOSIZE,
@ -41,7 +41,7 @@ static struct smb_version_values smb21_server_values = {
static struct smb_version_values smb30_server_values = { static struct smb_version_values smb30_server_values = {
.version_string = SMB30_VERSION_STRING, .version_string = SMB30_VERSION_STRING,
.protocol_id = SMB30_PROT_ID, .protocol_id = SMB30_PROT_ID,
.capabilities = SMB2_GLOBAL_CAP_LARGE_MTU, .req_capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
.max_read_size = SMB3_DEFAULT_IOSIZE, .max_read_size = SMB3_DEFAULT_IOSIZE,
.max_write_size = SMB3_DEFAULT_IOSIZE, .max_write_size = SMB3_DEFAULT_IOSIZE,
.max_trans_size = SMB3_DEFAULT_TRANS_SIZE, .max_trans_size = SMB3_DEFAULT_TRANS_SIZE,
@ -59,7 +59,7 @@ static struct smb_version_values smb30_server_values = {
.cap_large_files = SMB2_LARGE_FILES, .cap_large_files = SMB2_LARGE_FILES,
.create_lease_size = sizeof(struct create_lease_v2), .create_lease_size = sizeof(struct create_lease_v2),
.create_durable_size = sizeof(struct create_durable_rsp), .create_durable_size = sizeof(struct create_durable_rsp),
.create_durable_v2_size = sizeof(struct create_durable_v2_rsp), .create_durable_v2_size = sizeof(struct create_durable_rsp_v2),
.create_mxac_size = sizeof(struct create_mxac_rsp), .create_mxac_size = sizeof(struct create_mxac_rsp),
.create_disk_id_size = sizeof(struct create_disk_id_rsp), .create_disk_id_size = sizeof(struct create_disk_id_rsp),
.create_posix_size = sizeof(struct create_posix_rsp), .create_posix_size = sizeof(struct create_posix_rsp),
@ -68,7 +68,7 @@ static struct smb_version_values smb30_server_values = {
static struct smb_version_values smb302_server_values = { static struct smb_version_values smb302_server_values = {
.version_string = SMB302_VERSION_STRING, .version_string = SMB302_VERSION_STRING,
.protocol_id = SMB302_PROT_ID, .protocol_id = SMB302_PROT_ID,
.capabilities = SMB2_GLOBAL_CAP_LARGE_MTU, .req_capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
.max_read_size = SMB3_DEFAULT_IOSIZE, .max_read_size = SMB3_DEFAULT_IOSIZE,
.max_write_size = SMB3_DEFAULT_IOSIZE, .max_write_size = SMB3_DEFAULT_IOSIZE,
.max_trans_size = SMB3_DEFAULT_TRANS_SIZE, .max_trans_size = SMB3_DEFAULT_TRANS_SIZE,
@ -86,7 +86,7 @@ static struct smb_version_values smb302_server_values = {
.cap_large_files = SMB2_LARGE_FILES, .cap_large_files = SMB2_LARGE_FILES,
.create_lease_size = sizeof(struct create_lease_v2), .create_lease_size = sizeof(struct create_lease_v2),
.create_durable_size = sizeof(struct create_durable_rsp), .create_durable_size = sizeof(struct create_durable_rsp),
.create_durable_v2_size = sizeof(struct create_durable_v2_rsp), .create_durable_v2_size = sizeof(struct create_durable_rsp_v2),
.create_mxac_size = sizeof(struct create_mxac_rsp), .create_mxac_size = sizeof(struct create_mxac_rsp),
.create_disk_id_size = sizeof(struct create_disk_id_rsp), .create_disk_id_size = sizeof(struct create_disk_id_rsp),
.create_posix_size = sizeof(struct create_posix_rsp), .create_posix_size = sizeof(struct create_posix_rsp),
@ -95,7 +95,7 @@ static struct smb_version_values smb302_server_values = {
static struct smb_version_values smb311_server_values = { static struct smb_version_values smb311_server_values = {
.version_string = SMB311_VERSION_STRING, .version_string = SMB311_VERSION_STRING,
.protocol_id = SMB311_PROT_ID, .protocol_id = SMB311_PROT_ID,
.capabilities = SMB2_GLOBAL_CAP_LARGE_MTU, .req_capabilities = SMB2_GLOBAL_CAP_LARGE_MTU,
.max_read_size = SMB3_DEFAULT_IOSIZE, .max_read_size = SMB3_DEFAULT_IOSIZE,
.max_write_size = SMB3_DEFAULT_IOSIZE, .max_write_size = SMB3_DEFAULT_IOSIZE,
.max_trans_size = SMB3_DEFAULT_TRANS_SIZE, .max_trans_size = SMB3_DEFAULT_TRANS_SIZE,
@ -113,7 +113,7 @@ static struct smb_version_values smb311_server_values = {
.cap_large_files = SMB2_LARGE_FILES, .cap_large_files = SMB2_LARGE_FILES,
.create_lease_size = sizeof(struct create_lease_v2), .create_lease_size = sizeof(struct create_lease_v2),
.create_durable_size = sizeof(struct create_durable_rsp), .create_durable_size = sizeof(struct create_durable_rsp),
.create_durable_v2_size = sizeof(struct create_durable_v2_rsp), .create_durable_v2_size = sizeof(struct create_durable_rsp_v2),
.create_mxac_size = sizeof(struct create_mxac_rsp), .create_mxac_size = sizeof(struct create_mxac_rsp),
.create_disk_id_size = sizeof(struct create_disk_id_rsp), .create_disk_id_size = sizeof(struct create_disk_id_rsp),
.create_posix_size = sizeof(struct create_posix_rsp), .create_posix_size = sizeof(struct create_posix_rsp),
@ -204,7 +204,7 @@ void init_smb2_1_server(struct ksmbd_conn *conn)
conn->signing_algorithm = SIGNING_ALG_HMAC_SHA256_LE; conn->signing_algorithm = SIGNING_ALG_HMAC_SHA256_LE;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING; conn->vals->req_capabilities |= SMB2_GLOBAL_CAP_LEASING;
} }
/** /**
@ -221,20 +221,20 @@ void init_smb3_0_server(struct ksmbd_conn *conn)
conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE; conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING | conn->vals->req_capabilities |= SMB2_GLOBAL_CAP_LEASING |
SMB2_GLOBAL_CAP_DIRECTORY_LEASING; SMB2_GLOBAL_CAP_DIRECTORY_LEASING;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION && if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION &&
conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION) conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION; conn->vals->req_capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION || if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION ||
(!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) && (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) &&
conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)) conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION))
conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION; conn->vals->req_capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL; conn->vals->req_capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
} }
/** /**
@ -251,19 +251,19 @@ void init_smb3_02_server(struct ksmbd_conn *conn)
conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE; conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING | conn->vals->req_capabilities |= SMB2_GLOBAL_CAP_LEASING |
SMB2_GLOBAL_CAP_DIRECTORY_LEASING; SMB2_GLOBAL_CAP_DIRECTORY_LEASING;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION || if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION ||
(!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) && (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) &&
conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION)) conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION))
conn->vals->capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION; conn->vals->req_capabilities |= SMB2_GLOBAL_CAP_ENCRYPTION;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL; conn->vals->req_capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE) if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_PERSISTENT_HANDLES; conn->vals->req_capabilities |= SMB2_GLOBAL_CAP_PERSISTENT_HANDLES;
} }
/** /**
@ -280,14 +280,14 @@ int init_smb3_11_server(struct ksmbd_conn *conn)
conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE; conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING | conn->vals->req_capabilities |= SMB2_GLOBAL_CAP_LEASING |
SMB2_GLOBAL_CAP_DIRECTORY_LEASING; SMB2_GLOBAL_CAP_DIRECTORY_LEASING;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL; conn->vals->req_capabilities |= SMB2_GLOBAL_CAP_MULTI_CHANNEL;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE) if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_PERSISTENT_HANDLES; conn->vals->req_capabilities |= SMB2_GLOBAL_CAP_PERSISTENT_HANDLES;
INIT_LIST_HEAD(&conn->preauth_sess_table); INIT_LIST_HEAD(&conn->preauth_sess_table);
return 0; return 0;

View File

@ -282,7 +282,7 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
/* Not setting conn guid rsp->ServerGUID, as it /* Not setting conn guid rsp->ServerGUID, as it
* not used by client for identifying connection * not used by client for identifying connection
*/ */
rsp->Capabilities = cpu_to_le32(conn->vals->capabilities); rsp->Capabilities = cpu_to_le32(conn->vals->req_capabilities);
/* Default Max Message Size till SMB2.0, 64K*/ /* Default Max Message Size till SMB2.0, 64K*/
rsp->MaxTransactSize = cpu_to_le32(conn->vals->max_trans_size); rsp->MaxTransactSize = cpu_to_le32(conn->vals->max_trans_size);
rsp->MaxReadSize = cpu_to_le32(conn->vals->max_read_size); rsp->MaxReadSize = cpu_to_le32(conn->vals->max_read_size);
@ -956,7 +956,7 @@ bool smb3_encryption_negotiated(struct ksmbd_conn *conn)
* SMB 3.0 and 3.0.2 dialects use the SMB2_GLOBAL_CAP_ENCRYPTION flag. * SMB 3.0 and 3.0.2 dialects use the SMB2_GLOBAL_CAP_ENCRYPTION flag.
* SMB 3.1.1 uses the cipher_type field. * SMB 3.1.1 uses the cipher_type field.
*/ */
return (conn->vals->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) || return (conn->vals->req_capabilities & SMB2_GLOBAL_CAP_ENCRYPTION) ||
conn->cipher_type; conn->cipher_type;
} }
@ -1210,7 +1210,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
rc = -EINVAL; rc = -EINVAL;
goto err_out; goto err_out;
} }
rsp->Capabilities = cpu_to_le32(conn->vals->capabilities); rsp->Capabilities = cpu_to_le32(conn->vals->req_capabilities);
/* For stats */ /* For stats */
conn->connection_type = conn->dialect; conn->connection_type = conn->dialect;
@ -1538,12 +1538,7 @@ static int ntlm_authenticate(struct ksmbd_work *work,
if (smb3_encryption_negotiated(conn) && if (smb3_encryption_negotiated(conn) &&
!(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) { !(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
rc = conn->ops->generate_encryptionkey(conn, sess); conn->ops->generate_encryptionkey(conn, sess);
if (rc) {
ksmbd_debug(SMB,
"SMB3 encryption key generation failed\n");
return -EINVAL;
}
sess->enc = true; sess->enc = true;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION) if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION)
rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE; rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
@ -1640,12 +1635,7 @@ static int krb5_authenticate(struct ksmbd_work *work,
if (smb3_encryption_negotiated(conn) && if (smb3_encryption_negotiated(conn) &&
!(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) { !(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
retval = conn->ops->generate_encryptionkey(conn, sess); conn->ops->generate_encryptionkey(conn, sess);
if (retval) {
ksmbd_debug(SMB,
"SMB3 encryption key generation failed\n");
return -EINVAL;
}
sess->enc = true; sess->enc = true;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION) if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION)
rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE; rsp->SessionFlags = SMB2_SESSION_FLAG_ENCRYPT_DATA_LE;
@ -2168,7 +2158,7 @@ static int smb2_create_open_flags(bool file_present, __le32 access,
* smb2_tree_disconnect() - handler for smb tree connect request * smb2_tree_disconnect() - handler for smb tree connect request
* @work: smb work containing request buffer * @work: smb work containing request buffer
* *
* Return: 0 * Return: 0 on success, otherwise error
*/ */
int smb2_tree_disconnect(struct ksmbd_work *work) int smb2_tree_disconnect(struct ksmbd_work *work)
{ {
@ -2200,7 +2190,6 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
goto err_out; goto err_out;
} }
WARN_ON_ONCE(atomic_dec_and_test(&tcon->refcount));
tcon->t_state = TREE_DISCONNECTED; tcon->t_state = TREE_DISCONNECTED;
write_unlock(&sess->tree_conns_lock); write_unlock(&sess->tree_conns_lock);
@ -2210,8 +2199,6 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
goto err_out; goto err_out;
} }
work->tcon = NULL;
rsp->StructureSize = cpu_to_le16(4); rsp->StructureSize = cpu_to_le16(4);
err = ksmbd_iov_pin_rsp(work, rsp, err = ksmbd_iov_pin_rsp(work, rsp,
sizeof(struct smb2_tree_disconnect_rsp)); sizeof(struct smb2_tree_disconnect_rsp));
@ -2232,7 +2219,7 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
* smb2_session_logoff() - handler for session log off request * smb2_session_logoff() - handler for session log off request
* @work: smb work containing request buffer * @work: smb work containing request buffer
* *
* Return: 0 * Return: 0 on success, otherwise error
*/ */
int smb2_session_logoff(struct ksmbd_work *work) int smb2_session_logoff(struct ksmbd_work *work)
{ {
@ -2726,7 +2713,7 @@ static int parse_durable_handle_context(struct ksmbd_work *work,
switch (dh_idx) { switch (dh_idx) {
case DURABLE_RECONN_V2: case DURABLE_RECONN_V2:
{ {
struct create_durable_reconn_v2_req *recon_v2; struct create_durable_handle_reconnect_v2 *recon_v2;
if (dh_info->type == DURABLE_RECONN || if (dh_info->type == DURABLE_RECONN ||
dh_info->type == DURABLE_REQ_V2) { dh_info->type == DURABLE_REQ_V2) {
@ -2736,13 +2723,13 @@ static int parse_durable_handle_context(struct ksmbd_work *work,
if (le16_to_cpu(context->DataOffset) + if (le16_to_cpu(context->DataOffset) +
le32_to_cpu(context->DataLength) < le32_to_cpu(context->DataLength) <
sizeof(struct create_durable_reconn_v2_req)) { sizeof(struct create_durable_handle_reconnect_v2)) {
err = -EINVAL; err = -EINVAL;
goto out; goto out;
} }
recon_v2 = (struct create_durable_reconn_v2_req *)context; recon_v2 = (struct create_durable_handle_reconnect_v2 *)context;
persistent_id = recon_v2->Fid.PersistentFileId; persistent_id = recon_v2->dcontext.Fid.PersistentFileId;
dh_info->fp = ksmbd_lookup_durable_fd(persistent_id); dh_info->fp = ksmbd_lookup_durable_fd(persistent_id);
if (!dh_info->fp) { if (!dh_info->fp) {
ksmbd_debug(SMB, "Failed to get durable handle state\n"); ksmbd_debug(SMB, "Failed to get durable handle state\n");
@ -2750,7 +2737,7 @@ static int parse_durable_handle_context(struct ksmbd_work *work,
goto out; goto out;
} }
if (memcmp(dh_info->fp->create_guid, recon_v2->CreateGuid, if (memcmp(dh_info->fp->create_guid, recon_v2->dcontext.CreateGuid,
SMB2_CREATE_GUID_SIZE)) { SMB2_CREATE_GUID_SIZE)) {
err = -EBADF; err = -EBADF;
ksmbd_put_durable_fd(dh_info->fp); ksmbd_put_durable_fd(dh_info->fp);
@ -2766,7 +2753,7 @@ static int parse_durable_handle_context(struct ksmbd_work *work,
} }
case DURABLE_RECONN: case DURABLE_RECONN:
{ {
struct create_durable_reconn_req *recon; create_durable_reconn_t *recon;
if (dh_info->type == DURABLE_RECONN_V2 || if (dh_info->type == DURABLE_RECONN_V2 ||
dh_info->type == DURABLE_REQ_V2) { dh_info->type == DURABLE_REQ_V2) {
@ -2776,12 +2763,12 @@ static int parse_durable_handle_context(struct ksmbd_work *work,
if (le16_to_cpu(context->DataOffset) + if (le16_to_cpu(context->DataOffset) +
le32_to_cpu(context->DataLength) < le32_to_cpu(context->DataLength) <
sizeof(struct create_durable_reconn_req)) { sizeof(create_durable_reconn_t)) {
err = -EINVAL; err = -EINVAL;
goto out; goto out;
} }
recon = (struct create_durable_reconn_req *)context; recon = (create_durable_reconn_t *)context;
persistent_id = recon->Data.Fid.PersistentFileId; persistent_id = recon->Data.Fid.PersistentFileId;
dh_info->fp = ksmbd_lookup_durable_fd(persistent_id); dh_info->fp = ksmbd_lookup_durable_fd(persistent_id);
if (!dh_info->fp) { if (!dh_info->fp) {
@ -2816,7 +2803,7 @@ static int parse_durable_handle_context(struct ksmbd_work *work,
durable_v2_blob = durable_v2_blob =
(struct create_durable_req_v2 *)context; (struct create_durable_req_v2 *)context;
ksmbd_debug(SMB, "Request for durable v2 open\n"); ksmbd_debug(SMB, "Request for durable v2 open\n");
dh_info->fp = ksmbd_lookup_fd_cguid(durable_v2_blob->CreateGuid); dh_info->fp = ksmbd_lookup_fd_cguid(durable_v2_blob->dcontext.CreateGuid);
if (dh_info->fp) { if (dh_info->fp) {
if (!memcmp(conn->ClientGUID, dh_info->fp->client_guid, if (!memcmp(conn->ClientGUID, dh_info->fp->client_guid,
SMB2_CLIENT_GUID_SIZE)) { SMB2_CLIENT_GUID_SIZE)) {
@ -2834,11 +2821,11 @@ static int parse_durable_handle_context(struct ksmbd_work *work,
if ((lc && (lc->req_state & SMB2_LEASE_HANDLE_CACHING_LE)) || if ((lc && (lc->req_state & SMB2_LEASE_HANDLE_CACHING_LE)) ||
req_op_level == SMB2_OPLOCK_LEVEL_BATCH) { req_op_level == SMB2_OPLOCK_LEVEL_BATCH) {
dh_info->CreateGuid = dh_info->CreateGuid =
durable_v2_blob->CreateGuid; durable_v2_blob->dcontext.CreateGuid;
dh_info->persistent = dh_info->persistent =
le32_to_cpu(durable_v2_blob->Flags); le32_to_cpu(durable_v2_blob->dcontext.Flags);
dh_info->timeout = dh_info->timeout =
le32_to_cpu(durable_v2_blob->Timeout); le32_to_cpu(durable_v2_blob->dcontext.Timeout);
dh_info->type = dh_idx; dh_info->type = dh_idx;
} }
break; break;
@ -3474,7 +3461,7 @@ int smb2_open(struct ksmbd_work *work)
share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp); share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp);
if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) || if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) ||
(req_op_level == SMB2_OPLOCK_LEVEL_LEASE && (req_op_level == SMB2_OPLOCK_LEVEL_LEASE &&
!(conn->vals->capabilities & SMB2_GLOBAL_CAP_LEASING))) { !(conn->vals->req_capabilities & SMB2_GLOBAL_CAP_LEASING))) {
if (share_ret < 0 && !S_ISDIR(file_inode(fp->filp)->i_mode)) { if (share_ret < 0 && !S_ISDIR(file_inode(fp->filp)->i_mode)) {
rc = share_ret; rc = share_ret;
goto err_out1; goto err_out1;
@ -3796,15 +3783,15 @@ static int readdir_info_level_struct_sz(int info_level)
{ {
switch (info_level) { switch (info_level) {
case FILE_FULL_DIRECTORY_INFORMATION: case FILE_FULL_DIRECTORY_INFORMATION:
return sizeof(struct file_full_directory_info); return sizeof(FILE_FULL_DIRECTORY_INFO);
case FILE_BOTH_DIRECTORY_INFORMATION: case FILE_BOTH_DIRECTORY_INFORMATION:
return sizeof(struct file_both_directory_info); return sizeof(FILE_BOTH_DIRECTORY_INFO);
case FILE_DIRECTORY_INFORMATION: case FILE_DIRECTORY_INFORMATION:
return sizeof(struct file_directory_info); return sizeof(FILE_DIRECTORY_INFO);
case FILE_NAMES_INFORMATION: case FILE_NAMES_INFORMATION:
return sizeof(struct file_names_info); return sizeof(struct file_names_info);
case FILEID_FULL_DIRECTORY_INFORMATION: case FILEID_FULL_DIRECTORY_INFORMATION:
return sizeof(struct file_id_full_dir_info); return sizeof(FILE_ID_FULL_DIR_INFO);
case FILEID_BOTH_DIRECTORY_INFORMATION: case FILEID_BOTH_DIRECTORY_INFORMATION:
return sizeof(struct file_id_both_directory_info); return sizeof(struct file_id_both_directory_info);
case SMB_FIND_FILE_POSIX_INFO: case SMB_FIND_FILE_POSIX_INFO:
@ -3819,9 +3806,9 @@ static int dentry_name(struct ksmbd_dir_info *d_info, int info_level)
switch (info_level) { switch (info_level) {
case FILE_FULL_DIRECTORY_INFORMATION: case FILE_FULL_DIRECTORY_INFORMATION:
{ {
struct file_full_directory_info *ffdinfo; FILE_FULL_DIRECTORY_INFO *ffdinfo;
ffdinfo = (struct file_full_directory_info *)d_info->rptr; ffdinfo = (FILE_FULL_DIRECTORY_INFO *)d_info->rptr;
d_info->rptr += le32_to_cpu(ffdinfo->NextEntryOffset); d_info->rptr += le32_to_cpu(ffdinfo->NextEntryOffset);
d_info->name = ffdinfo->FileName; d_info->name = ffdinfo->FileName;
d_info->name_len = le32_to_cpu(ffdinfo->FileNameLength); d_info->name_len = le32_to_cpu(ffdinfo->FileNameLength);
@ -3829,9 +3816,9 @@ static int dentry_name(struct ksmbd_dir_info *d_info, int info_level)
} }
case FILE_BOTH_DIRECTORY_INFORMATION: case FILE_BOTH_DIRECTORY_INFORMATION:
{ {
struct file_both_directory_info *fbdinfo; FILE_BOTH_DIRECTORY_INFO *fbdinfo;
fbdinfo = (struct file_both_directory_info *)d_info->rptr; fbdinfo = (FILE_BOTH_DIRECTORY_INFO *)d_info->rptr;
d_info->rptr += le32_to_cpu(fbdinfo->NextEntryOffset); d_info->rptr += le32_to_cpu(fbdinfo->NextEntryOffset);
d_info->name = fbdinfo->FileName; d_info->name = fbdinfo->FileName;
d_info->name_len = le32_to_cpu(fbdinfo->FileNameLength); d_info->name_len = le32_to_cpu(fbdinfo->FileNameLength);
@ -3839,9 +3826,9 @@ static int dentry_name(struct ksmbd_dir_info *d_info, int info_level)
} }
case FILE_DIRECTORY_INFORMATION: case FILE_DIRECTORY_INFORMATION:
{ {
struct file_directory_info *fdinfo; FILE_DIRECTORY_INFO *fdinfo;
fdinfo = (struct file_directory_info *)d_info->rptr; fdinfo = (FILE_DIRECTORY_INFO *)d_info->rptr;
d_info->rptr += le32_to_cpu(fdinfo->NextEntryOffset); d_info->rptr += le32_to_cpu(fdinfo->NextEntryOffset);
d_info->name = fdinfo->FileName; d_info->name = fdinfo->FileName;
d_info->name_len = le32_to_cpu(fdinfo->FileNameLength); d_info->name_len = le32_to_cpu(fdinfo->FileNameLength);
@ -3859,9 +3846,9 @@ static int dentry_name(struct ksmbd_dir_info *d_info, int info_level)
} }
case FILEID_FULL_DIRECTORY_INFORMATION: case FILEID_FULL_DIRECTORY_INFORMATION:
{ {
struct file_id_full_dir_info *dinfo; FILE_ID_FULL_DIR_INFO *dinfo;
dinfo = (struct file_id_full_dir_info *)d_info->rptr; dinfo = (FILE_ID_FULL_DIR_INFO *)d_info->rptr;
d_info->rptr += le32_to_cpu(dinfo->NextEntryOffset); d_info->rptr += le32_to_cpu(dinfo->NextEntryOffset);
d_info->name = dinfo->FileName; d_info->name = dinfo->FileName;
d_info->name_len = le32_to_cpu(dinfo->FileNameLength); d_info->name_len = le32_to_cpu(dinfo->FileNameLength);
@ -3944,9 +3931,9 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
switch (info_level) { switch (info_level) {
case FILE_FULL_DIRECTORY_INFORMATION: case FILE_FULL_DIRECTORY_INFORMATION:
{ {
struct file_full_directory_info *ffdinfo; FILE_FULL_DIRECTORY_INFO *ffdinfo;
ffdinfo = (struct file_full_directory_info *)kstat; ffdinfo = (FILE_FULL_DIRECTORY_INFO *)kstat;
ffdinfo->FileNameLength = cpu_to_le32(conv_len); ffdinfo->FileNameLength = cpu_to_le32(conv_len);
ffdinfo->EaSize = ffdinfo->EaSize =
smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode); smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
@ -3960,9 +3947,9 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
} }
case FILE_BOTH_DIRECTORY_INFORMATION: case FILE_BOTH_DIRECTORY_INFORMATION:
{ {
struct file_both_directory_info *fbdinfo; FILE_BOTH_DIRECTORY_INFO *fbdinfo;
fbdinfo = (struct file_both_directory_info *)kstat; fbdinfo = (FILE_BOTH_DIRECTORY_INFO *)kstat;
fbdinfo->FileNameLength = cpu_to_le32(conv_len); fbdinfo->FileNameLength = cpu_to_le32(conv_len);
fbdinfo->EaSize = fbdinfo->EaSize =
smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode); smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
@ -3978,9 +3965,9 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
} }
case FILE_DIRECTORY_INFORMATION: case FILE_DIRECTORY_INFORMATION:
{ {
struct file_directory_info *fdinfo; FILE_DIRECTORY_INFO *fdinfo;
fdinfo = (struct file_directory_info *)kstat; fdinfo = (FILE_DIRECTORY_INFO *)kstat;
fdinfo->FileNameLength = cpu_to_le32(conv_len); fdinfo->FileNameLength = cpu_to_le32(conv_len);
if (d_info->hide_dot_file && d_info->name[0] == '.') if (d_info->hide_dot_file && d_info->name[0] == '.')
fdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE; fdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
@ -4000,9 +3987,9 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
} }
case FILEID_FULL_DIRECTORY_INFORMATION: case FILEID_FULL_DIRECTORY_INFORMATION:
{ {
struct file_id_full_dir_info *dinfo; FILE_ID_FULL_DIR_INFO *dinfo;
dinfo = (struct file_id_full_dir_info *)kstat; dinfo = (FILE_ID_FULL_DIR_INFO *)kstat;
dinfo->FileNameLength = cpu_to_le32(conv_len); dinfo->FileNameLength = cpu_to_le32(conv_len);
dinfo->EaSize = dinfo->EaSize =
smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode); smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
@ -4206,9 +4193,9 @@ static int reserve_populate_dentry(struct ksmbd_dir_info *d_info,
switch (info_level) { switch (info_level) {
case FILE_FULL_DIRECTORY_INFORMATION: case FILE_FULL_DIRECTORY_INFORMATION:
{ {
struct file_full_directory_info *ffdinfo; FILE_FULL_DIRECTORY_INFO *ffdinfo;
ffdinfo = (struct file_full_directory_info *)d_info->wptr; ffdinfo = (FILE_FULL_DIRECTORY_INFO *)d_info->wptr;
memcpy(ffdinfo->FileName, d_info->name, d_info->name_len); memcpy(ffdinfo->FileName, d_info->name, d_info->name_len);
ffdinfo->FileName[d_info->name_len] = 0x00; ffdinfo->FileName[d_info->name_len] = 0x00;
ffdinfo->FileNameLength = cpu_to_le32(d_info->name_len); ffdinfo->FileNameLength = cpu_to_le32(d_info->name_len);
@ -4217,9 +4204,9 @@ static int reserve_populate_dentry(struct ksmbd_dir_info *d_info,
} }
case FILE_BOTH_DIRECTORY_INFORMATION: case FILE_BOTH_DIRECTORY_INFORMATION:
{ {
struct file_both_directory_info *fbdinfo; FILE_BOTH_DIRECTORY_INFO *fbdinfo;
fbdinfo = (struct file_both_directory_info *)d_info->wptr; fbdinfo = (FILE_BOTH_DIRECTORY_INFO *)d_info->wptr;
memcpy(fbdinfo->FileName, d_info->name, d_info->name_len); memcpy(fbdinfo->FileName, d_info->name, d_info->name_len);
fbdinfo->FileName[d_info->name_len] = 0x00; fbdinfo->FileName[d_info->name_len] = 0x00;
fbdinfo->FileNameLength = cpu_to_le32(d_info->name_len); fbdinfo->FileNameLength = cpu_to_le32(d_info->name_len);
@ -4228,9 +4215,9 @@ static int reserve_populate_dentry(struct ksmbd_dir_info *d_info,
} }
case FILE_DIRECTORY_INFORMATION: case FILE_DIRECTORY_INFORMATION:
{ {
struct file_directory_info *fdinfo; FILE_DIRECTORY_INFO *fdinfo;
fdinfo = (struct file_directory_info *)d_info->wptr; fdinfo = (FILE_DIRECTORY_INFO *)d_info->wptr;
memcpy(fdinfo->FileName, d_info->name, d_info->name_len); memcpy(fdinfo->FileName, d_info->name, d_info->name_len);
fdinfo->FileName[d_info->name_len] = 0x00; fdinfo->FileName[d_info->name_len] = 0x00;
fdinfo->FileNameLength = cpu_to_le32(d_info->name_len); fdinfo->FileNameLength = cpu_to_le32(d_info->name_len);
@ -4250,9 +4237,9 @@ static int reserve_populate_dentry(struct ksmbd_dir_info *d_info,
} }
case FILEID_FULL_DIRECTORY_INFORMATION: case FILEID_FULL_DIRECTORY_INFORMATION:
{ {
struct file_id_full_dir_info *dinfo; FILE_ID_FULL_DIR_INFO *dinfo;
dinfo = (struct file_id_full_dir_info *)d_info->wptr; dinfo = (FILE_ID_FULL_DIR_INFO *)d_info->wptr;
memcpy(dinfo->FileName, d_info->name, d_info->name_len); memcpy(dinfo->FileName, d_info->name, d_info->name_len);
dinfo->FileName[d_info->name_len] = 0x00; dinfo->FileName[d_info->name_len] = 0x00;
dinfo->FileNameLength = cpu_to_le32(d_info->name_len); dinfo->FileNameLength = cpu_to_le32(d_info->name_len);
@ -4514,7 +4501,7 @@ int smb2_query_dir(struct ksmbd_work *work)
goto err_out; goto err_out;
} else { } else {
no_buf_len: no_buf_len:
((struct file_directory_info *) ((FILE_DIRECTORY_INFO *)
((char *)rsp->Buffer + d_info.last_entry_offset)) ((char *)rsp->Buffer + d_info.last_entry_offset))
->NextEntryOffset = 0; ->NextEntryOffset = 0;
if (d_info.data_count >= d_info.last_entry_off_align) if (d_info.data_count >= d_info.last_entry_off_align)
@ -4560,7 +4547,7 @@ int smb2_query_dir(struct ksmbd_work *work)
smb2_set_err_rsp(work); smb2_set_err_rsp(work);
ksmbd_fd_put(work, dir_fp); ksmbd_fd_put(work, dir_fp);
ksmbd_revert_fsids(work); ksmbd_revert_fsids(work);
return 0; return rc;
} }
/** /**
@ -5133,7 +5120,7 @@ static int get_file_internal_info(struct smb2_query_info_rsp *rsp,
static int get_file_network_open_info(struct smb2_query_info_rsp *rsp, static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
struct ksmbd_file *fp, void *rsp_org) struct ksmbd_file *fp, void *rsp_org)
{ {
struct smb2_file_ntwrk_info *file_info; struct smb2_file_network_open_info *file_info;
struct kstat stat; struct kstat stat;
u64 time; u64 time;
int ret; int ret;
@ -5149,7 +5136,7 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
if (ret) if (ret)
return ret; return ret;
file_info = (struct smb2_file_ntwrk_info *)rsp->Buffer; file_info = (struct smb2_file_network_open_info *)rsp->Buffer;
file_info->CreationTime = cpu_to_le64(fp->create_time); file_info->CreationTime = cpu_to_le64(fp->create_time);
time = ksmbd_UnixTimeToNT(stat.atime); time = ksmbd_UnixTimeToNT(stat.atime);
@ -5168,7 +5155,7 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
} }
file_info->Reserved = cpu_to_le32(0); file_info->Reserved = cpu_to_le32(0);
rsp->OutputBufferLength = rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_ntwrk_info)); cpu_to_le32(sizeof(struct smb2_file_network_open_info));
return 0; return 0;
} }
@ -5476,9 +5463,9 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
switch (fsinfoclass) { switch (fsinfoclass) {
case FS_DEVICE_INFORMATION: case FS_DEVICE_INFORMATION:
{ {
struct filesystem_device_info *info; FILE_SYSTEM_DEVICE_INFO *info;
info = (struct filesystem_device_info *)rsp->Buffer; info = (FILE_SYSTEM_DEVICE_INFO *)rsp->Buffer;
info->DeviceType = cpu_to_le32(FILE_DEVICE_DISK); info->DeviceType = cpu_to_le32(FILE_DEVICE_DISK);
info->DeviceCharacteristics = info->DeviceCharacteristics =
@ -5492,10 +5479,10 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
} }
case FS_ATTRIBUTE_INFORMATION: case FS_ATTRIBUTE_INFORMATION:
{ {
struct filesystem_attribute_info *info; FILE_SYSTEM_ATTRIBUTE_INFO *info;
size_t sz; size_t sz;
info = (struct filesystem_attribute_info *)rsp->Buffer; info = (FILE_SYSTEM_ATTRIBUTE_INFO *)rsp->Buffer;
info->Attributes = cpu_to_le32(FILE_SUPPORTS_OBJECT_IDS | info->Attributes = cpu_to_le32(FILE_SUPPORTS_OBJECT_IDS |
FILE_PERSISTENT_ACLS | FILE_PERSISTENT_ACLS |
FILE_UNICODE_ON_DISK | FILE_UNICODE_ON_DISK |
@ -5514,7 +5501,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
"NTFS", PATH_MAX, conn->local_nls, 0); "NTFS", PATH_MAX, conn->local_nls, 0);
len = len * 2; len = len * 2;
info->FileSystemNameLen = cpu_to_le32(len); info->FileSystemNameLen = cpu_to_le32(len);
sz = sizeof(struct filesystem_attribute_info) + len; sz = sizeof(FILE_SYSTEM_ATTRIBUTE_INFO) + len;
rsp->OutputBufferLength = cpu_to_le32(sz); rsp->OutputBufferLength = cpu_to_le32(sz);
break; break;
} }
@ -5546,11 +5533,11 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
} }
case FS_SIZE_INFORMATION: case FS_SIZE_INFORMATION:
{ {
struct filesystem_info *info; FILE_SYSTEM_SIZE_INFO *info;
info = (struct filesystem_info *)(rsp->Buffer); info = (FILE_SYSTEM_SIZE_INFO *)(rsp->Buffer);
info->TotalAllocationUnits = cpu_to_le64(stfs.f_blocks); info->TotalAllocationUnits = cpu_to_le64(stfs.f_blocks);
info->FreeAllocationUnits = cpu_to_le64(stfs.f_bfree); info->AvailableAllocationUnits = cpu_to_le64(stfs.f_bfree);
info->SectorsPerAllocationUnit = cpu_to_le32(1); info->SectorsPerAllocationUnit = cpu_to_le32(1);
info->BytesPerSector = cpu_to_le32(stfs.f_bsize); info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
rsp->OutputBufferLength = cpu_to_le32(24); rsp->OutputBufferLength = cpu_to_le32(24);
@ -5633,14 +5620,14 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
} }
case FS_POSIX_INFORMATION: case FS_POSIX_INFORMATION:
{ {
struct filesystem_posix_info *info; FILE_SYSTEM_POSIX_INFO *info;
if (!work->tcon->posix_extensions) { if (!work->tcon->posix_extensions) {
pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n"); pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
path_put(&path); path_put(&path);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} else { } else {
info = (struct filesystem_posix_info *)(rsp->Buffer); info = (FILE_SYSTEM_POSIX_INFO *)(rsp->Buffer);
info->OptimalTransferSize = cpu_to_le32(stfs.f_bsize); info->OptimalTransferSize = cpu_to_le32(stfs.f_bsize);
info->BlockSize = cpu_to_le32(stfs.f_bsize); info->BlockSize = cpu_to_le32(stfs.f_bsize);
info->TotalBlocks = cpu_to_le64(stfs.f_blocks); info->TotalBlocks = cpu_to_le64(stfs.f_blocks);
@ -5844,7 +5831,7 @@ static noinline int smb2_close_pipe(struct ksmbd_work *work)
* smb2_close() - handler for smb2 close file command * smb2_close() - handler for smb2 close file command
* @work: smb work containing close request buffer * @work: smb work containing close request buffer
* *
* Return: 0 * Return: 0 on success, otherwise error
*/ */
int smb2_close(struct ksmbd_work *work) int smb2_close(struct ksmbd_work *work)
{ {
@ -5969,7 +5956,7 @@ int smb2_close(struct ksmbd_work *work)
* smb2_echo() - handler for smb2 echo(ping) command * smb2_echo() - handler for smb2 echo(ping) command
* @work: smb work containing echo request buffer * @work: smb work containing echo request buffer
* *
* Return: 0 * Return: 0 on success, otherwise error
*/ */
int smb2_echo(struct ksmbd_work *work) int smb2_echo(struct ksmbd_work *work)
{ {
@ -6396,7 +6383,6 @@ static int set_file_mode_info(struct ksmbd_file *fp,
* @share: ksmbd_share_config pointer * @share: ksmbd_share_config pointer
* *
* Return: 0 on success, otherwise error * Return: 0 on success, otherwise error
* TODO: need to implement an error handling for STATUS_INFO_LENGTH_MISMATCH
*/ */
static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp, static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
struct smb2_set_info_req *req, struct smb2_set_info_req *req,
@ -6409,14 +6395,14 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
case FILE_BASIC_INFORMATION: case FILE_BASIC_INFORMATION:
{ {
if (buf_len < sizeof(struct smb2_file_basic_info)) if (buf_len < sizeof(struct smb2_file_basic_info))
return -EINVAL; return -EMSGSIZE;
return set_file_basic_info(fp, (struct smb2_file_basic_info *)buffer, share); return set_file_basic_info(fp, (struct smb2_file_basic_info *)buffer, share);
} }
case FILE_ALLOCATION_INFORMATION: case FILE_ALLOCATION_INFORMATION:
{ {
if (buf_len < sizeof(struct smb2_file_alloc_info)) if (buf_len < sizeof(struct smb2_file_alloc_info))
return -EINVAL; return -EMSGSIZE;
return set_file_allocation_info(work, fp, return set_file_allocation_info(work, fp,
(struct smb2_file_alloc_info *)buffer); (struct smb2_file_alloc_info *)buffer);
@ -6424,7 +6410,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
case FILE_END_OF_FILE_INFORMATION: case FILE_END_OF_FILE_INFORMATION:
{ {
if (buf_len < sizeof(struct smb2_file_eof_info)) if (buf_len < sizeof(struct smb2_file_eof_info))
return -EINVAL; return -EMSGSIZE;
return set_end_of_file_info(work, fp, return set_end_of_file_info(work, fp,
(struct smb2_file_eof_info *)buffer); (struct smb2_file_eof_info *)buffer);
@ -6432,7 +6418,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
case FILE_RENAME_INFORMATION: case FILE_RENAME_INFORMATION:
{ {
if (buf_len < sizeof(struct smb2_file_rename_info)) if (buf_len < sizeof(struct smb2_file_rename_info))
return -EINVAL; return -EMSGSIZE;
return set_rename_info(work, fp, return set_rename_info(work, fp,
(struct smb2_file_rename_info *)buffer, (struct smb2_file_rename_info *)buffer,
@ -6441,7 +6427,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
case FILE_LINK_INFORMATION: case FILE_LINK_INFORMATION:
{ {
if (buf_len < sizeof(struct smb2_file_link_info)) if (buf_len < sizeof(struct smb2_file_link_info))
return -EINVAL; return -EMSGSIZE;
return smb2_create_link(work, work->tcon->share_conf, return smb2_create_link(work, work->tcon->share_conf,
(struct smb2_file_link_info *)buffer, (struct smb2_file_link_info *)buffer,
@ -6451,7 +6437,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
case FILE_DISPOSITION_INFORMATION: case FILE_DISPOSITION_INFORMATION:
{ {
if (buf_len < sizeof(struct smb2_file_disposition_info)) if (buf_len < sizeof(struct smb2_file_disposition_info))
return -EINVAL; return -EMSGSIZE;
return set_file_disposition_info(fp, return set_file_disposition_info(fp,
(struct smb2_file_disposition_info *)buffer); (struct smb2_file_disposition_info *)buffer);
@ -6465,7 +6451,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
} }
if (buf_len < sizeof(struct smb2_ea_info)) if (buf_len < sizeof(struct smb2_ea_info))
return -EINVAL; return -EMSGSIZE;
return smb2_set_ea((struct smb2_ea_info *)buffer, return smb2_set_ea((struct smb2_ea_info *)buffer,
buf_len, &fp->filp->f_path, true); buf_len, &fp->filp->f_path, true);
@ -6473,14 +6459,14 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
case FILE_POSITION_INFORMATION: case FILE_POSITION_INFORMATION:
{ {
if (buf_len < sizeof(struct smb2_file_pos_info)) if (buf_len < sizeof(struct smb2_file_pos_info))
return -EINVAL; return -EMSGSIZE;
return set_file_position_info(fp, (struct smb2_file_pos_info *)buffer); return set_file_position_info(fp, (struct smb2_file_pos_info *)buffer);
} }
case FILE_MODE_INFORMATION: case FILE_MODE_INFORMATION:
{ {
if (buf_len < sizeof(struct smb2_file_mode_info)) if (buf_len < sizeof(struct smb2_file_mode_info))
return -EINVAL; return -EMSGSIZE;
return set_file_mode_info(fp, (struct smb2_file_mode_info *)buffer); return set_file_mode_info(fp, (struct smb2_file_mode_info *)buffer);
} }
@ -6587,6 +6573,8 @@ int smb2_set_info(struct ksmbd_work *work)
rsp->hdr.Status = STATUS_ACCESS_DENIED; rsp->hdr.Status = STATUS_ACCESS_DENIED;
else if (rc == -EINVAL) else if (rc == -EINVAL)
rsp->hdr.Status = STATUS_INVALID_PARAMETER; rsp->hdr.Status = STATUS_INVALID_PARAMETER;
else if (rc == -EMSGSIZE)
rsp->hdr.Status = STATUS_INFO_LENGTH_MISMATCH;
else if (rc == -ESHARE) else if (rc == -ESHARE)
rsp->hdr.Status = STATUS_SHARING_VIOLATION; rsp->hdr.Status = STATUS_SHARING_VIOLATION;
else if (rc == -ENOENT) else if (rc == -ENOENT)
@ -6842,7 +6830,7 @@ int smb2_read(struct ksmbd_work *work)
rsp->hdr.Status = STATUS_END_OF_FILE; rsp->hdr.Status = STATUS_END_OF_FILE;
smb2_set_err_rsp(work); smb2_set_err_rsp(work);
ksmbd_fd_put(work, fp); ksmbd_fd_put(work, fp);
return 0; return -ENODATA;
} }
ksmbd_debug(SMB, "nbytes %zu, offset %lld mincount %zu\n", ksmbd_debug(SMB, "nbytes %zu, offset %lld mincount %zu\n",
@ -7764,11 +7752,11 @@ static int fsctl_copychunk(struct ksmbd_work *work,
} }
src_fp = ksmbd_lookup_foreign_fd(work, src_fp = ksmbd_lookup_foreign_fd(work,
le64_to_cpu(ci_req->ResumeKey[0])); le64_to_cpu(ci_req->SourceKeyU64[0]));
dst_fp = ksmbd_lookup_fd_slow(work, volatile_id, persistent_id); dst_fp = ksmbd_lookup_fd_slow(work, volatile_id, persistent_id);
ret = -EINVAL; ret = -EINVAL;
if (!src_fp || if (!src_fp ||
src_fp->persistent_id != le64_to_cpu(ci_req->ResumeKey[1])) { src_fp->persistent_id != le64_to_cpu(ci_req->SourceKeyU64[1])) {
rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND; rsp->hdr.Status = STATUS_OBJECT_NAME_NOT_FOUND;
goto out; goto out;
} }
@ -7876,9 +7864,9 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
nii_rsp->Capability = 0; nii_rsp->Capability = 0;
if (netdev->real_num_tx_queues > 1) if (netdev->real_num_tx_queues > 1)
nii_rsp->Capability |= cpu_to_le32(RSS_CAPABLE); nii_rsp->Capability |= RSS_CAPABLE;
if (ksmbd_rdma_capable_netdev(netdev)) if (ksmbd_rdma_capable_netdev(netdev))
nii_rsp->Capability |= cpu_to_le32(RDMA_CAPABLE); nii_rsp->Capability |= RDMA_CAPABLE;
nii_rsp->Next = cpu_to_le32(152); nii_rsp->Next = cpu_to_le32(152);
nii_rsp->Reserved = 0; nii_rsp->Reserved = 0;
@ -7904,13 +7892,13 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
if (!ipv4_set) { if (!ipv4_set) {
struct in_device *idev; struct in_device *idev;
sockaddr_storage->Family = cpu_to_le16(INTERNETWORK); sockaddr_storage->Family = INTERNETWORK;
sockaddr_storage->addr4.Port = 0; sockaddr_storage->addr4.Port = 0;
idev = __in_dev_get_rtnl(netdev); idev = __in_dev_get_rtnl(netdev);
if (!idev) if (!idev)
continue; continue;
sockaddr_storage->addr4.IPv4address = sockaddr_storage->addr4.IPv4Address =
idev_ipv4_address(idev); idev_ipv4_address(idev);
nbytes += sizeof(struct network_interface_info_ioctl_rsp); nbytes += sizeof(struct network_interface_info_ioctl_rsp);
ipv4_set = true; ipv4_set = true;
@ -7918,9 +7906,9 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
} else { } else {
struct inet6_dev *idev6; struct inet6_dev *idev6;
struct inet6_ifaddr *ifa; struct inet6_ifaddr *ifa;
__u8 *ipv6_addr = sockaddr_storage->addr6.IPv6address; __u8 *ipv6_addr = sockaddr_storage->addr6.IPv6Address;
sockaddr_storage->Family = cpu_to_le16(INTERNETWORKV6); sockaddr_storage->Family = INTERNETWORKV6;
sockaddr_storage->addr6.Port = 0; sockaddr_storage->addr6.Port = 0;
sockaddr_storage->addr6.FlowInfo = 0; sockaddr_storage->addr6.FlowInfo = 0;
@ -7984,7 +7972,7 @@ static int fsctl_validate_negotiate_info(struct ksmbd_conn *conn,
goto err_out; goto err_out;
} }
neg_rsp->Capabilities = cpu_to_le32(conn->vals->capabilities); neg_rsp->Capabilities = cpu_to_le32(conn->vals->req_capabilities);
memset(neg_rsp->Guid, 0, SMB2_CLIENT_GUID_SIZE); memset(neg_rsp->Guid, 0, SMB2_CLIENT_GUID_SIZE);
neg_rsp->SecurityMode = cpu_to_le16(conn->srv_sec_mode); neg_rsp->SecurityMode = cpu_to_le16(conn->srv_sec_mode);
neg_rsp->Dialect = cpu_to_le16(conn->dialect); neg_rsp->Dialect = cpu_to_le16(conn->dialect);
@ -8122,8 +8110,8 @@ static int fsctl_request_resume_key(struct ksmbd_work *work,
return -ENOENT; return -ENOENT;
memset(key_rsp, 0, sizeof(*key_rsp)); memset(key_rsp, 0, sizeof(*key_rsp));
key_rsp->ResumeKey[0] = req->VolatileFileId; key_rsp->ResumeKeyU64[0] = req->VolatileFileId;
key_rsp->ResumeKey[1] = req->PersistentFileId; key_rsp->ResumeKeyU64[1] = req->PersistentFileId;
ksmbd_fd_put(work, fp); ksmbd_fd_put(work, fp);
return 0; return 0;
@ -8164,7 +8152,7 @@ int smb2_ioctl(struct ksmbd_work *work)
id = req->VolatileFileId; id = req->VolatileFileId;
if (req->Flags != cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL)) { if (req->Flags != cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL)) {
rsp->hdr.Status = STATUS_NOT_SUPPORTED; ret = -EOPNOTSUPP;
goto out; goto out;
} }
@ -8184,8 +8172,9 @@ int smb2_ioctl(struct ksmbd_work *work)
case FSCTL_DFS_GET_REFERRALS: case FSCTL_DFS_GET_REFERRALS:
case FSCTL_DFS_GET_REFERRALS_EX: case FSCTL_DFS_GET_REFERRALS_EX:
/* Not support DFS yet */ /* Not support DFS yet */
ret = -EOPNOTSUPP;
rsp->hdr.Status = STATUS_FS_DRIVER_REQUIRED; rsp->hdr.Status = STATUS_FS_DRIVER_REQUIRED;
goto out; goto out2;
case FSCTL_CREATE_OR_GET_OBJECT_ID: case FSCTL_CREATE_OR_GET_OBJECT_ID:
{ {
struct file_object_buf_type1_ioctl_rsp *obj_buf; struct file_object_buf_type1_ioctl_rsp *obj_buf;
@ -8475,8 +8464,10 @@ int smb2_ioctl(struct ksmbd_work *work)
rsp->hdr.Status = STATUS_BUFFER_TOO_SMALL; rsp->hdr.Status = STATUS_BUFFER_TOO_SMALL;
else if (ret < 0 || rsp->hdr.Status == 0) else if (ret < 0 || rsp->hdr.Status == 0)
rsp->hdr.Status = STATUS_INVALID_PARAMETER; rsp->hdr.Status = STATUS_INVALID_PARAMETER;
out2:
smb2_set_err_rsp(work); smb2_set_err_rsp(work);
return 0; return ret;
} }
/** /**
@ -8755,7 +8746,7 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
* smb2_oplock_break() - dispatcher for smb2.0 and 2.1 oplock/lease break * smb2_oplock_break() - dispatcher for smb2.0 and 2.1 oplock/lease break
* @work: smb work containing oplock/lease break command buffer * @work: smb work containing oplock/lease break command buffer
* *
* Return: 0 * Return: 0 on success, otherwise error
*/ */
int smb2_oplock_break(struct ksmbd_work *work) int smb2_oplock_break(struct ksmbd_work *work)
{ {
@ -8778,6 +8769,7 @@ int smb2_oplock_break(struct ksmbd_work *work)
le16_to_cpu(req->StructureSize)); le16_to_cpu(req->StructureSize));
rsp->hdr.Status = STATUS_INVALID_PARAMETER; rsp->hdr.Status = STATUS_INVALID_PARAMETER;
smb2_set_err_rsp(work); smb2_set_err_rsp(work);
return -EINVAL;
} }
return 0; return 0;
@ -8787,7 +8779,7 @@ int smb2_oplock_break(struct ksmbd_work *work)
* smb2_notify() - handler for smb2 notify request * smb2_notify() - handler for smb2 notify request
* @work: smb work containing notify command buffer * @work: smb work containing notify command buffer
* *
* Return: 0 * Return: 0 on success, otherwise error
*/ */
int smb2_notify(struct ksmbd_work *work) int smb2_notify(struct ksmbd_work *work)
{ {
@ -8801,12 +8793,12 @@ int smb2_notify(struct ksmbd_work *work)
if (work->next_smb2_rcv_hdr_off && req->hdr.NextCommand) { if (work->next_smb2_rcv_hdr_off && req->hdr.NextCommand) {
rsp->hdr.Status = STATUS_INTERNAL_ERROR; rsp->hdr.Status = STATUS_INTERNAL_ERROR;
smb2_set_err_rsp(work); smb2_set_err_rsp(work);
return 0; return -EIO;
} }
smb2_set_err_rsp(work); smb2_set_err_rsp(work);
rsp->hdr.Status = STATUS_NOT_IMPLEMENTED; rsp->hdr.Status = STATUS_NOT_IMPLEMENTED;
return 0; return -EOPNOTSUPP;
} }
/** /**
@ -8861,9 +8853,8 @@ int smb2_check_sign_req(struct ksmbd_work *work)
iov[0].iov_base = (char *)&hdr->ProtocolId; iov[0].iov_base = (char *)&hdr->ProtocolId;
iov[0].iov_len = len; iov[0].iov_len = len;
if (ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, 1, ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, 1,
signature)) signature);
return 0;
if (memcmp(signature, signature_req, SMB2_SIGNATURE_SIZE)) { if (memcmp(signature, signature_req, SMB2_SIGNATURE_SIZE)) {
pr_err("bad smb2 signature\n"); pr_err("bad smb2 signature\n");
@ -8896,9 +8887,9 @@ void smb2_set_sign_rsp(struct ksmbd_work *work)
iov = &work->iov[work->iov_idx]; iov = &work->iov[work->iov_idx];
} }
if (!ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, n_vec, ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, n_vec,
signature)) signature);
memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE); memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE);
} }
/** /**

View File

@ -66,40 +66,8 @@ struct preauth_integrity_info {
/* Apple Defined Contexts */ /* Apple Defined Contexts */
#define SMB2_CREATE_AAPL "AAPL" #define SMB2_CREATE_AAPL "AAPL"
struct create_durable_req_v2 {
struct create_context_hdr ccontext;
__u8 Name[8];
__le32 Timeout;
__le32 Flags;
__u8 Reserved[8];
__u8 CreateGuid[16];
} __packed;
#define DURABLE_HANDLE_MAX_TIMEOUT 300000 #define DURABLE_HANDLE_MAX_TIMEOUT 300000
struct create_durable_reconn_req {
struct create_context_hdr ccontext;
__u8 Name[8];
union {
__u8 Reserved[16];
struct {
__u64 PersistentFileId;
__u64 VolatileFileId;
} Fid;
} Data;
} __packed;
struct create_durable_reconn_v2_req {
struct create_context_hdr ccontext;
__u8 Name[8];
struct {
__u64 PersistentFileId;
__u64 VolatileFileId;
} Fid;
__u8 CreateGuid[16];
__le32 Flags;
} __packed;
struct create_alloc_size_req { struct create_alloc_size_req {
struct create_context_hdr ccontext; struct create_context_hdr ccontext;
__u8 Name[8]; __u8 Name[8];
@ -115,16 +83,6 @@ struct create_durable_rsp {
} Data; } Data;
} __packed; } __packed;
/* See MS-SMB2 2.2.13.2.11 */
/* Flags */
#define SMB2_DHANDLE_FLAG_PERSISTENT 0x00000002
struct create_durable_v2_rsp {
struct create_context_hdr ccontext;
__u8 Name[8];
__le32 Timeout;
__le32 Flags;
} __packed;
/* equivalent of the contents of SMB3.1.1 POSIX open context response */ /* equivalent of the contents of SMB3.1.1 POSIX open context response */
struct create_posix_rsp { struct create_posix_rsp {
struct create_context_hdr ccontext; struct create_context_hdr ccontext;
@ -138,22 +96,6 @@ struct create_posix_rsp {
#define SMB2_0_IOCTL_IS_FSCTL 0x00000001 #define SMB2_0_IOCTL_IS_FSCTL 0x00000001
struct smb_sockaddr_in {
__be16 Port;
__be32 IPv4address;
__u8 Reserved[8];
} __packed;
struct smb_sockaddr_in6 {
__be16 Port;
__be32 FlowInfo;
__u8 IPv6address[16];
__be32 ScopeId;
} __packed;
#define INTERNETWORK 0x0002
#define INTERNETWORKV6 0x0017
struct sockaddr_storage_rsp { struct sockaddr_storage_rsp {
__le16 Family; __le16 Family;
union { union {
@ -162,18 +104,6 @@ struct sockaddr_storage_rsp {
}; };
} __packed; } __packed;
#define RSS_CAPABLE 0x00000001
#define RDMA_CAPABLE 0x00000002
struct network_interface_info_ioctl_rsp {
__le32 Next; /* next interface. zero if this is last one */
__le32 IfIndex;
__le32 Capability; /* RSS or RDMA Capable */
__le32 Reserved;
__le64 LinkSpeed;
char SockAddr_Storage[128];
} __packed;
struct file_object_buf_type1_ioctl_rsp { struct file_object_buf_type1_ioctl_rsp {
__u8 ObjectId[16]; __u8 ObjectId[16];
__u8 BirthVolumeId[16]; __u8 BirthVolumeId[16];
@ -181,32 +111,6 @@ struct file_object_buf_type1_ioctl_rsp {
__u8 DomainId[16]; __u8 DomainId[16];
} __packed; } __packed;
struct resume_key_ioctl_rsp {
__u64 ResumeKey[3];
__le32 ContextLength;
__u8 Context[4]; /* ignored, Windows sets to 4 bytes of zero */
} __packed;
struct srv_copychunk {
__le64 SourceOffset;
__le64 TargetOffset;
__le32 Length;
__le32 Reserved;
} __packed;
struct copychunk_ioctl_req {
__le64 ResumeKey[3];
__le32 ChunkCount;
__le32 Reserved;
struct srv_copychunk Chunks[] __counted_by_le(ChunkCount);
} __packed;
struct copychunk_ioctl_rsp {
__le32 ChunksWritten;
__le32 ChunkBytesWritten;
__le32 TotalBytesWritten;
} __packed;
struct file_sparse { struct file_sparse {
__u8 SetSparse; __u8 SetSparse;
} __packed; } __packed;
@ -301,17 +205,6 @@ struct smb2_file_stream_info {
char StreamName[]; char StreamName[];
} __packed; } __packed;
struct smb2_file_ntwrk_info {
__le64 CreationTime;
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le64 AllocationSize;
__le64 EndOfFile;
__le32 Attributes;
__le32 Reserved;
} __packed;
struct smb2_file_standard_info { struct smb2_file_standard_info {
__le64 AllocationSize; __le64 AllocationSize;
__le64 EndOfFile; __le64 EndOfFile;

View File

@ -10,8 +10,9 @@
#include "glob.h" #include "glob.h"
#include "nterr.h" #include "nterr.h"
#include "../common/cifsglob.h" #include "../common/smbglob.h"
#include "../common/smb2pdu.h" #include "../common/smb2pdu.h"
#include "../common/fscc.h"
#include "smb2pdu.h" #include "smb2pdu.h"
/* ksmbd's Specific ERRNO */ /* ksmbd's Specific ERRNO */
@ -29,8 +30,6 @@
#define SMB_ECHO_INTERVAL (60 * HZ) #define SMB_ECHO_INTERVAL (60 * HZ)
#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
#define MAX_STREAM_PROT_LEN 0x00FFFFFF #define MAX_STREAM_PROT_LEN 0x00FFFFFF
/* Responses when opening a file. */ /* Responses when opening a file. */
@ -39,80 +38,7 @@
#define F_CREATED 2 #define F_CREATED 2
#define F_OVERWRITTEN 3 #define F_OVERWRITTEN 3
/* /* Combinations of file access permission bits */
* File Attribute flags
*/
#define ATTR_POSIX_SEMANTICS 0x01000000
#define ATTR_BACKUP_SEMANTICS 0x02000000
#define ATTR_DELETE_ON_CLOSE 0x04000000
#define ATTR_SEQUENTIAL_SCAN 0x08000000
#define ATTR_RANDOM_ACCESS 0x10000000
#define ATTR_NO_BUFFERING 0x20000000
#define ATTR_WRITE_THROUGH 0x80000000
/* List of FileSystemAttributes - see 2.5.1 of MS-FSCC */
#define FILE_SUPPORTS_SPARSE_VDL 0x10000000 /* faster nonsparse extend */
#define FILE_SUPPORTS_BLOCK_REFCOUNTING 0x08000000 /* allow ioctl dup extents */
#define FILE_SUPPORT_INTEGRITY_STREAMS 0x04000000
#define FILE_SUPPORTS_USN_JOURNAL 0x02000000
#define FILE_SUPPORTS_OPEN_BY_FILE_ID 0x01000000
#define FILE_SUPPORTS_EXTENDED_ATTRIBUTES 0x00800000
#define FILE_SUPPORTS_HARD_LINKS 0x00400000
#define FILE_SUPPORTS_TRANSACTIONS 0x00200000
#define FILE_SEQUENTIAL_WRITE_ONCE 0x00100000
#define FILE_READ_ONLY_VOLUME 0x00080000
#define FILE_NAMED_STREAMS 0x00040000
#define FILE_SUPPORTS_ENCRYPTION 0x00020000
#define FILE_SUPPORTS_OBJECT_IDS 0x00010000
#define FILE_VOLUME_IS_COMPRESSED 0x00008000
#define FILE_SUPPORTS_POSIX_UNLINK_RENAME 0x00000400
#define FILE_RETURNS_CLEANUP_RESULT_INFO 0x00000200
#define FILE_SUPPORTS_REMOTE_STORAGE 0x00000100
#define FILE_SUPPORTS_REPARSE_POINTS 0x00000080
#define FILE_SUPPORTS_SPARSE_FILES 0x00000040
#define FILE_VOLUME_QUOTAS 0x00000020
#define FILE_FILE_COMPRESSION 0x00000010
#define FILE_PERSISTENT_ACLS 0x00000008
#define FILE_UNICODE_ON_DISK 0x00000004
#define FILE_CASE_PRESERVED_NAMES 0x00000002
#define FILE_CASE_SENSITIVE_SEARCH 0x00000001
#define FILE_READ_DATA 0x00000001 /* Data can be read from the file */
#define FILE_WRITE_DATA 0x00000002 /* Data can be written to the file */
#define FILE_APPEND_DATA 0x00000004 /* Data can be appended to the file */
#define FILE_READ_EA 0x00000008 /* Extended attributes associated */
/* with the file can be read */
#define FILE_WRITE_EA 0x00000010 /* Extended attributes associated */
/* with the file can be written */
#define FILE_EXECUTE 0x00000020 /*Data can be read into memory from */
/* the file using system paging I/O */
#define FILE_DELETE_CHILD 0x00000040
#define FILE_READ_ATTRIBUTES 0x00000080 /* Attributes associated with the */
/* file can be read */
#define FILE_WRITE_ATTRIBUTES 0x00000100 /* Attributes associated with the */
/* file can be written */
#define DELETE 0x00010000 /* The file can be deleted */
#define READ_CONTROL 0x00020000 /* The access control list and */
/* ownership associated with the */
/* file can be read */
#define WRITE_DAC 0x00040000 /* The access control list and */
/* ownership associated with the */
/* file can be written. */
#define WRITE_OWNER 0x00080000 /* Ownership information associated */
/* with the file can be written */
#define SYNCHRONIZE 0x00100000 /* The file handle can waited on to */
/* synchronize with the completion */
/* of an input/output request */
#define GENERIC_ALL 0x10000000
#define GENERIC_EXECUTE 0x20000000
#define GENERIC_WRITE 0x40000000
#define GENERIC_READ 0x80000000
/* In summary - Relevant file */
/* access flags from CIFS are */
/* file_read_data, file_write_data */
/* file_execute, file_read_attributes*/
/* write_dac, and delete. */
#define SET_FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA \ #define SET_FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA \
| FILE_READ_ATTRIBUTES \ | FILE_READ_ATTRIBUTES \
| DELETE | READ_CONTROL | WRITE_DAC \ | DELETE | READ_CONTROL | WRITE_DAC \
@ -123,14 +49,6 @@
| FILE_WRITE_ATTRIBUTES \ | FILE_WRITE_ATTRIBUTES \
| DELETE | READ_CONTROL | WRITE_DAC \ | DELETE | READ_CONTROL | WRITE_DAC \
| WRITE_OWNER | SYNCHRONIZE) | WRITE_OWNER | SYNCHRONIZE)
#define SET_FILE_EXEC_RIGHTS (FILE_READ_EA | FILE_WRITE_EA | FILE_EXECUTE \
| FILE_READ_ATTRIBUTES \
| FILE_WRITE_ATTRIBUTES \
| DELETE | READ_CONTROL | WRITE_DAC \
| WRITE_OWNER | SYNCHRONIZE)
#define SET_MINIMUM_RIGHTS (FILE_READ_EA | FILE_READ_ATTRIBUTES \
| READ_CONTROL | SYNCHRONIZE)
/* generic flags for file open */ /* generic flags for file open */
#define GENERIC_READ_FLAGS (READ_CONTROL | FILE_READ_DATA | \ #define GENERIC_READ_FLAGS (READ_CONTROL | FILE_READ_DATA | \
@ -151,71 +69,27 @@
FILE_EXECUTE | FILE_DELETE_CHILD | \ FILE_EXECUTE | FILE_DELETE_CHILD | \
FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES) FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)
#define SMB1_PROTO_NUMBER cpu_to_le32(0x424d53ff) #define SMB_COM_NEGOTIATE 0x72 /* See MS-CIFS 2.2.2.1 */
#define SMB_COM_NEGOTIATE 0x72
#define SMB1_CLIENT_GUID_SIZE (16)
/* See MS-CIFS 2.2.3.1 */
#define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */ #define SMBFLG_RESPONSE 0x80 /* this PDU is a response from server */
/*
* See MS-CIFS 2.2.3.1
* MS-SMB 2.2.3.1
*/
#define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40) #define SMBFLG2_IS_LONG_NAME cpu_to_le16(0x40)
#define SMBFLG2_EXT_SEC cpu_to_le16(0x800) #define SMBFLG2_EXT_SEC cpu_to_le16(0x800)
#define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000) #define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000)
#define SMBFLG2_UNICODE cpu_to_le16(0x8000) #define SMBFLG2_UNICODE cpu_to_le16(0x8000)
struct smb_hdr { /* See MS-CIFS 2.2.4.52.2 */
__be32 smb_buf_length;
__u8 Protocol[4];
__u8 Command;
union {
struct {
__u8 ErrorClass;
__u8 Reserved;
__le16 Error;
} __packed DosError;
__le32 CifsError;
} __packed Status;
__u8 Flags;
__le16 Flags2; /* note: le */
__le16 PidHigh;
union {
struct {
__le32 SequenceNumber; /* le */
__u32 Reserved; /* zero */
} __packed Sequence;
__u8 SecuritySignature[8]; /* le */
} __packed Signature;
__u8 pad[2];
__le16 Tid;
__le16 Pid;
__le16 Uid;
__le16 Mid;
__u8 WordCount;
} __packed;
struct smb_negotiate_req {
struct smb_hdr hdr; /* wct = 0 */
__le16 ByteCount;
unsigned char DialectsArray[];
} __packed;
struct smb_negotiate_rsp { struct smb_negotiate_rsp {
struct smb_hdr hdr; /* wct = 17 */ struct smb_hdr hdr; /* wct = 17 */
__le16 DialectIndex; /* 0xFFFF = no dialect acceptable */ __le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
__le16 ByteCount; __le16 ByteCount;
} __packed; } __packed;
struct filesystem_attribute_info {
__le32 Attributes;
__le32 MaxPathNameComponentLength;
__le32 FileSystemNameLen;
__le16 FileSystemName[]; /* do not have to save this - get subset? */
} __packed;
struct filesystem_device_info {
__le32 DeviceType;
__le32 DeviceCharacteristics;
} __packed; /* device info level 0x104 */
struct filesystem_vol_info { struct filesystem_vol_info {
__le64 VolumeCreationTime; __le64 VolumeCreationTime;
__le32 SerialNumber; __le32 SerialNumber;
@ -224,13 +98,6 @@ struct filesystem_vol_info {
__le16 VolumeLabel[]; __le16 VolumeLabel[];
} __packed; } __packed;
struct filesystem_info {
__le64 TotalAllocationUnits;
__le64 FreeAllocationUnits;
__le32 SectorsPerAllocationUnit;
__le32 BytesPerSector;
} __packed; /* size info, level 0x103 */
#define EXTENDED_INFO_MAGIC 0x43667364 /* Cfsd */ #define EXTENDED_INFO_MAGIC 0x43667364 /* Cfsd */
#define STRING_LENGTH 28 #define STRING_LENGTH 28
@ -247,20 +114,6 @@ struct object_id_info {
struct fs_extended_info extended_info; struct fs_extended_info extended_info;
} __packed; } __packed;
struct file_directory_info {
__le32 NextEntryOffset;
__u32 FileIndex;
__le64 CreationTime;
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le64 EndOfFile;
__le64 AllocationSize;
__le32 ExtFileAttributes;
__le32 FileNameLength;
char FileName[];
} __packed; /* level 0x101 FF resp data */
struct file_names_info { struct file_names_info {
__le32 NextEntryOffset; __le32 NextEntryOffset;
__u32 FileIndex; __u32 FileIndex;
@ -268,39 +121,6 @@ struct file_names_info {
char FileName[]; char FileName[];
} __packed; /* level 0xc FF resp data */ } __packed; /* level 0xc FF resp data */
struct file_full_directory_info {
__le32 NextEntryOffset;
__u32 FileIndex;
__le64 CreationTime;
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le64 EndOfFile;
__le64 AllocationSize;
__le32 ExtFileAttributes;
__le32 FileNameLength;
__le32 EaSize;
char FileName[];
} __packed; /* level 0x102 FF resp */
struct file_both_directory_info {
__le32 NextEntryOffset;
__u32 FileIndex;
__le64 CreationTime;
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le64 EndOfFile;
__le64 AllocationSize;
__le32 ExtFileAttributes;
__le32 FileNameLength;
__le32 EaSize; /* length of the xattrs */
__u8 ShortNameLength;
__u8 Reserved;
__u8 ShortName[24];
char FileName[];
} __packed; /* level 0x104 FFrsp data */
struct file_id_both_directory_info { struct file_id_both_directory_info {
__le32 NextEntryOffset; __le32 NextEntryOffset;
__u32 FileIndex; __u32 FileIndex;
@ -321,75 +141,6 @@ struct file_id_both_directory_info {
char FileName[]; char FileName[];
} __packed; } __packed;
struct file_id_full_dir_info {
__le32 NextEntryOffset;
__u32 FileIndex;
__le64 CreationTime;
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le64 EndOfFile;
__le64 AllocationSize;
__le32 ExtFileAttributes;
__le32 FileNameLength;
__le32 EaSize; /* EA size */
__le32 Reserved;
__le64 UniqueId; /* inode num - le since Samba puts ino in low 32 bit*/
char FileName[];
} __packed; /* level 0x105 FF rsp data */
struct smb_version_values {
char *version_string;
__u16 protocol_id;
__le16 lock_cmd;
__u32 capabilities;
__u32 max_read_size;
__u32 max_write_size;
__u32 max_trans_size;
__u32 max_credits;
__u32 large_lock_type;
__u32 exclusive_lock_type;
__u32 shared_lock_type;
__u32 unlock_lock_type;
size_t header_size;
size_t max_header_size;
size_t read_rsp_size;
unsigned int cap_unix;
unsigned int cap_nt_find;
unsigned int cap_large_files;
__u16 signing_enabled;
__u16 signing_required;
size_t create_lease_size;
size_t create_durable_size;
size_t create_durable_v2_size;
size_t create_mxac_size;
size_t create_disk_id_size;
size_t create_posix_size;
};
struct filesystem_posix_info {
/* For undefined recommended transfer size return -1 in that field */
__le32 OptimalTransferSize; /* bsize on some os, iosize on other os */
__le32 BlockSize;
/* The next three fields are in terms of the block size.
* (above). If block size is unknown, 4096 would be a
* reasonable block size for a server to report.
* Note that returning the blocks/blocksavail removes need
* to make a second call (to QFSInfo level 0x103 to get this info.
* UserBlockAvail is typically less than or equal to BlocksAvail,
* if no distinction is made return the same value in each
*/
__le64 TotalBlocks;
__le64 BlocksAvail; /* bfree */
__le64 UserBlocksAvail; /* bavail */
/* For undefined Node fields or FSID return -1 */
__le64 TotalFileNodes;
__le64 FreeFileNodes;
__le64 FileSysIdentifier; /* fsid */
/* NB Namelen comes from FILE_SYSTEM_ATTRIBUTE_INFO call */
/* NB flags can come from FILE_SYSTEM_DEVICE_INFO call */
} __packed;
struct smb_version_ops { struct smb_version_ops {
u16 (*get_cmd_val)(struct ksmbd_work *swork); u16 (*get_cmd_val)(struct ksmbd_work *swork);
int (*init_rsp_hdr)(struct ksmbd_work *swork); int (*init_rsp_hdr)(struct ksmbd_work *swork);
@ -402,7 +153,7 @@ struct smb_version_ops {
int (*check_sign_req)(struct ksmbd_work *work); int (*check_sign_req)(struct ksmbd_work *work);
void (*set_sign_rsp)(struct ksmbd_work *work); void (*set_sign_rsp)(struct ksmbd_work *work);
int (*generate_signingkey)(struct ksmbd_session *sess, struct ksmbd_conn *conn); int (*generate_signingkey)(struct ksmbd_session *sess, struct ksmbd_conn *conn);
int (*generate_encryptionkey)(struct ksmbd_conn *conn, struct ksmbd_session *sess); void (*generate_encryptionkey)(struct ksmbd_conn *conn, struct ksmbd_session *sess);
bool (*is_transform_hdr)(void *buf); bool (*is_transform_hdr)(void *buf);
int (*decrypt_req)(struct ksmbd_work *work); int (*decrypt_req)(struct ksmbd_work *work);
int (*encrypt_resp)(struct ksmbd_work *work); int (*encrypt_resp)(struct ksmbd_work *work);
@ -452,9 +203,4 @@ unsigned int ksmbd_server_side_copy_max_chunk_size(void);
unsigned int ksmbd_server_side_copy_max_total_size(void); unsigned int ksmbd_server_side_copy_max_total_size(void);
bool is_asterisk(char *p); bool is_asterisk(char *p);
__le32 smb_map_generic_desired_access(__le32 daccess); __le32 smb_map_generic_desired_access(__le32 daccess);
static inline unsigned int get_rfc1002_len(void *buf)
{
return be32_to_cpu(*((__be32 *)buf)) & 0xffffff;
}
#endif /* __SMB_COMMON_H__ */ #endif /* __SMB_COMMON_H__ */

View File

@ -553,12 +553,16 @@ static void *ipc_msg_send_request(struct ksmbd_ipc_msg *msg, unsigned int handle
up_write(&ipc_msg_table_lock); up_write(&ipc_msg_table_lock);
ret = ipc_msg_send(msg); ret = ipc_msg_send(msg);
if (ret) if (ret) {
down_write(&ipc_msg_table_lock);
goto out; goto out;
}
ret = wait_event_interruptible_timeout(entry.wait, ret = wait_event_interruptible_timeout(entry.wait,
entry.response != NULL, entry.response != NULL,
IPC_WAIT_TIMEOUT); IPC_WAIT_TIMEOUT);
down_write(&ipc_msg_table_lock);
if (entry.response) { if (entry.response) {
ret = ipc_validate_msg(&entry); ret = ipc_validate_msg(&entry);
if (ret) { if (ret) {
@ -567,7 +571,6 @@ static void *ipc_msg_send_request(struct ksmbd_ipc_msg *msg, unsigned int handle
} }
} }
out: out:
down_write(&ipc_msg_table_lock);
hash_del(&entry.ipc_table_hlist); hash_del(&entry.ipc_table_hlist);
up_write(&ipc_msg_table_lock); up_write(&ipc_msg_table_lock);
return entry.response; return entry.response;

View File

@ -19,6 +19,8 @@
#include <rdma/rdma_cm.h> #include <rdma/rdma_cm.h>
#include <rdma/rw.h> #include <rdma/rw.h>
#define __SMBDIRECT_SOCKET_DISCONNECT(__sc) smb_direct_disconnect_rdma_connection(__sc)
#include "glob.h" #include "glob.h"
#include "connection.h" #include "connection.h"
#include "smb_common.h" #include "smb_common.h"
@ -231,6 +233,9 @@ static void smb_direct_disconnect_rdma_work(struct work_struct *work)
struct smbdirect_socket *sc = struct smbdirect_socket *sc =
container_of(work, struct smbdirect_socket, disconnect_work); container_of(work, struct smbdirect_socket, disconnect_work);
if (sc->first_error == 0)
sc->first_error = -ECONNABORTED;
/* /*
* make sure this and other work is not queued again * make sure this and other work is not queued again
* but here we don't block and avoid * but here we don't block and avoid
@ -241,9 +246,6 @@ static void smb_direct_disconnect_rdma_work(struct work_struct *work)
disable_delayed_work(&sc->idle.timer_work); disable_delayed_work(&sc->idle.timer_work);
disable_work(&sc->idle.immediate_work); disable_work(&sc->idle.immediate_work);
if (sc->first_error == 0)
sc->first_error = -ECONNABORTED;
switch (sc->status) { switch (sc->status) {
case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED: case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED:
case SMBDIRECT_SOCKET_NEGOTIATE_RUNNING: case SMBDIRECT_SOCKET_NEGOTIATE_RUNNING:
@ -287,6 +289,9 @@ static void smb_direct_disconnect_rdma_work(struct work_struct *work)
static void static void
smb_direct_disconnect_rdma_connection(struct smbdirect_socket *sc) smb_direct_disconnect_rdma_connection(struct smbdirect_socket *sc)
{ {
if (sc->first_error == 0)
sc->first_error = -ECONNABORTED;
/* /*
* make sure other work (than disconnect_work) is * make sure other work (than disconnect_work) is
* not queued again but here we don't block and avoid * not queued again but here we don't block and avoid
@ -296,9 +301,6 @@ smb_direct_disconnect_rdma_connection(struct smbdirect_socket *sc)
disable_work(&sc->idle.immediate_work); disable_work(&sc->idle.immediate_work);
disable_delayed_work(&sc->idle.timer_work); disable_delayed_work(&sc->idle.timer_work);
if (sc->first_error == 0)
sc->first_error = -ECONNABORTED;
switch (sc->status) { switch (sc->status) {
case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED: case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED:
case SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED: case SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED:
@ -639,7 +641,18 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
return; return;
} }
sc->recv_io.reassembly.full_packet_received = true; sc->recv_io.reassembly.full_packet_received = true;
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_NEGOTIATE_NEEDED); /*
* Some drivers (at least mlx5_ib) might post a
* recv completion before RDMA_CM_EVENT_ESTABLISHED,
* we need to adjust our expectation in that case.
*/
if (!sc->first_error && sc->status == SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING)
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED;
if (SMBDIRECT_CHECK_STATUS_WARN(sc, SMBDIRECT_SOCKET_NEGOTIATE_NEEDED)) {
put_recvmsg(sc, recvmsg);
smb_direct_disconnect_rdma_connection(sc);
return;
}
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING; sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING;
enqueue_reassembly(sc, recvmsg, 0); enqueue_reassembly(sc, recvmsg, 0);
wake_up(&sc->status_wait); wake_up(&sc->status_wait);
@ -1725,7 +1738,18 @@ static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
switch (event->event) { switch (event->event) {
case RDMA_CM_EVENT_ESTABLISHED: { case RDMA_CM_EVENT_ESTABLISHED: {
WARN_ON_ONCE(sc->status != SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING); /*
* Some drivers (at least mlx5_ib) might post a
* recv completion before RDMA_CM_EVENT_ESTABLISHED,
* we need to adjust our expectation in that case.
*
* As we already started the negotiation, we just
* ignore RDMA_CM_EVENT_ESTABLISHED here.
*/
if (!sc->first_error && sc->status > SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING)
break;
if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING))
break;
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED; sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED;
wake_up(&sc->status_wait); wake_up(&sc->status_wait);
break; break;

View File

@ -22,7 +22,6 @@ struct interface {
struct socket *ksmbd_socket; struct socket *ksmbd_socket;
struct list_head entry; struct list_head entry;
char *name; char *name;
struct mutex sock_release_lock;
int state; int state;
}; };
@ -56,19 +55,6 @@ static inline void ksmbd_tcp_reuseaddr(struct socket *sock)
sock_set_reuseaddr(sock->sk); sock_set_reuseaddr(sock->sk);
} }
static inline void ksmbd_tcp_rcv_timeout(struct socket *sock, s64 secs)
{
if (secs && secs < MAX_SCHEDULE_TIMEOUT / HZ - 1)
WRITE_ONCE(sock->sk->sk_rcvtimeo, secs * HZ);
else
WRITE_ONCE(sock->sk->sk_rcvtimeo, MAX_SCHEDULE_TIMEOUT);
}
static inline void ksmbd_tcp_snd_timeout(struct socket *sock, s64 secs)
{
sock_set_sndtimeo(sock->sk, secs);
}
static struct tcp_transport *alloc_transport(struct socket *client_sk) static struct tcp_transport *alloc_transport(struct socket *client_sk)
{ {
struct tcp_transport *t; struct tcp_transport *t;
@ -236,20 +222,14 @@ static int ksmbd_kthread_fn(void *p)
unsigned int max_ip_conns; unsigned int max_ip_conns;
while (!kthread_should_stop()) { while (!kthread_should_stop()) {
mutex_lock(&iface->sock_release_lock);
if (!iface->ksmbd_socket) { if (!iface->ksmbd_socket) {
mutex_unlock(&iface->sock_release_lock);
break; break;
} }
ret = kernel_accept(iface->ksmbd_socket, &client_sk, ret = kernel_accept(iface->ksmbd_socket, &client_sk, 0);
SOCK_NONBLOCK); if (ret == -EINVAL)
mutex_unlock(&iface->sock_release_lock); break;
if (ret) { if (ret)
if (ret == -EAGAIN)
/* check for new connections every 100 msecs */
schedule_timeout_interruptible(HZ / 10);
continue; continue;
}
if (!server_conf.max_ip_connections) if (!server_conf.max_ip_connections)
goto skip_max_ip_conns_limit; goto skip_max_ip_conns_limit;
@ -458,10 +438,6 @@ static void tcp_destroy_socket(struct socket *ksmbd_socket)
if (!ksmbd_socket) if (!ksmbd_socket)
return; return;
/* set zero to timeout */
ksmbd_tcp_rcv_timeout(ksmbd_socket, 0);
ksmbd_tcp_snd_timeout(ksmbd_socket, 0);
ret = kernel_sock_shutdown(ksmbd_socket, SHUT_RDWR); ret = kernel_sock_shutdown(ksmbd_socket, SHUT_RDWR);
if (ret) if (ret)
pr_err("Failed to shutdown socket: %d\n", ret); pr_err("Failed to shutdown socket: %d\n", ret);
@ -532,9 +508,6 @@ static int create_socket(struct interface *iface)
goto out_error; goto out_error;
} }
ksmbd_socket->sk->sk_rcvtimeo = KSMBD_TCP_RECV_TIMEOUT;
ksmbd_socket->sk->sk_sndtimeo = KSMBD_TCP_SEND_TIMEOUT;
ret = kernel_listen(ksmbd_socket, KSMBD_SOCKET_BACKLOG); ret = kernel_listen(ksmbd_socket, KSMBD_SOCKET_BACKLOG);
if (ret) { if (ret) {
pr_err("Port listen() error: %d\n", ret); pr_err("Port listen() error: %d\n", ret);
@ -604,12 +577,11 @@ static int ksmbd_netdev_event(struct notifier_block *nb, unsigned long event,
if (iface && iface->state == IFACE_STATE_CONFIGURED) { if (iface && iface->state == IFACE_STATE_CONFIGURED) {
ksmbd_debug(CONN, "netdev-down event: netdev(%s) is going down\n", ksmbd_debug(CONN, "netdev-down event: netdev(%s) is going down\n",
iface->name); iface->name);
kernel_sock_shutdown(iface->ksmbd_socket, SHUT_RDWR);
tcp_stop_kthread(iface->ksmbd_kthread); tcp_stop_kthread(iface->ksmbd_kthread);
iface->ksmbd_kthread = NULL; iface->ksmbd_kthread = NULL;
mutex_lock(&iface->sock_release_lock); sock_release(iface->ksmbd_socket);
tcp_destroy_socket(iface->ksmbd_socket);
iface->ksmbd_socket = NULL; iface->ksmbd_socket = NULL;
mutex_unlock(&iface->sock_release_lock);
iface->state = IFACE_STATE_DOWN; iface->state = IFACE_STATE_DOWN;
break; break;
@ -672,7 +644,6 @@ static struct interface *alloc_iface(char *ifname)
iface->name = ifname; iface->name = ifname;
iface->state = IFACE_STATE_DOWN; iface->state = IFACE_STATE_DOWN;
list_add(&iface->entry, &iface_list); list_add(&iface->entry, &iface_list);
mutex_init(&iface->sock_release_lock);
return iface; return iface;
} }

View File

@ -303,6 +303,9 @@ static int check_lock_range(struct file *filp, loff_t start, loff_t end,
struct file_lock_context *ctx = locks_inode_context(file_inode(filp)); struct file_lock_context *ctx = locks_inode_context(file_inode(filp));
int error = 0; int error = 0;
if (start == end)
return 0;
if (!ctx || list_empty_careful(&ctx->flc_posix)) if (!ctx || list_empty_careful(&ctx->flc_posix))
return 0; return 0;
@ -767,7 +770,7 @@ int ksmbd_vfs_truncate(struct ksmbd_work *work,
if (size < inode->i_size) { if (size < inode->i_size) {
err = check_lock_range(filp, size, err = check_lock_range(filp, size,
inode->i_size - 1, WRITE); inode->i_size - 1, WRITE);
} else { } else if (size > inode->i_size) {
err = check_lock_range(filp, inode->i_size, err = check_lock_range(filp, inode->i_size,
size - 1, WRITE); size - 1, WRITE);
} }
@ -1591,7 +1594,7 @@ int ksmbd_vfs_get_dos_attrib_xattr(struct mnt_idmap *idmap,
*/ */
void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat) void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat)
{ {
struct file_directory_info *info = (struct file_directory_info *)(*p); FILE_DIRECTORY_INFO *info = (FILE_DIRECTORY_INFO *)(*p);
struct kstat *kstat = ksmbd_kstat->kstat; struct kstat *kstat = ksmbd_kstat->kstat;
u64 time; u64 time;

View File

@ -112,40 +112,62 @@ int ksmbd_query_inode_status(struct dentry *dentry)
read_lock(&inode_hash_lock); read_lock(&inode_hash_lock);
ci = __ksmbd_inode_lookup(dentry); ci = __ksmbd_inode_lookup(dentry);
if (ci) {
ret = KSMBD_INODE_STATUS_OK;
if (ci->m_flags & (S_DEL_PENDING | S_DEL_ON_CLS))
ret = KSMBD_INODE_STATUS_PENDING_DELETE;
atomic_dec(&ci->m_count);
}
read_unlock(&inode_hash_lock); read_unlock(&inode_hash_lock);
if (!ci)
return ret;
down_read(&ci->m_lock);
if (ci->m_flags & (S_DEL_PENDING | S_DEL_ON_CLS))
ret = KSMBD_INODE_STATUS_PENDING_DELETE;
else
ret = KSMBD_INODE_STATUS_OK;
up_read(&ci->m_lock);
atomic_dec(&ci->m_count);
return ret; return ret;
} }
bool ksmbd_inode_pending_delete(struct ksmbd_file *fp) bool ksmbd_inode_pending_delete(struct ksmbd_file *fp)
{ {
return (fp->f_ci->m_flags & (S_DEL_PENDING | S_DEL_ON_CLS)); struct ksmbd_inode *ci = fp->f_ci;
int ret;
down_read(&ci->m_lock);
ret = (ci->m_flags & (S_DEL_PENDING | S_DEL_ON_CLS));
up_read(&ci->m_lock);
return ret;
} }
void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp) void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp)
{ {
fp->f_ci->m_flags |= S_DEL_PENDING; struct ksmbd_inode *ci = fp->f_ci;
down_write(&ci->m_lock);
ci->m_flags |= S_DEL_PENDING;
up_write(&ci->m_lock);
} }
void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp) void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp)
{ {
fp->f_ci->m_flags &= ~S_DEL_PENDING; struct ksmbd_inode *ci = fp->f_ci;
down_write(&ci->m_lock);
ci->m_flags &= ~S_DEL_PENDING;
up_write(&ci->m_lock);
} }
void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp, void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp,
int file_info) int file_info)
{ {
if (ksmbd_stream_fd(fp)) { struct ksmbd_inode *ci = fp->f_ci;
fp->f_ci->m_flags |= S_DEL_ON_CLS_STREAM;
return;
}
fp->f_ci->m_flags |= S_DEL_ON_CLS; down_write(&ci->m_lock);
if (ksmbd_stream_fd(fp))
ci->m_flags |= S_DEL_ON_CLS_STREAM;
else
ci->m_flags |= S_DEL_ON_CLS;
up_write(&ci->m_lock);
} }
static void ksmbd_inode_hash(struct ksmbd_inode *ci) static void ksmbd_inode_hash(struct ksmbd_inode *ci)
@ -257,27 +279,41 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
struct file *filp; struct file *filp;
filp = fp->filp; filp = fp->filp;
if (ksmbd_stream_fd(fp) && (ci->m_flags & S_DEL_ON_CLS_STREAM)) {
ci->m_flags &= ~S_DEL_ON_CLS_STREAM; if (ksmbd_stream_fd(fp)) {
err = ksmbd_vfs_remove_xattr(file_mnt_idmap(filp), bool remove_stream_xattr = false;
&filp->f_path,
fp->stream.name, down_write(&ci->m_lock);
true); if (ci->m_flags & S_DEL_ON_CLS_STREAM) {
if (err) ci->m_flags &= ~S_DEL_ON_CLS_STREAM;
pr_err("remove xattr failed : %s\n", remove_stream_xattr = true;
fp->stream.name); }
up_write(&ci->m_lock);
if (remove_stream_xattr) {
err = ksmbd_vfs_remove_xattr(file_mnt_idmap(filp),
&filp->f_path,
fp->stream.name,
true);
if (err)
pr_err("remove xattr failed : %s\n",
fp->stream.name);
}
} }
if (atomic_dec_and_test(&ci->m_count)) { if (atomic_dec_and_test(&ci->m_count)) {
bool do_unlink = false;
down_write(&ci->m_lock); down_write(&ci->m_lock);
if (ci->m_flags & (S_DEL_ON_CLS | S_DEL_PENDING)) { if (ci->m_flags & (S_DEL_ON_CLS | S_DEL_PENDING)) {
ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING); ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING);
up_write(&ci->m_lock); do_unlink = true;
ksmbd_vfs_unlink(filp);
down_write(&ci->m_lock);
} }
up_write(&ci->m_lock); up_write(&ci->m_lock);
if (do_unlink)
ksmbd_vfs_unlink(filp);
ksmbd_inode_free(ci); ksmbd_inode_free(ci);
} }
} }