mirror of https://github.com/torvalds/linux.git
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:
commit
869737543b
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 */
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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__ */
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue