Forty four smb client and server changesets

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

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

Pull smb client and server updates from Steve French:

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

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

  - smbdirect (RDMA) fixes

  - client debugging improvements for leases

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

View File

@ -249,9 +249,9 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
seq_puts(m, "# Format:\n");
seq_puts(m, "# <tree id> <ses id> <persistent fid> <flags> <count> <pid> <uid>");
#ifdef CONFIG_CIFS_DEBUG2
seq_puts(m, " <filename> <lease> <mid>\n");
seq_puts(m, " <filename> <lease> <lease-key> <mid>\n");
#else
seq_puts(m, " <filename> <lease>\n");
seq_puts(m, " <filename> <lease> <lease-key>\n");
#endif /* CIFS_DEBUG2 */
spin_lock(&cifs_tcp_ses_lock);
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 */
inode = d_inode(cfile->dentry);
cinode = NULL;
n = 0;
if (inode) {
cinode = CIFS_I(inode);
@ -291,6 +292,12 @@ static int cifs_debug_files_proc_show(struct seq_file *m, void *v)
else
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
seq_printf(m, " %llu", cfile->fid.mid);
#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, "# 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);
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 long)atomic64_read(&cfids->total_dirents_bytes));
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,
ses->Suid,
cfid->fid.persistent_fid,
cfid->path);
cfid->fid.persistent_fid);
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)
seq_printf(m, "\tvalid file info");
if (cfid->dirents.is_valid)

View File

@ -24,8 +24,9 @@
#include "cifsacl.h"
#include <crypto/internal/hash.h>
#include <uapi/linux/cifs/cifs_mount.h>
#include "../common/cifsglob.h"
#include "../common/smbglob.h"
#include "../common/smb2pdu.h"
#include "../common/fscc.h"
#include "smb2pdu.h"
#include <linux/filelock.h>
@ -633,28 +634,6 @@ struct smb_version_operations {
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 MAX_HEADER_SIZE(server) (server->vals->max_header_size)
#define HEADER_PREAMBLE_SIZE(server) (server->vals->header_preamble_size)
@ -692,12 +671,6 @@ struct cifs_mnt_data {
int flags;
};
static inline unsigned int
get_rfc1002_length(void *buf)
{
return be32_to_cpu(*((__be32 *)buf)) & 0xffffff;
}
struct TCP_Server_Info {
struct list_head tcp_ses_list;
struct list_head smb_ses_list;

File diff suppressed because it is too large Load Diff

View File

@ -361,7 +361,7 @@ static int validate_t2(struct smb_t2_rsp *pSMB)
}
static int
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;
u16 count;
@ -419,8 +419,8 @@ CIFSSMBNegotiate(const unsigned int xid,
struct cifs_ses *ses,
struct TCP_Server_Info *server)
{
NEGOTIATE_REQ *pSMB;
NEGOTIATE_RSP *pSMBr;
SMB_NEGOTIATE_REQ *pSMB;
SMB_NEGOTIATE_RSP *pSMBr;
int rc = 0;
int bytes_returned;
int i;
@ -614,7 +614,7 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
iov[0].iov_len = 4;
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;
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_len = 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,
rdata->subreq.debug_index,
@ -1830,7 +1830,7 @@ cifs_async_writev(struct cifs_io_subrequest *wdata)
/* 4 for RFC1001 length + 1 for BCC */
iov[0].iov_len = 4;
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;
rqst.rq_iov = iov;
@ -4746,7 +4746,7 @@ CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
/* level 0x103 SMB_QUERY_FILE_SYSTEM_INFO */
TRANSACTION2_QFSI_REQ *pSMB = NULL;
TRANSACTION2_QFSI_RSP *pSMBr = NULL;
FILE_SYSTEM_INFO *response_data;
FILE_SYSTEM_SIZE_INFO *response_data;
int rc = 0;
int bytes_returned = 0;
__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);
response_data =
(FILE_SYSTEM_INFO
(FILE_SYSTEM_SIZE_INFO
*) (((char *) &pSMBr->hdr.Protocol) +
data_offset);
FSData->f_bsize =
@ -4811,7 +4811,7 @@ CIFSSMBQFSInfo(const unsigned int xid, struct cifs_tcon *tcon,
FSData->f_blocks =
le64_to_cpu(response_data->TotalAllocationUnits);
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",
(unsigned long long)FSData->f_blocks,
(unsigned long long)FSData->f_bfree,

View File

@ -165,7 +165,7 @@ SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses,
int resp_buf_type;
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;
rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov);
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,
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));
@ -370,7 +370,7 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses,
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);
rc = cifs_check_receive(midQ, server, 0);
out:
@ -554,7 +554,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon,
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);
rc = cifs_check_receive(midQ, server, 0);
out:

View File

@ -1295,7 +1295,7 @@ cifs_demultiplex_thread(void *p)
* The right amount was read from socket - 4 bytes,
* 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);
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 */
static inline int
cifs_set_cifscreds(struct smb3_fs_context *ctx __attribute__((unused)),
struct cifs_ses *ses __attribute__((unused)))
cifs_set_cifscreds(struct smb3_fs_context *ctx __maybe_unused,
struct cifs_ses *ses __maybe_unused)
{
return -ENOSYS;
}

View File

@ -1329,7 +1329,7 @@ static int cifs_get_fattr(struct cifs_open_info_data *data,
/* for easier reading */
FILE_ALL_INFO *fi;
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,
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);
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);
fattr->cf_uniqueid = le64_to_cpu(si->UniqueId);

View File

@ -318,7 +318,7 @@ static int
check_smb_hdr(struct smb_hdr *smb)
{
/* 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",
*(unsigned int *)smb->Protocol);
return 1;

View File

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

View File

@ -98,7 +98,7 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
default:
break;
}
} else if (fattr->cf_cifsattrs & ATTR_REPARSE) {
} else if (fattr->cf_cifsattrs & ATTR_REPARSE_POINT) {
reparse_need_reval = true;
}
@ -138,7 +138,7 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
* reparse tag and ctime haven't changed.
*/
rc = 0;
if (fattr->cf_cifsattrs & ATTR_REPARSE) {
if (fattr->cf_cifsattrs & ATTR_REPARSE_POINT) {
if (likely(reparse_inode_match(inode, fattr))) {
fattr->cf_mode = inode->i_mode;
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
* 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))
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_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);
/* 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);
/* 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);
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,
const SEARCH_ID_FULL_DIR_INFO *info)
const FILE_ID_FULL_DIR_INFO *info)
{
de->name = &info->FileName[0];
de->namelen = le32_to_cpu(info->FileNameLength);

View File

@ -93,7 +93,7 @@ static inline bool reparse_inode_match(struct inode *inode,
if (cinode->reparse_tag != IO_REPARSE_TAG_INTERNAL &&
cinode->reparse_tag != fattr->cf_cifstag)
return false;
return (cinode->cifsAttrs & ATTR_REPARSE) &&
return (cinode->cifsAttrs & ATTR_REPARSE_POINT) &&
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);
if (data->reparse_point) {
attrs |= ATTR_REPARSE;
attrs |= ATTR_REPARSE_POINT;
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);
if (data->reparse_point) {
attrs |= ATTR_REPARSE;
attrs |= ATTR_REPARSE_POINT;
fi->Attributes = cpu_to_le32(attrs);
}
}
ret = attrs & ATTR_REPARSE;
ret = attrs & ATTR_REPARSE_POINT;
return ret;
}

View File

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

View File

@ -648,7 +648,7 @@ static int cifs_query_path_info(const unsigned int xid,
if (!rc) {
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

View File

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

View File

@ -624,8 +624,8 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
struct network_interface_info_ioctl_rsp *p;
struct sockaddr_in *addr4;
struct sockaddr_in6 *addr6;
struct iface_info_ipv4 *p4;
struct iface_info_ipv6 *p6;
struct smb_sockaddr_in *p4;
struct smb_sockaddr_in6 *p6;
struct cifs_server_iface *info = NULL, *iface = NULL, *niface = NULL;
struct cifs_server_iface tmp_iface;
ssize_t bytes_left;
@ -685,7 +685,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
*/
case INTERNETWORK:
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;
memcpy(&addr4->sin_addr, &p4->IPv4Address, 4);
@ -697,7 +697,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
break;
case INTERNETWORKV6:
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;
memcpy(&addr6->sin6_addr, &p6->IPv6Address, 16);
@ -1524,11 +1524,11 @@ smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon,
static int
SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid,
struct copychunk_ioctl *pcchunk)
struct copychunk_ioctl_req *pcchunk)
{
int rc;
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,
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);
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");
rc = -EINVAL;
goto req_res_key_exit;
@ -1857,10 +1857,10 @@ smb2_copychunk_range(const unsigned int xid,
{
int rc = 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 cifs_tcon *tcon;
struct copychunk *chunk;
struct srv_copychunk *chunk;
u32 chunks, chunk_count, chunk_bytes;
u32 copy_bytes, copy_bytes_left;
u32 chunks_written, bytes_written;
@ -4484,61 +4484,6 @@ crypt_message(struct TCP_Server_Info *server, int num_rqst,
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.
*/
@ -4564,7 +4509,7 @@ void
smb3_free_compound_rqst(int num_rqst, struct smb_rqst *rqst)
{
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;
if (size > 0) {
buffer = cifs_alloc_folioq_buffer(size);
if (!buffer)
size_t cur_size = 0;
rc = netfs_alloc_folioq_buffer(NULL, &buffer, &cur_size,
size, GFP_NOFS);
if (rc < 0)
goto err_free;
new->rq_buffer = buffer;
@ -4932,7 +4879,7 @@ static void smb2_decrypt_offload(struct work_struct *work)
}
free_pages:
cifs_clear_folioq_buffer(dw->buffer);
netfs_free_folioq_buffer(dw->buffer);
cifs_small_buf_release(dw->buf);
kfree(dw);
}
@ -4970,9 +4917,9 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid,
dw->len = len;
len = round_up(dw->len, PAGE_SIZE);
rc = -ENOMEM;
dw->buffer = cifs_alloc_folioq_buffer(len);
if (!dw->buffer)
size_t cur_size = 0;
rc = netfs_alloc_folioq_buffer(NULL, &dw->buffer, &cur_size, len, GFP_NOFS);
if (rc < 0)
goto discard_data;
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:
cifs_clear_folioq_buffer(dw->buffer);
netfs_free_folioq_buffer(dw->buffer);
free_dw:
kfree(dw);
return rc;

View File

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

View File

@ -133,46 +133,6 @@ struct share_redirect_error_context_rsp {
#define SMB2_LEASE_HANDLE_CACHING_HE 0x02
#define SMB2_LEASE_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 */
struct crt_twarp_ctxt {
struct create_context_hdr ccontext;
@ -193,36 +153,6 @@ struct crt_sd_ctxt {
struct smb3_sd sd;
} __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 */
struct get_retrieval_pointer_count_req {
__le64 StartingVcn; /* virtual cluster number (signed) */
@ -263,35 +193,6 @@ struct network_resiliency_req {
} __packed;
/* 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 */
struct compress_ioctl {
@ -323,19 +224,6 @@ struct smb2_file_reparse_point_info {
__le32 Tag;
} __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 */
struct smb2_file_id_information {
__le64 VolumeSerialNumber;

View File

@ -7,6 +7,7 @@
#include <linux/module.h>
#include <linux/highmem.h>
#include <linux/folio_queue.h>
#define __SMBDIRECT_SOCKET_DISCONNECT(__sc) smbd_disconnect_rdma_connection(__sc)
#include "../common/smbdirect/smbdirect_pdu.h"
#include "smbdirect.h"
#include "cifs_debug.h"
@ -186,6 +187,9 @@ static void smbd_disconnect_rdma_work(struct work_struct *work)
struct smbdirect_socket *sc =
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
* 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_delayed_work(&sc->idle.timer_work);
if (sc->first_error == 0)
sc->first_error = -ECONNABORTED;
switch (sc->status) {
case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED:
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)
{
if (sc->first_error == 0)
sc->first_error = -ECONNABORTED;
/*
* make sure other work (than disconnect_work) is
* 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_delayed_work(&sc->idle.timer_work);
if (sc->first_error == 0)
sc->first_error = -ECONNABORTED;
switch (sc->status) {
case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED:
case SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED:
@ -322,27 +323,27 @@ static int smbd_conn_upcall(
switch (event->event) {
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;
wake_up(&sc->status_wait);
break;
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;
wake_up(&sc->status_wait);
break;
case RDMA_CM_EVENT_ADDR_ERROR:
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;
smbd_disconnect_rdma_work(&sc->disconnect_work);
break;
case RDMA_CM_EVENT_ROUTE_ERROR:
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;
smbd_disconnect_rdma_work(&sc->disconnect_work);
break;
@ -428,7 +429,8 @@ static int smbd_conn_upcall(
min_t(u8, sp->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;
wake_up(&sc->status_wait);
break;
@ -437,7 +439,6 @@ static int smbd_conn_upcall(
case RDMA_CM_EVENT_UNREACHABLE:
case RDMA_CM_EVENT_REJECTED:
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;
smbd_disconnect_rdma_work(&sc->disconnect_work);
break;
@ -699,7 +700,8 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
negotiate_done =
process_negotiation_response(response, wc->byte_len);
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) {
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_FAILED;
smbd_disconnect_rdma_connection(sc);

View File

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

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

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

View File

@ -1149,12 +1149,6 @@ struct smb2_server_client_notification {
#define FILE_OVERWRITE_IF_LE cpu_to_le32(0x00000005)
#define FILE_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 */
#define FILE_DIRECTORY_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;
/* 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;
__u8 Name[8];
union {
@ -1281,7 +1275,7 @@ struct create_durable {
__u64 VolatileFileId;
} Fid;
} Data;
} __packed;
} __packed create_durable_req_t, create_durable_reconn_t;
/* See MS-SMB2 2.2.13.2.5 */
struct create_mxac_req {
@ -1290,6 +1284,56 @@ struct create_mxac_req {
__le64 Timestamp;
} __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 */
struct create_mxac_rsp {
struct create_context_hdr ccontext;
@ -1388,6 +1432,45 @@ struct smb2_ioctl_req {
__u8 Buffer[];
} __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_hdr hdr;
__le16 StructureSize; /* Must be 49 */
@ -1404,6 +1487,41 @@ struct smb2_ioctl_rsp {
__u8 Buffer[];
} __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 */
struct file_zero_data_information {
__le64 FileOffset;
@ -1893,6 +2011,151 @@ struct smb2_lease_ack {
__le64 LeaseDuration;
} __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_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 */

View File

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

View File

@ -74,6 +74,19 @@ const char *smbdirect_socket_status_string(enum smbdirect_socket_status status)
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 {
SMBDIRECT_KEEPALIVE_NONE,
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);
}
#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_socket *socket;
struct ib_cqe cqe;

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

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

View File

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

View File

@ -13,6 +13,8 @@
#include <linux/xattr.h>
#include <crypto/hash.h>
#include <crypto/aead.h>
#include <crypto/md5.h>
#include <crypto/sha2.h>
#include <linux/random.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);
}
/**
* 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,
char *ntlmv2_hash, char *dname)
{
int ret, len, conv_len;
wchar_t *domain = NULL;
__le16 *uniname = NULL;
struct ksmbd_crypto_ctx *ctx;
struct hmac_md5_ctx ctx;
ctx = ksmbd_crypto_ctx_find_hmacmd5();
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),
hmac_md5_init_usingrawkey(&ctx, user_passkey(sess->user),
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 */
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);
ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
(char *)uniname,
UNICODE_LEN(conv_len));
if (ret) {
ksmbd_debug(AUTH, "Could not update with user\n");
goto out;
}
hmac_md5_update(&ctx, (const u8 *)uniname, UNICODE_LEN(conv_len));
/* Convert domain name or conn name to unicode and uppercase */
len = strlen(dname);
@ -188,21 +115,12 @@ static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess,
goto out;
}
ret = crypto_shash_update(CRYPTO_HMACMD5(ctx),
(char *)domain,
UNICODE_LEN(conv_len));
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");
hmac_md5_update(&ctx, (const u8 *)domain, UNICODE_LEN(conv_len));
hmac_md5_final(&ctx, ntlmv2_hash);
ret = 0;
out:
kfree(uniname);
kfree(domain);
ksmbd_release_crypto_ctx(ctx);
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_rsp[CIFS_HMAC_MD5_HASH_SIZE];
struct ksmbd_crypto_ctx *ctx = NULL;
char *construct = NULL;
int rc, len;
struct hmac_md5_ctx ctx;
int rc;
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);
if (rc) {
ksmbd_debug(AUTH, "could not get v2 hash rc %d\n", rc);
goto out;
return rc;
}
ctx = ksmbd_crypto_ctx_find_hmacmd5();
if (!ctx) {
ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
return -ENOMEM;
}
hmac_md5_init_usingrawkey(&ctx, ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE);
hmac_md5_update(&ctx, cryptkey, CIFS_CRYPTO_KEY_SIZE);
hmac_md5_update(&ctx, (const u8 *)&ntlmv2->blob_signature, blen);
hmac_md5_final(&ctx, ntlmv2_rsp);
rc = crypto_shash_setkey(CRYPTO_HMACMD5_TFM(ctx),
ntlmv2_hash,
CIFS_HMAC_MD5_HASH_SIZE);
if (rc) {
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;
}
/* Generate the session key */
hmac_md5_usingrawkey(ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE,
ntlmv2_rsp, CIFS_HMAC_MD5_HASH_SIZE,
sess->sess_key);
if (memcmp(ntlmv2->ntlmv2_hash, ntlmv2_rsp, CIFS_HMAC_MD5_HASH_SIZE) != 0)
rc = -EINVAL;
out:
if (ctx)
ksmbd_release_crypto_ctx(ctx);
kfree(construct);
return rc;
return -EINVAL;
return 0;
}
/**
@ -589,46 +467,16 @@ int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
* @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)
{
struct ksmbd_crypto_ctx *ctx;
int rc, i;
struct hmac_sha256_ctx ctx;
int i;
ctx = ksmbd_crypto_ctx_find_hmacsha256();
if (!ctx) {
ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
return -ENOMEM;
}
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;
hmac_sha256_init_usingrawkey(&ctx, key, SMB2_NTLMV2_SESSKEY_SIZE);
for (i = 0; i < n_vec; i++)
hmac_sha256_update(&ctx, iov[i].iov_base, iov[i].iov_len);
hmac_sha256_final(&ctx, sig);
}
/**
@ -688,7 +536,7 @@ struct derivation {
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,
unsigned int key_size)
{
@ -696,90 +544,31 @@ static int generate_key(struct ksmbd_conn *conn, struct ksmbd_session *sess,
__u8 i[4] = {0, 0, 0, 1};
__u8 L128[4] = {0, 0, 0, 128};
__u8 L256[4] = {0, 0, 1, 0};
int rc;
unsigned char prfhash[SMB2_HMACSHA256_SIZE];
unsigned char *hashptr = prfhash;
struct ksmbd_crypto_ctx *ctx;
struct hmac_sha256_ctx ctx;
memset(prfhash, 0x0, SMB2_HMACSHA256_SIZE);
memset(key, 0x0, key_size);
ctx = ksmbd_crypto_ctx_find_hmacsha256();
if (!ctx) {
ksmbd_debug(AUTH, "could not crypto alloc hmacmd5\n");
return -ENOMEM;
}
rc = crypto_shash_setkey(CRYPTO_HMACSHA256_TFM(ctx),
sess->sess_key,
hmac_sha256_init_usingrawkey(&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;
}
hmac_sha256_update(&ctx, i, 4);
hmac_sha256_update(&ctx, label.iov_base, label.iov_len);
hmac_sha256_update(&ctx, &zero, 1);
hmac_sha256_update(&ctx, context.iov_base, context.iov_len);
if (key_size == SMB3_ENC_DEC_KEY_SIZE &&
(conn->cipher_type == SMB2_ENCRYPTION_AES256_CCM ||
conn->cipher_type == SMB2_ENCRYPTION_AES256_GCM))
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L256, 4);
hmac_sha256_update(&ctx, L256, 4);
else
rc = crypto_shash_update(CRYPTO_HMACSHA256(ctx), L128, 4);
if (rc) {
ksmbd_debug(AUTH, "could not update with L\n");
goto smb3signkey_ret;
}
hmac_sha256_update(&ctx, L128, 4);
rc = crypto_shash_final(CRYPTO_HMACSHA256(ctx), hashptr);
if (rc) {
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;
hmac_sha256_final(&ctx, prfhash);
memcpy(key, prfhash, key_size);
}
static int generate_smb3signingkey(struct ksmbd_session *sess,
struct ksmbd_conn *conn,
const struct derivation *signing)
{
int rc;
struct channel *chann;
char *key;
@ -792,10 +581,8 @@ static int generate_smb3signingkey(struct ksmbd_session *sess,
else
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);
if (rc)
return rc;
if (!(conn->dialect >= SMB30_PROT_ID && signing->binding))
memcpy(chann->smb3signingkey, key, SMB3_SIGN_KEY_SIZE);
@ -851,23 +638,17 @@ struct derivation_twin {
struct derivation decryption;
};
static int generate_smb3encryptionkey(struct ksmbd_conn *conn,
static void generate_smb3encryptionkey(struct ksmbd_conn *conn,
struct ksmbd_session *sess,
const struct derivation_twin *ptwin)
{
int rc;
rc = generate_key(conn, sess, ptwin->encryption.label,
generate_key(conn, sess, ptwin->encryption.label,
ptwin->encryption.context, sess->smb3encryptionkey,
SMB3_ENC_DEC_KEY_SIZE);
if (rc)
return rc;
rc = generate_key(conn, sess, ptwin->decryption.label,
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, "Cipher type %d\n", conn->cipher_type);
@ -886,10 +667,9 @@ static int generate_smb3encryptionkey(struct ksmbd_conn *conn,
ksmbd_debug(AUTH, "ServerOut Key %*ph\n",
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 derivation_twin twin;
@ -907,10 +687,10 @@ int ksmbd_gen_smb30_encryptionkey(struct ksmbd_conn *conn,
d->context.iov_base = "ServerIn ";
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 derivation_twin twin;
@ -928,54 +708,26 @@ int ksmbd_gen_smb311_encryptionkey(struct ksmbd_conn *conn,
d->context.iov_base = sess->Preauth_HashValue;
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,
__u8 *pi_hash)
{
int rc;
struct smb2_hdr *rcv_hdr = smb2_get_msg(buf);
char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId;
int msg_size = get_rfc1002_len(buf);
struct ksmbd_crypto_ctx *ctx = NULL;
struct sha512_ctx sha_ctx;
if (conn->preauth_info->Preauth_HashId !=
SMB2_PREAUTH_INTEGRITY_SHA512)
return -EINVAL;
ctx = ksmbd_crypto_ctx_find_sha512();
if (!ctx) {
ksmbd_debug(AUTH, "could not alloc sha512\n");
return -ENOMEM;
}
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;
sha512_init(&sha_ctx);
sha512_update(&sha_ctx, pi_hash, 64);
sha512_update(&sha_ctx, all_bytes_msg, msg_size);
sha512_final(&sha_ctx, pi_hash);
return 0;
}
static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,

View File

@ -52,7 +52,7 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
struct ksmbd_conn *conn);
int ksmbd_krb5_authenticate(struct ksmbd_session *sess, char *in_blob,
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 ksmbd_sign_smb3_pdu(struct ksmbd_conn *conn, char *key, struct kvec *iov,
int n_vec, char *sig);
@ -60,9 +60,9 @@ int ksmbd_gen_smb30_signingkey(struct ksmbd_session *sess,
struct ksmbd_conn *conn);
int ksmbd_gen_smb311_signingkey(struct ksmbd_session *sess,
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,
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,
__u8 *pi_hash);

View File

@ -66,18 +66,9 @@ static struct shash_desc *alloc_shash_desc(int id)
struct shash_desc *shash;
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:
tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
break;
case CRYPTO_SHASH_SHA512:
tfm = crypto_alloc_shash("sha512", 0, 0);
break;
default:
return NULL;
}
@ -180,26 +171,11 @@ static struct ksmbd_crypto_ctx *____crypto_shash_ctx_find(int id)
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)
{
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)
{
struct ksmbd_crypto_ctx *ctx;

View File

@ -10,10 +10,7 @@
#include <crypto/aead.h>
enum {
CRYPTO_SHASH_HMACMD5 = 0,
CRYPTO_SHASH_HMACSHA256,
CRYPTO_SHASH_CMACAES,
CRYPTO_SHASH_SHA512,
CRYPTO_SHASH_CMACAES = 0,
CRYPTO_SHASH_MAX,
};
@ -35,25 +32,15 @@ struct ksmbd_crypto_ctx {
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_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_SHA512_TFM(c) ((c)->desc[CRYPTO_SHASH_SHA512]->tfm)
#define CRYPTO_GCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_GCM])
#define CRYPTO_CCM(c) ((c)->ccmaes[CRYPTO_AEAD_AES_CCM])
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_sha512(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_gcm(void);
struct ksmbd_crypto_ctx *ksmbd_crypto_ctx_find_ccm(void);
void ksmbd_crypto_destroy(void);

View File

@ -78,7 +78,6 @@ ksmbd_tree_conn_connect(struct ksmbd_work *work, const char *share_name)
tree_conn->t_state = TREE_NEW;
status.tree_conn = tree_conn;
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,
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)
{
/*
* Checking waitqueue to releasing tree connect on
* 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);
if (atomic_dec_and_test(&tcon->refcount))
kfree(tcon);
}
int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
@ -119,13 +112,10 @@ int ksmbd_tree_conn_disconnect(struct ksmbd_session *sess,
xa_erase(&sess->tree_conns, tree_conn->id);
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);
ksmbd_release_tree_conn_id(sess, tree_conn->id);
ksmbd_share_config_put(tree_conn->share_conf);
if (atomic_dec_and_test(&tree_conn->refcount))
kfree(tree_conn);
return ret;
}

View File

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

View File

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

View File

@ -1617,9 +1617,9 @@ void create_durable_rsp_buf(char *cc)
*/
void create_durable_v2_rsp_buf(char *cc, struct ksmbd_file *fp)
{
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));
buf->ccontext.DataOffset = cpu_to_le16(offsetof
(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[3] = 'Q';
buf->Timeout = cpu_to_le32(fp->durable_timeout);
buf->dcontext.Timeout = cpu_to_le32(fp->durable_timeout);
if (fp->is_persistent)
buf->Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
}
/**

View File

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

View File

@ -460,7 +460,7 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
}
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))
return 1;

View File

@ -15,7 +15,7 @@
static struct smb_version_values smb21_server_values = {
.version_string = SMB21_VERSION_STRING,
.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_write_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 = {
.version_string = SMB30_VERSION_STRING,
.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_write_size = SMB3_DEFAULT_IOSIZE,
.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,
.create_lease_size = sizeof(struct create_lease_v2),
.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_disk_id_size = sizeof(struct create_disk_id_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 = {
.version_string = SMB302_VERSION_STRING,
.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_write_size = SMB3_DEFAULT_IOSIZE,
.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,
.create_lease_size = sizeof(struct create_lease_v2),
.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_disk_id_size = sizeof(struct create_disk_id_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 = {
.version_string = SMB311_VERSION_STRING,
.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_write_size = SMB3_DEFAULT_IOSIZE,
.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,
.create_lease_size = sizeof(struct create_lease_v2),
.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_disk_id_size = sizeof(struct create_disk_id_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;
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;
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;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_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 ||
(!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) &&
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)
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;
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;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION ||
(!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) &&
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)
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)
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;
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;
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)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_PERSISTENT_HANDLES;
conn->vals->req_capabilities |= SMB2_GLOBAL_CAP_PERSISTENT_HANDLES;
INIT_LIST_HEAD(&conn->preauth_sess_table);
return 0;

View File

@ -282,7 +282,7 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
/* Not setting conn guid rsp->ServerGUID, as it
* not 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*/
rsp->MaxTransactSize = cpu_to_le32(conn->vals->max_trans_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.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;
}
@ -1210,7 +1210,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
rc = -EINVAL;
goto err_out;
}
rsp->Capabilities = cpu_to_le32(conn->vals->capabilities);
rsp->Capabilities = cpu_to_le32(conn->vals->req_capabilities);
/* For stats */
conn->connection_type = conn->dialect;
@ -1538,12 +1538,7 @@ static int ntlm_authenticate(struct ksmbd_work *work,
if (smb3_encryption_negotiated(conn) &&
!(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
rc = conn->ops->generate_encryptionkey(conn, sess);
if (rc) {
ksmbd_debug(SMB,
"SMB3 encryption key generation failed\n");
return -EINVAL;
}
conn->ops->generate_encryptionkey(conn, sess);
sess->enc = true;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION)
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) &&
!(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
retval = conn->ops->generate_encryptionkey(conn, sess);
if (retval) {
ksmbd_debug(SMB,
"SMB3 encryption key generation failed\n");
return -EINVAL;
}
conn->ops->generate_encryptionkey(conn, sess);
sess->enc = true;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION)
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
* @work: smb work containing request buffer
*
* Return: 0
* Return: 0 on success, otherwise error
*/
int smb2_tree_disconnect(struct ksmbd_work *work)
{
@ -2200,7 +2190,6 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
goto err_out;
}
WARN_ON_ONCE(atomic_dec_and_test(&tcon->refcount));
tcon->t_state = TREE_DISCONNECTED;
write_unlock(&sess->tree_conns_lock);
@ -2210,8 +2199,6 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
goto err_out;
}
work->tcon = NULL;
rsp->StructureSize = cpu_to_le16(4);
err = ksmbd_iov_pin_rsp(work, 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
* @work: smb work containing request buffer
*
* Return: 0
* Return: 0 on success, otherwise error
*/
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) {
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 ||
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) +
le32_to_cpu(context->DataLength) <
sizeof(struct create_durable_reconn_v2_req)) {
sizeof(struct create_durable_handle_reconnect_v2)) {
err = -EINVAL;
goto out;
}
recon_v2 = (struct create_durable_reconn_v2_req *)context;
persistent_id = recon_v2->Fid.PersistentFileId;
recon_v2 = (struct create_durable_handle_reconnect_v2 *)context;
persistent_id = recon_v2->dcontext.Fid.PersistentFileId;
dh_info->fp = ksmbd_lookup_durable_fd(persistent_id);
if (!dh_info->fp) {
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;
}
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)) {
err = -EBADF;
ksmbd_put_durable_fd(dh_info->fp);
@ -2766,7 +2753,7 @@ static int parse_durable_handle_context(struct ksmbd_work *work,
}
case DURABLE_RECONN:
{
struct create_durable_reconn_req *recon;
create_durable_reconn_t *recon;
if (dh_info->type == DURABLE_RECONN_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) +
le32_to_cpu(context->DataLength) <
sizeof(struct create_durable_reconn_req)) {
sizeof(create_durable_reconn_t)) {
err = -EINVAL;
goto out;
}
recon = (struct create_durable_reconn_req *)context;
recon = (create_durable_reconn_t *)context;
persistent_id = recon->Data.Fid.PersistentFileId;
dh_info->fp = ksmbd_lookup_durable_fd(persistent_id);
if (!dh_info->fp) {
@ -2816,7 +2803,7 @@ static int parse_durable_handle_context(struct ksmbd_work *work,
durable_v2_blob =
(struct create_durable_req_v2 *)context;
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 (!memcmp(conn->ClientGUID, dh_info->fp->client_guid,
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)) ||
req_op_level == SMB2_OPLOCK_LEVEL_BATCH) {
dh_info->CreateGuid =
durable_v2_blob->CreateGuid;
durable_v2_blob->dcontext.CreateGuid;
dh_info->persistent =
le32_to_cpu(durable_v2_blob->Flags);
le32_to_cpu(durable_v2_blob->dcontext.Flags);
dh_info->timeout =
le32_to_cpu(durable_v2_blob->Timeout);
le32_to_cpu(durable_v2_blob->dcontext.Timeout);
dh_info->type = dh_idx;
}
break;
@ -3474,7 +3461,7 @@ int smb2_open(struct ksmbd_work *work)
share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp);
if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) ||
(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)) {
rc = share_ret;
goto err_out1;
@ -3796,15 +3783,15 @@ static int readdir_info_level_struct_sz(int info_level)
{
switch (info_level) {
case FILE_FULL_DIRECTORY_INFORMATION:
return sizeof(struct file_full_directory_info);
return sizeof(FILE_FULL_DIRECTORY_INFO);
case FILE_BOTH_DIRECTORY_INFORMATION:
return sizeof(struct file_both_directory_info);
return sizeof(FILE_BOTH_DIRECTORY_INFO);
case FILE_DIRECTORY_INFORMATION:
return sizeof(struct file_directory_info);
return sizeof(FILE_DIRECTORY_INFO);
case FILE_NAMES_INFORMATION:
return sizeof(struct file_names_info);
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:
return sizeof(struct file_id_both_directory_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) {
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->name = ffdinfo->FileName;
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:
{
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->name = fbdinfo->FileName;
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:
{
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->name = fdinfo->FileName;
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:
{
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->name = dinfo->FileName;
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) {
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->EaSize =
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:
{
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->EaSize =
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:
{
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);
if (d_info->hide_dot_file && d_info->name[0] == '.')
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:
{
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->EaSize =
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) {
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);
ffdinfo->FileName[d_info->name_len] = 0x00;
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:
{
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);
fbdinfo->FileName[d_info->name_len] = 0x00;
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:
{
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);
fdinfo->FileName[d_info->name_len] = 0x00;
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:
{
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);
dinfo->FileName[d_info->name_len] = 0x00;
dinfo->FileNameLength = cpu_to_le32(d_info->name_len);
@ -4514,7 +4501,7 @@ int smb2_query_dir(struct ksmbd_work *work)
goto err_out;
} else {
no_buf_len:
((struct file_directory_info *)
((FILE_DIRECTORY_INFO *)
((char *)rsp->Buffer + d_info.last_entry_offset))
->NextEntryOffset = 0;
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);
ksmbd_fd_put(work, dir_fp);
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,
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;
u64 time;
int ret;
@ -5149,7 +5136,7 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp,
if (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);
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);
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_ntwrk_info));
cpu_to_le32(sizeof(struct smb2_file_network_open_info));
return 0;
}
@ -5476,9 +5463,9 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
switch (fsinfoclass) {
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->DeviceCharacteristics =
@ -5492,10 +5479,10 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
}
case FS_ATTRIBUTE_INFORMATION:
{
struct filesystem_attribute_info *info;
FILE_SYSTEM_ATTRIBUTE_INFO *info;
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 |
FILE_PERSISTENT_ACLS |
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);
len = len * 2;
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);
break;
}
@ -5546,11 +5533,11 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
}
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->FreeAllocationUnits = cpu_to_le64(stfs.f_bfree);
info->AvailableAllocationUnits = cpu_to_le64(stfs.f_bfree);
info->SectorsPerAllocationUnit = cpu_to_le32(1);
info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
rsp->OutputBufferLength = cpu_to_le32(24);
@ -5633,14 +5620,14 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
}
case FS_POSIX_INFORMATION:
{
struct filesystem_posix_info *info;
FILE_SYSTEM_POSIX_INFO *info;
if (!work->tcon->posix_extensions) {
pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
path_put(&path);
return -EOPNOTSUPP;
} else {
info = (struct filesystem_posix_info *)(rsp->Buffer);
info = (FILE_SYSTEM_POSIX_INFO *)(rsp->Buffer);
info->OptimalTransferSize = cpu_to_le32(stfs.f_bsize);
info->BlockSize = cpu_to_le32(stfs.f_bsize);
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
* @work: smb work containing close request buffer
*
* Return: 0
* Return: 0 on success, otherwise error
*/
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
* @work: smb work containing echo request buffer
*
* Return: 0
* Return: 0 on success, otherwise error
*/
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
*
* 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,
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:
{
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);
}
case FILE_ALLOCATION_INFORMATION:
{
if (buf_len < sizeof(struct smb2_file_alloc_info))
return -EINVAL;
return -EMSGSIZE;
return set_file_allocation_info(work, fp,
(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:
{
if (buf_len < sizeof(struct smb2_file_eof_info))
return -EINVAL;
return -EMSGSIZE;
return set_end_of_file_info(work, fp,
(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:
{
if (buf_len < sizeof(struct smb2_file_rename_info))
return -EINVAL;
return -EMSGSIZE;
return set_rename_info(work, fp,
(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:
{
if (buf_len < sizeof(struct smb2_file_link_info))
return -EINVAL;
return -EMSGSIZE;
return smb2_create_link(work, work->tcon->share_conf,
(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:
{
if (buf_len < sizeof(struct smb2_file_disposition_info))
return -EINVAL;
return -EMSGSIZE;
return set_file_disposition_info(fp,
(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))
return -EINVAL;
return -EMSGSIZE;
return smb2_set_ea((struct smb2_ea_info *)buffer,
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:
{
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);
}
case FILE_MODE_INFORMATION:
{
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);
}
@ -6587,6 +6573,8 @@ int smb2_set_info(struct ksmbd_work *work)
rsp->hdr.Status = STATUS_ACCESS_DENIED;
else if (rc == -EINVAL)
rsp->hdr.Status = STATUS_INVALID_PARAMETER;
else if (rc == -EMSGSIZE)
rsp->hdr.Status = STATUS_INFO_LENGTH_MISMATCH;
else if (rc == -ESHARE)
rsp->hdr.Status = STATUS_SHARING_VIOLATION;
else if (rc == -ENOENT)
@ -6842,7 +6830,7 @@ int smb2_read(struct ksmbd_work *work)
rsp->hdr.Status = STATUS_END_OF_FILE;
smb2_set_err_rsp(work);
ksmbd_fd_put(work, fp);
return 0;
return -ENODATA;
}
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,
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);
ret = -EINVAL;
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;
goto out;
}
@ -7876,9 +7864,9 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
nii_rsp->Capability = 0;
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))
nii_rsp->Capability |= cpu_to_le32(RDMA_CAPABLE);
nii_rsp->Capability |= RDMA_CAPABLE;
nii_rsp->Next = cpu_to_le32(152);
nii_rsp->Reserved = 0;
@ -7904,13 +7892,13 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
if (!ipv4_set) {
struct in_device *idev;
sockaddr_storage->Family = cpu_to_le16(INTERNETWORK);
sockaddr_storage->Family = INTERNETWORK;
sockaddr_storage->addr4.Port = 0;
idev = __in_dev_get_rtnl(netdev);
if (!idev)
continue;
sockaddr_storage->addr4.IPv4address =
sockaddr_storage->addr4.IPv4Address =
idev_ipv4_address(idev);
nbytes += sizeof(struct network_interface_info_ioctl_rsp);
ipv4_set = true;
@ -7918,9 +7906,9 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
} else {
struct inet6_dev *idev6;
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.FlowInfo = 0;
@ -7984,7 +7972,7 @@ static int fsctl_validate_negotiate_info(struct ksmbd_conn *conn,
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);
neg_rsp->SecurityMode = cpu_to_le16(conn->srv_sec_mode);
neg_rsp->Dialect = cpu_to_le16(conn->dialect);
@ -8122,8 +8110,8 @@ static int fsctl_request_resume_key(struct ksmbd_work *work,
return -ENOENT;
memset(key_rsp, 0, sizeof(*key_rsp));
key_rsp->ResumeKey[0] = req->VolatileFileId;
key_rsp->ResumeKey[1] = req->PersistentFileId;
key_rsp->ResumeKeyU64[0] = req->VolatileFileId;
key_rsp->ResumeKeyU64[1] = req->PersistentFileId;
ksmbd_fd_put(work, fp);
return 0;
@ -8164,7 +8152,7 @@ int smb2_ioctl(struct ksmbd_work *work)
id = req->VolatileFileId;
if (req->Flags != cpu_to_le32(SMB2_0_IOCTL_IS_FSCTL)) {
rsp->hdr.Status = STATUS_NOT_SUPPORTED;
ret = -EOPNOTSUPP;
goto out;
}
@ -8184,8 +8172,9 @@ int smb2_ioctl(struct ksmbd_work *work)
case FSCTL_DFS_GET_REFERRALS:
case FSCTL_DFS_GET_REFERRALS_EX:
/* Not support DFS yet */
ret = -EOPNOTSUPP;
rsp->hdr.Status = STATUS_FS_DRIVER_REQUIRED;
goto out;
goto out2;
case FSCTL_CREATE_OR_GET_OBJECT_ID:
{
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;
else if (ret < 0 || rsp->hdr.Status == 0)
rsp->hdr.Status = STATUS_INVALID_PARAMETER;
out2:
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
* @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)
{
@ -8778,6 +8769,7 @@ int smb2_oplock_break(struct ksmbd_work *work)
le16_to_cpu(req->StructureSize));
rsp->hdr.Status = STATUS_INVALID_PARAMETER;
smb2_set_err_rsp(work);
return -EINVAL;
}
return 0;
@ -8787,7 +8779,7 @@ int smb2_oplock_break(struct ksmbd_work *work)
* smb2_notify() - handler for smb2 notify request
* @work: smb work containing notify command buffer
*
* Return: 0
* Return: 0 on success, otherwise error
*/
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) {
rsp->hdr.Status = STATUS_INTERNAL_ERROR;
smb2_set_err_rsp(work);
return 0;
return -EIO;
}
smb2_set_err_rsp(work);
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_len = len;
if (ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, 1,
signature))
return 0;
ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, 1,
signature);
if (memcmp(signature, signature_req, SMB2_SIGNATURE_SIZE)) {
pr_err("bad smb2 signature\n");
@ -8896,8 +8887,8 @@ void smb2_set_sign_rsp(struct ksmbd_work *work)
iov = &work->iov[work->iov_idx];
}
if (!ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, n_vec,
signature))
ksmbd_sign_smb2_pdu(work->conn, work->sess->sess_key, iov, n_vec,
signature);
memcpy(hdr->Signature, signature, SMB2_SIGNATURE_SIZE);
}

View File

@ -66,40 +66,8 @@ struct preauth_integrity_info {
/* Apple Defined Contexts */
#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
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_context_hdr ccontext;
__u8 Name[8];
@ -115,16 +83,6 @@ struct create_durable_rsp {
} Data;
} __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 */
struct create_posix_rsp {
struct create_context_hdr ccontext;
@ -138,22 +96,6 @@ struct create_posix_rsp {
#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 {
__le16 Family;
union {
@ -162,18 +104,6 @@ struct sockaddr_storage_rsp {
};
} __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 {
__u8 ObjectId[16];
__u8 BirthVolumeId[16];
@ -181,32 +111,6 @@ struct file_object_buf_type1_ioctl_rsp {
__u8 DomainId[16];
} __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 {
__u8 SetSparse;
} __packed;
@ -301,17 +205,6 @@ struct smb2_file_stream_info {
char StreamName[];
} __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 {
__le64 AllocationSize;
__le64 EndOfFile;

View File

@ -10,8 +10,9 @@
#include "glob.h"
#include "nterr.h"
#include "../common/cifsglob.h"
#include "../common/smbglob.h"
#include "../common/smb2pdu.h"
#include "../common/fscc.h"
#include "smb2pdu.h"
/* ksmbd's Specific ERRNO */
@ -29,8 +30,6 @@
#define SMB_ECHO_INTERVAL (60 * HZ)
#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
#define MAX_STREAM_PROT_LEN 0x00FFFFFF
/* Responses when opening a file. */
@ -39,80 +38,7 @@
#define F_CREATED 2
#define F_OVERWRITTEN 3
/*
* 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. */
/* Combinations of file access permission bits */
#define SET_FILE_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA \
| FILE_READ_ATTRIBUTES \
| DELETE | READ_CONTROL | WRITE_DAC \
@ -123,14 +49,6 @@
| FILE_WRITE_ATTRIBUTES \
| DELETE | READ_CONTROL | WRITE_DAC \
| 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 */
#define GENERIC_READ_FLAGS (READ_CONTROL | FILE_READ_DATA | \
@ -151,71 +69,27 @@
FILE_EXECUTE | FILE_DELETE_CHILD | \
FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES)
#define SMB1_PROTO_NUMBER cpu_to_le32(0x424d53ff)
#define SMB_COM_NEGOTIATE 0x72
#define SMB1_CLIENT_GUID_SIZE (16)
#define SMB_COM_NEGOTIATE 0x72 /* See MS-CIFS 2.2.2.1 */
/* See MS-CIFS 2.2.3.1 */
#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_EXT_SEC cpu_to_le16(0x800)
#define SMBFLG2_ERR_STATUS cpu_to_le16(0x4000)
#define SMBFLG2_UNICODE cpu_to_le16(0x8000)
struct smb_hdr {
__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;
/* See MS-CIFS 2.2.4.52.2 */
struct smb_negotiate_rsp {
struct smb_hdr hdr; /* wct = 17 */
__le16 DialectIndex; /* 0xFFFF = no dialect acceptable */
__le16 ByteCount;
} __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 {
__le64 VolumeCreationTime;
__le32 SerialNumber;
@ -224,13 +98,6 @@ struct filesystem_vol_info {
__le16 VolumeLabel[];
} __packed;
struct filesystem_info {
__le64 TotalAllocationUnits;
__le64 FreeAllocationUnits;
__le32 SectorsPerAllocationUnit;
__le32 BytesPerSector;
} __packed; /* size info, level 0x103 */
#define EXTENDED_INFO_MAGIC 0x43667364 /* Cfsd */
#define STRING_LENGTH 28
@ -247,20 +114,6 @@ struct object_id_info {
struct fs_extended_info extended_info;
} __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 {
__le32 NextEntryOffset;
__u32 FileIndex;
@ -268,39 +121,6 @@ struct file_names_info {
char FileName[];
} __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 {
__le32 NextEntryOffset;
__u32 FileIndex;
@ -321,75 +141,6 @@ struct file_id_both_directory_info {
char FileName[];
} __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 {
u16 (*get_cmd_val)(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);
void (*set_sign_rsp)(struct ksmbd_work *work);
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);
int (*decrypt_req)(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);
bool is_asterisk(char *p);
__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__ */

View File

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

View File

@ -19,6 +19,8 @@
#include <rdma/rdma_cm.h>
#include <rdma/rw.h>
#define __SMBDIRECT_SOCKET_DISCONNECT(__sc) smb_direct_disconnect_rdma_connection(__sc)
#include "glob.h"
#include "connection.h"
#include "smb_common.h"
@ -231,6 +233,9 @@ static void smb_direct_disconnect_rdma_work(struct work_struct *work)
struct smbdirect_socket *sc =
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
* 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_work(&sc->idle.immediate_work);
if (sc->first_error == 0)
sc->first_error = -ECONNABORTED;
switch (sc->status) {
case SMBDIRECT_SOCKET_NEGOTIATE_NEEDED:
case SMBDIRECT_SOCKET_NEGOTIATE_RUNNING:
@ -287,6 +289,9 @@ static void smb_direct_disconnect_rdma_work(struct work_struct *work)
static void
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
* 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_delayed_work(&sc->idle.timer_work);
if (sc->first_error == 0)
sc->first_error = -ECONNABORTED;
switch (sc->status) {
case SMBDIRECT_SOCKET_RESOLVE_ADDR_FAILED:
case SMBDIRECT_SOCKET_RESOLVE_ROUTE_FAILED:
@ -639,7 +641,18 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
return;
}
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;
enqueue_reassembly(sc, recvmsg, 0);
wake_up(&sc->status_wait);
@ -1725,7 +1738,18 @@ static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
switch (event->event) {
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;
wake_up(&sc->status_wait);
break;

View File

@ -22,7 +22,6 @@ struct interface {
struct socket *ksmbd_socket;
struct list_head entry;
char *name;
struct mutex sock_release_lock;
int state;
};
@ -56,19 +55,6 @@ static inline void ksmbd_tcp_reuseaddr(struct socket *sock)
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)
{
struct tcp_transport *t;
@ -236,20 +222,14 @@ static int ksmbd_kthread_fn(void *p)
unsigned int max_ip_conns;
while (!kthread_should_stop()) {
mutex_lock(&iface->sock_release_lock);
if (!iface->ksmbd_socket) {
mutex_unlock(&iface->sock_release_lock);
break;
}
ret = kernel_accept(iface->ksmbd_socket, &client_sk,
SOCK_NONBLOCK);
mutex_unlock(&iface->sock_release_lock);
if (ret) {
if (ret == -EAGAIN)
/* check for new connections every 100 msecs */
schedule_timeout_interruptible(HZ / 10);
ret = kernel_accept(iface->ksmbd_socket, &client_sk, 0);
if (ret == -EINVAL)
break;
if (ret)
continue;
}
if (!server_conf.max_ip_connections)
goto skip_max_ip_conns_limit;
@ -458,10 +438,6 @@ static void tcp_destroy_socket(struct socket *ksmbd_socket)
if (!ksmbd_socket)
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);
if (ret)
pr_err("Failed to shutdown socket: %d\n", ret);
@ -532,9 +508,6 @@ static int create_socket(struct interface *iface)
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);
if (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) {
ksmbd_debug(CONN, "netdev-down event: netdev(%s) is going down\n",
iface->name);
kernel_sock_shutdown(iface->ksmbd_socket, SHUT_RDWR);
tcp_stop_kthread(iface->ksmbd_kthread);
iface->ksmbd_kthread = NULL;
mutex_lock(&iface->sock_release_lock);
tcp_destroy_socket(iface->ksmbd_socket);
sock_release(iface->ksmbd_socket);
iface->ksmbd_socket = NULL;
mutex_unlock(&iface->sock_release_lock);
iface->state = IFACE_STATE_DOWN;
break;
@ -672,7 +644,6 @@ static struct interface *alloc_iface(char *ifname)
iface->name = ifname;
iface->state = IFACE_STATE_DOWN;
list_add(&iface->entry, &iface_list);
mutex_init(&iface->sock_release_lock);
return iface;
}

View File

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

View File

@ -112,40 +112,62 @@ int ksmbd_query_inode_status(struct dentry *dentry)
read_lock(&inode_hash_lock);
ci = __ksmbd_inode_lookup(dentry);
if (ci) {
ret = KSMBD_INODE_STATUS_OK;
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);
}
read_unlock(&inode_hash_lock);
return ret;
}
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)
{
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)
{
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,
int file_info)
{
if (ksmbd_stream_fd(fp)) {
fp->f_ci->m_flags |= S_DEL_ON_CLS_STREAM;
return;
}
struct ksmbd_inode *ci = fp->f_ci;
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)
@ -257,8 +279,18 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
struct file *filp;
filp = fp->filp;
if (ksmbd_stream_fd(fp) && (ci->m_flags & S_DEL_ON_CLS_STREAM)) {
if (ksmbd_stream_fd(fp)) {
bool remove_stream_xattr = false;
down_write(&ci->m_lock);
if (ci->m_flags & S_DEL_ON_CLS_STREAM) {
ci->m_flags &= ~S_DEL_ON_CLS_STREAM;
remove_stream_xattr = true;
}
up_write(&ci->m_lock);
if (remove_stream_xattr) {
err = ksmbd_vfs_remove_xattr(file_mnt_idmap(filp),
&filp->f_path,
fp->stream.name,
@ -267,17 +299,21 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
pr_err("remove xattr failed : %s\n",
fp->stream.name);
}
}
if (atomic_dec_and_test(&ci->m_count)) {
bool do_unlink = false;
down_write(&ci->m_lock);
if (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);
ksmbd_vfs_unlink(filp);
down_write(&ci->m_lock);
do_unlink = true;
}
up_write(&ci->m_lock);
if (do_unlink)
ksmbd_vfs_unlink(filp);
ksmbd_inode_free(ci);
}
}