提交 a6132241 编写于 作者: L Linus Torvalds

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

Pull ksmbd updates from Steve French:
 "Several smb server fixes; three for stable:

   - important fix for negotiation info validation

   - fix alignment check in packet validation

   - cleanup of dead code (like MD4)

   - refactoring some protocol headers to use common code in smbfs_common"

* tag '5.16-rc-ksmbd-fixes' of git://git.samba.org/ksmbd:
  ksmbd: Use the SMB3_Create definitions from the shared
  ksmbd: Move more definitions into the shared area
  ksmbd: use the common definitions for NEGOTIATE_PROTOCOL
  ksmbd: switch to use shared definitions where available
  ksmbd: change LeaseKey data type to u8 array
  ksmbd: remove smb2_buf_length in smb2_transform_hdr
  ksmbd: remove smb2_buf_length in smb2_hdr
  ksmbd: remove md4 leftovers
  ksmbd: set unique value to volume serial field in FS_VOLUME_INFORMATION
  ksmbd: don't need 8byte alignment for request length in ksmbd_check_message
  ksmbd: Fix buffer length check in fsctl_validate_negotiate_info()
  ksmbd: Remove redundant 'flush_workqueue()' calls
  ksmdb: use cmd helper variable in smb2_get_ksmbd_tcon()
  ksmbd: use ksmbd_req_buf_next() in ksmbd_smb2_check_message()
  ksmbd: use ksmbd_req_buf_next() in ksmbd_verify_smb_message()
......@@ -6,7 +6,6 @@ config SMB_SERVER
select NLS
select NLS_UTF8
select CRYPTO
select CRYPTO_MD4
select CRYPTO_MD5
select CRYPTO_HMAC
select CRYPTO_ECB
......@@ -19,6 +18,7 @@ config SMB_SERVER
select CRYPTO_GCM
select ASN1
select OID_REGISTRY
select CRC32
default n
help
Choose Y here if you want to allow SMB3 compliant clients
......
......@@ -873,9 +873,9 @@ int ksmbd_gen_preauth_integrity_hash(struct ksmbd_conn *conn, char *buf,
__u8 *pi_hash)
{
int rc;
struct smb2_hdr *rcv_hdr = (struct smb2_hdr *)buf;
struct smb2_hdr *rcv_hdr = smb2_get_msg(buf);
char *all_bytes_msg = (char *)&rcv_hdr->ProtocolId;
int msg_size = be32_to_cpu(rcv_hdr->smb2_buf_length);
int msg_size = get_rfc1002_len(buf);
struct ksmbd_crypto_ctx *ctx = NULL;
if (conn->preauth_info->Preauth_HashId !=
......@@ -983,7 +983,7 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
u8 *sign)
{
struct scatterlist *sg;
unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
int i, nr_entries[3] = {0}, total_entries = 0, sg_idx = 0;
if (!nvec)
......@@ -1047,9 +1047,8 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
int ksmbd_crypt_message(struct ksmbd_conn *conn, struct kvec *iov,
unsigned int nvec, int enc)
{
struct smb2_transform_hdr *tr_hdr =
(struct smb2_transform_hdr *)iov[0].iov_base;
unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
struct smb2_transform_hdr *tr_hdr = smb2_get_msg(iov[0].iov_base);
unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
int rc;
struct scatterlist *sg;
u8 sign[SMB2_SIGNATURE_SIZE] = {};
......
......@@ -158,26 +158,25 @@ void ksmbd_conn_wait_idle(struct ksmbd_conn *conn)
int ksmbd_conn_write(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct smb_hdr *rsp_hdr = work->response_buf;
size_t len = 0;
int sent;
struct kvec iov[3];
int iov_idx = 0;
ksmbd_conn_try_dequeue_request(work);
if (!rsp_hdr) {
if (!work->response_buf) {
pr_err("NULL response header\n");
return -EINVAL;
}
if (work->tr_buf) {
iov[iov_idx] = (struct kvec) { work->tr_buf,
sizeof(struct smb2_transform_hdr) };
sizeof(struct smb2_transform_hdr) + 4 };
len += iov[iov_idx++].iov_len;
}
if (work->aux_payload_sz) {
iov[iov_idx] = (struct kvec) { rsp_hdr, work->resp_hdr_sz };
iov[iov_idx] = (struct kvec) { work->response_buf, work->resp_hdr_sz };
len += iov[iov_idx++].iov_len;
iov[iov_idx] = (struct kvec) { work->aux_payload_buf, work->aux_payload_sz };
len += iov[iov_idx++].iov_len;
......@@ -185,8 +184,8 @@ int ksmbd_conn_write(struct ksmbd_work *work)
if (work->tr_buf)
iov[iov_idx].iov_len = work->resp_hdr_sz;
else
iov[iov_idx].iov_len = get_rfc1002_len(rsp_hdr) + 4;
iov[iov_idx].iov_base = rsp_hdr;
iov[iov_idx].iov_len = get_rfc1002_len(work->response_buf) + 4;
iov[iov_idx].iov_base = work->response_buf;
len += iov[iov_idx++].iov_len;
}
......
......@@ -69,7 +69,6 @@ int ksmbd_workqueue_init(void)
void ksmbd_workqueue_destroy(void)
{
flush_workqueue(ksmbd_wq);
destroy_workqueue(ksmbd_wq);
ksmbd_wq = NULL;
}
......
......@@ -92,7 +92,7 @@ struct ksmbd_work {
*/
static inline void *ksmbd_resp_buf_next(struct ksmbd_work *work)
{
return work->response_buf + work->next_smb2_rsp_hdr_off;
return work->response_buf + work->next_smb2_rsp_hdr_off + 4;
}
/**
......@@ -101,7 +101,7 @@ static inline void *ksmbd_resp_buf_next(struct ksmbd_work *work)
*/
static inline void *ksmbd_req_buf_next(struct ksmbd_work *work)
{
return work->request_buf + work->next_smb2_rcv_hdr_off;
return work->request_buf + work->next_smb2_rcv_hdr_off + 4;
}
struct ksmbd_work *ksmbd_alloc_work_struct(void);
......
......@@ -629,10 +629,10 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
return;
}
rsp_hdr = work->response_buf;
rsp_hdr = smb2_get_msg(work->response_buf);
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
rsp_hdr->smb2_buf_length =
cpu_to_be32(smb2_hdr_size_no_buflen(conn->vals));
*(__be32 *)work->response_buf =
cpu_to_be32(conn->vals->header_size);
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->CreditRequest = cpu_to_le16(0);
......@@ -645,7 +645,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
rsp_hdr->SessionId = 0;
memset(rsp_hdr->Signature, 0, 16);
rsp = work->response_buf;
rsp = smb2_get_msg(work->response_buf);
rsp->StructureSize = cpu_to_le16(24);
if (!br_info->open_trunc &&
......@@ -659,7 +659,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
rsp->PersistentFid = cpu_to_le64(fp->persistent_id);
rsp->VolatileFid = cpu_to_le64(fp->volatile_id);
inc_rfc1001_len(rsp, 24);
inc_rfc1001_len(work->response_buf, 24);
ksmbd_debug(OPLOCK,
"sending oplock break v_id %llu p_id = %llu lock level = %d\n",
......@@ -736,10 +736,10 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
return;
}
rsp_hdr = work->response_buf;
rsp_hdr = smb2_get_msg(work->response_buf);
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
rsp_hdr->smb2_buf_length =
cpu_to_be32(smb2_hdr_size_no_buflen(conn->vals));
*(__be32 *)work->response_buf =
cpu_to_be32(conn->vals->header_size);
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->CreditRequest = cpu_to_le16(0);
......@@ -752,7 +752,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
rsp_hdr->SessionId = 0;
memset(rsp_hdr->Signature, 0, 16);
rsp = work->response_buf;
rsp = smb2_get_msg(work->response_buf);
rsp->StructureSize = cpu_to_le16(44);
rsp->Epoch = br_info->epoch;
rsp->Flags = 0;
......@@ -768,7 +768,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
rsp->AccessMaskHint = 0;
rsp->ShareMaskHint = 0;
inc_rfc1001_len(rsp, 44);
inc_rfc1001_len(work->response_buf, 44);
ksmbd_conn_write(work);
ksmbd_free_work_struct(work);
......@@ -1335,19 +1335,16 @@ __u8 smb2_map_lease_to_oplock(__le32 lease_state)
*/
void create_lease_buf(u8 *rbuf, struct lease *lease)
{
char *LeaseKey = (char *)&lease->lease_key;
if (lease->version == 2) {
struct create_lease_v2 *buf = (struct create_lease_v2 *)rbuf;
char *ParentLeaseKey = (char *)&lease->parent_lease_key;
memset(buf, 0, sizeof(struct create_lease_v2));
buf->lcontext.LeaseKeyLow = *((__le64 *)LeaseKey);
buf->lcontext.LeaseKeyHigh = *((__le64 *)(LeaseKey + 8));
memcpy(buf->lcontext.LeaseKey, lease->lease_key,
SMB2_LEASE_KEY_SIZE);
buf->lcontext.LeaseFlags = lease->flags;
buf->lcontext.LeaseState = lease->state;
buf->lcontext.ParentLeaseKeyLow = *((__le64 *)ParentLeaseKey);
buf->lcontext.ParentLeaseKeyHigh = *((__le64 *)(ParentLeaseKey + 8));
memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key,
SMB2_LEASE_KEY_SIZE);
buf->ccontext.DataOffset = cpu_to_le16(offsetof
(struct create_lease_v2, lcontext));
buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2));
......@@ -1362,8 +1359,7 @@ void create_lease_buf(u8 *rbuf, struct lease *lease)
struct create_lease *buf = (struct create_lease *)rbuf;
memset(buf, 0, sizeof(struct create_lease));
buf->lcontext.LeaseKeyLow = *((__le64 *)LeaseKey);
buf->lcontext.LeaseKeyHigh = *((__le64 *)(LeaseKey + 8));
memcpy(buf->lcontext.LeaseKey, lease->lease_key, SMB2_LEASE_KEY_SIZE);
buf->lcontext.LeaseFlags = lease->flags;
buf->lcontext.LeaseState = lease->state;
buf->ccontext.DataOffset = cpu_to_le16(offsetof
......@@ -1398,7 +1394,7 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
if (!lreq)
return NULL;
data_offset = (char *)req + 4 + le32_to_cpu(req->CreateContextsOffset);
data_offset = (char *)req + le32_to_cpu(req->CreateContextsOffset);
cc = (struct create_context *)data_offset;
do {
cc = (struct create_context *)((char *)cc + next);
......@@ -1416,19 +1412,17 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
if (sizeof(struct lease_context_v2) == le32_to_cpu(cc->DataLength)) {
struct create_lease_v2 *lc = (struct create_lease_v2 *)cc;
*((__le64 *)lreq->lease_key) = lc->lcontext.LeaseKeyLow;
*((__le64 *)(lreq->lease_key + 8)) = lc->lcontext.LeaseKeyHigh;
memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
lreq->req_state = lc->lcontext.LeaseState;
lreq->flags = lc->lcontext.LeaseFlags;
lreq->duration = lc->lcontext.LeaseDuration;
*((__le64 *)lreq->parent_lease_key) = lc->lcontext.ParentLeaseKeyLow;
*((__le64 *)(lreq->parent_lease_key + 8)) = lc->lcontext.ParentLeaseKeyHigh;
memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
SMB2_LEASE_KEY_SIZE);
lreq->version = 2;
} else {
struct create_lease *lc = (struct create_lease *)cc;
*((__le64 *)lreq->lease_key) = lc->lcontext.LeaseKeyLow;
*((__le64 *)(lreq->lease_key + 8)) = lc->lcontext.LeaseKeyHigh;
memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
lreq->req_state = lc->lcontext.LeaseState;
lreq->flags = lc->lcontext.LeaseFlags;
lreq->duration = lc->lcontext.LeaseDuration;
......@@ -1462,7 +1456,7 @@ struct create_context *smb2_find_context_vals(void *open_req, const char *tag)
* CreateContextsOffset and CreateContextsLength are guaranteed to
* be valid because of ksmbd_smb2_check_message().
*/
cc = (struct create_context *)((char *)req + 4 +
cc = (struct create_context *)((char *)req +
le32_to_cpu(req->CreateContextsOffset));
remain_len = le32_to_cpu(req->CreateContextsLength);
do {
......
......@@ -28,8 +28,6 @@
#define OPLOCK_WRITE_TO_NONE 0x04
#define OPLOCK_READ_TO_NONE 0x08
#define SMB2_LEASE_KEY_SIZE 16
struct lease_ctx_info {
__u8 lease_key[SMB2_LEASE_KEY_SIZE];
__le32 req_state;
......
......@@ -622,7 +622,6 @@ MODULE_DESCRIPTION("Linux kernel CIFS/SMB SERVER");
MODULE_LICENSE("GPL");
MODULE_SOFTDEP("pre: ecb");
MODULE_SOFTDEP("pre: hmac");
MODULE_SOFTDEP("pre: md4");
MODULE_SOFTDEP("pre: md5");
MODULE_SOFTDEP("pre: nls");
MODULE_SOFTDEP("pre: aes");
......@@ -632,5 +631,6 @@ MODULE_SOFTDEP("pre: sha512");
MODULE_SOFTDEP("pre: aead2");
MODULE_SOFTDEP("pre: ccm");
MODULE_SOFTDEP("pre: gcm");
MODULE_SOFTDEP("pre: crc32");
module_init(ksmbd_server_init)
module_exit(ksmbd_server_exit)
......@@ -6,7 +6,6 @@
#include "glob.h"
#include "nterr.h"
#include "smb2pdu.h"
#include "smb_common.h"
#include "smbstatus.h"
#include "mgmt/user_session.h"
......@@ -347,23 +346,16 @@ static int smb2_validate_credit_charge(struct ksmbd_conn *conn,
int ksmbd_smb2_check_message(struct ksmbd_work *work)
{
struct smb2_pdu *pdu = work->request_buf;
struct smb2_pdu *pdu = ksmbd_req_buf_next(work);
struct smb2_hdr *hdr = &pdu->hdr;
int command;
__u32 clc_len; /* calculated length */
__u32 len = get_rfc1002_len(pdu);
__u32 len = get_rfc1002_len(work->request_buf);
if (work->next_smb2_rcv_hdr_off) {
pdu = ksmbd_req_buf_next(work);
hdr = &pdu->hdr;
}
if (le32_to_cpu(hdr->NextCommand) > 0) {
if (le32_to_cpu(hdr->NextCommand) > 0)
len = le32_to_cpu(hdr->NextCommand);
} else if (work->next_smb2_rcv_hdr_off) {
else if (work->next_smb2_rcv_hdr_off)
len -= work->next_smb2_rcv_hdr_off;
len = round_up(len, 8);
}
if (check_smb2_hdr(hdr))
return 1;
......
......@@ -6,7 +6,6 @@
#include <linux/slab.h>
#include "glob.h"
#include "smb2pdu.h"
#include "auth.h"
#include "connection.h"
......@@ -199,7 +198,7 @@ void init_smb2_1_server(struct ksmbd_conn *conn)
conn->cmds = smb2_0_server_cmds;
conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
conn->max_credits = SMB2_MAX_CREDITS;
conn->signing_algorithm = SIGNING_ALG_HMAC_SHA256;
conn->signing_algorithm = SIGNING_ALG_HMAC_SHA256_LE;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
......@@ -217,7 +216,7 @@ void init_smb3_0_server(struct ksmbd_conn *conn)
conn->cmds = smb2_0_server_cmds;
conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
conn->max_credits = SMB2_MAX_CREDITS;
conn->signing_algorithm = SIGNING_ALG_AES_CMAC;
conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
......@@ -242,7 +241,7 @@ void init_smb3_02_server(struct ksmbd_conn *conn)
conn->cmds = smb2_0_server_cmds;
conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
conn->max_credits = SMB2_MAX_CREDITS;
conn->signing_algorithm = SIGNING_ALG_AES_CMAC;
conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
......@@ -267,7 +266,7 @@ int init_smb3_11_server(struct ksmbd_conn *conn)
conn->cmds = smb2_0_server_cmds;
conn->max_cmds = ARRAY_SIZE(smb2_0_server_cmds);
conn->max_credits = SMB2_MAX_CREDITS;
conn->signing_algorithm = SIGNING_ALG_AES_CMAC;
conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE;
if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES)
conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING;
......
......@@ -13,7 +13,6 @@
#include <linux/falloc.h>
#include "glob.h"
#include "smb2pdu.h"
#include "smbfsctl.h"
#include "oplock.h"
#include "smbacl.h"
......@@ -44,8 +43,8 @@ static void __wbuf(struct ksmbd_work *work, void **req, void **rsp)
*req = ksmbd_req_buf_next(work);
*rsp = ksmbd_resp_buf_next(work);
} else {
*req = work->request_buf;
*rsp = work->response_buf;
*req = smb2_get_msg(work->request_buf);
*rsp = smb2_get_msg(work->response_buf);
}
}
......@@ -93,13 +92,14 @@ struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn
*/
int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
{
struct smb2_hdr *req_hdr = work->request_buf;
struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
unsigned int cmd = le16_to_cpu(req_hdr->Command);
int tree_id;
work->tcon = NULL;
if (work->conn->ops->get_cmd_val(work) == SMB2_TREE_CONNECT_HE ||
work->conn->ops->get_cmd_val(work) == SMB2_CANCEL_HE ||
work->conn->ops->get_cmd_val(work) == SMB2_LOGOFF_HE) {
if (cmd == SMB2_TREE_CONNECT_HE ||
cmd == SMB2_CANCEL_HE ||
cmd == SMB2_LOGOFF_HE) {
ksmbd_debug(SMB, "skip to check tree connect request\n");
return 0;
}
......@@ -130,7 +130,7 @@ void smb2_set_err_rsp(struct ksmbd_work *work)
if (work->next_smb2_rcv_hdr_off)
err_rsp = ksmbd_resp_buf_next(work);
else
err_rsp = work->response_buf;
err_rsp = smb2_get_msg(work->response_buf);
if (err_rsp->hdr.Status != STATUS_STOPPED_ON_SYMLINK) {
err_rsp->StructureSize = SMB2_ERROR_STRUCTURE_SIZE2_LE;
......@@ -150,7 +150,7 @@ void smb2_set_err_rsp(struct ksmbd_work *work)
*/
bool is_smb2_neg_cmd(struct ksmbd_work *work)
{
struct smb2_hdr *hdr = work->request_buf;
struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
/* is it SMB2 header ? */
if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
......@@ -174,7 +174,7 @@ bool is_smb2_neg_cmd(struct ksmbd_work *work)
*/
bool is_smb2_rsp(struct ksmbd_work *work)
{
struct smb2_hdr *hdr = work->response_buf;
struct smb2_hdr *hdr = smb2_get_msg(work->response_buf);
/* is it SMB2 header ? */
if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
......@@ -200,7 +200,7 @@ u16 get_smb2_cmd_val(struct ksmbd_work *work)
if (work->next_smb2_rcv_hdr_off)
rcv_hdr = ksmbd_req_buf_next(work);
else
rcv_hdr = work->request_buf;
rcv_hdr = smb2_get_msg(work->request_buf);
return le16_to_cpu(rcv_hdr->Command);
}
......@@ -216,7 +216,7 @@ void set_smb2_rsp_status(struct ksmbd_work *work, __le32 err)
if (work->next_smb2_rcv_hdr_off)
rsp_hdr = ksmbd_resp_buf_next(work);
else
rsp_hdr = work->response_buf;
rsp_hdr = smb2_get_msg(work->response_buf);
rsp_hdr->Status = err;
smb2_set_err_rsp(work);
}
......@@ -237,13 +237,11 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
if (conn->need_neg == false)
return -EINVAL;
rsp_hdr = work->response_buf;
*(__be32 *)work->response_buf =
cpu_to_be32(conn->vals->header_size);
rsp_hdr = smb2_get_msg(work->response_buf);
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
rsp_hdr->smb2_buf_length =
cpu_to_be32(smb2_hdr_size_no_buflen(conn->vals));
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->CreditRequest = cpu_to_le16(2);
......@@ -256,7 +254,7 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
rsp_hdr->SessionId = 0;
memset(rsp_hdr->Signature, 0, 16);
rsp = work->response_buf;
rsp = smb2_get_msg(work->response_buf);
WARN_ON(ksmbd_conn_good(work));
......@@ -277,12 +275,12 @@ int init_smb2_neg_rsp(struct ksmbd_work *work)
rsp->SecurityBufferOffset = cpu_to_le16(128);
rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH);
ksmbd_copy_gss_neg_header(((char *)(&rsp->hdr) +
sizeof(rsp->hdr.smb2_buf_length)) +
ksmbd_copy_gss_neg_header((char *)(&rsp->hdr) +
le16_to_cpu(rsp->SecurityBufferOffset));
inc_rfc1001_len(rsp, sizeof(struct smb2_negotiate_rsp) -
sizeof(struct smb2_hdr) - sizeof(rsp->Buffer) +
AUTH_GSS_LENGTH);
inc_rfc1001_len(work->response_buf,
sizeof(struct smb2_negotiate_rsp) -
sizeof(struct smb2_hdr) - sizeof(rsp->Buffer) +
AUTH_GSS_LENGTH);
rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE;
if (server_conf.signing == KSMBD_CONFIG_OPT_MANDATORY)
rsp->SecurityMode |= SMB2_NEGOTIATE_SIGNING_REQUIRED_LE;
......@@ -387,8 +385,8 @@ static void init_chained_smb2_rsp(struct ksmbd_work *work)
next_hdr_offset = le32_to_cpu(req->NextCommand);
new_len = ALIGN(len, 8);
inc_rfc1001_len(work->response_buf, ((sizeof(struct smb2_hdr) - 4)
+ new_len - len));
inc_rfc1001_len(work->response_buf,
sizeof(struct smb2_hdr) + new_len - len);
rsp->NextCommand = cpu_to_le32(new_len);
work->next_smb2_rcv_hdr_off += next_hdr_offset;
......@@ -406,7 +404,7 @@ static void init_chained_smb2_rsp(struct ksmbd_work *work)
work->compound_fid = KSMBD_NO_FID;
work->compound_pfid = KSMBD_NO_FID;
}
memset((char *)rsp_hdr + 4, 0, sizeof(struct smb2_hdr) + 2);
memset((char *)rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
rsp_hdr->ProtocolId = SMB2_PROTO_NUMBER;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->Command = rcv_hdr->Command;
......@@ -432,7 +430,7 @@ static void init_chained_smb2_rsp(struct ksmbd_work *work)
*/
bool is_chained_smb2_message(struct ksmbd_work *work)
{
struct smb2_hdr *hdr = work->request_buf;
struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
unsigned int len, next_cmd;
if (hdr->ProtocolId != SMB2_PROTO_NUMBER)
......@@ -483,13 +481,13 @@ bool is_chained_smb2_message(struct ksmbd_work *work)
*/
int init_smb2_rsp_hdr(struct ksmbd_work *work)
{
struct smb2_hdr *rsp_hdr = work->response_buf;
struct smb2_hdr *rcv_hdr = work->request_buf;
struct smb2_hdr *rsp_hdr = smb2_get_msg(work->response_buf);
struct smb2_hdr *rcv_hdr = smb2_get_msg(work->request_buf);
struct ksmbd_conn *conn = work->conn;
memset(rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
rsp_hdr->smb2_buf_length =
cpu_to_be32(smb2_hdr_size_no_buflen(conn->vals));
*(__be32 *)work->response_buf =
cpu_to_be32(conn->vals->header_size);
rsp_hdr->ProtocolId = rcv_hdr->ProtocolId;
rsp_hdr->StructureSize = SMB2_HEADER_STRUCTURE_SIZE;
rsp_hdr->Command = rcv_hdr->Command;
......@@ -522,7 +520,7 @@ int init_smb2_rsp_hdr(struct ksmbd_work *work)
*/
int smb2_allocate_rsp_buf(struct ksmbd_work *work)
{
struct smb2_hdr *hdr = work->request_buf;
struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
size_t small_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
size_t large_sz = small_sz + work->conn->vals->max_trans_size;
size_t sz = small_sz;
......@@ -534,7 +532,7 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
if (cmd == SMB2_QUERY_INFO_HE) {
struct smb2_query_info_req *req;
req = work->request_buf;
req = smb2_get_msg(work->request_buf);
if (req->InfoType == SMB2_O_INFO_FILE &&
(req->FileInfoClass == FILE_FULL_EA_INFORMATION ||
req->FileInfoClass == FILE_ALL_INFORMATION))
......@@ -561,7 +559,7 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
*/
int smb2_check_user_session(struct ksmbd_work *work)
{
struct smb2_hdr *req_hdr = work->request_buf;
struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
struct ksmbd_conn *conn = work->conn;
unsigned int cmd = conn->ops->get_cmd_val(work);
unsigned long long sess_id;
......@@ -642,7 +640,7 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg)
struct ksmbd_conn *conn = work->conn;
int id;
rsp_hdr = work->response_buf;
rsp_hdr = smb2_get_msg(work->response_buf);
rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND;
id = ksmbd_acquire_async_msg_id(&conn->async_ida);
......@@ -674,7 +672,7 @@ void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status)
{
struct smb2_hdr *rsp_hdr;
rsp_hdr = work->response_buf;
rsp_hdr = smb2_get_msg(work->response_buf);
smb2_set_err_rsp(work);
rsp_hdr->Status = status;
......@@ -715,17 +713,17 @@ static int smb2_get_dos_mode(struct kstat *stat, int attribute)
int attr = 0;
if (S_ISDIR(stat->mode)) {
attr = ATTR_DIRECTORY |
(attribute & (ATTR_HIDDEN | ATTR_SYSTEM));
attr = FILE_ATTRIBUTE_DIRECTORY |
(attribute & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM));
} else {
attr = (attribute & 0x00005137) | ATTR_ARCHIVE;
attr &= ~(ATTR_DIRECTORY);
attr = (attribute & 0x00005137) | FILE_ATTRIBUTE_ARCHIVE;
attr &= ~(FILE_ATTRIBUTE_DIRECTORY);
if (S_ISREG(stat->mode) && (server_conf.share_fake_fscaps &
FILE_SUPPORTS_SPARSE_FILES))
attr |= ATTR_SPARSE;
attr |= FILE_ATTRIBUTE_SPARSE_FILE;
if (smb2_get_reparse_tag_special_file(stat->mode))
attr |= ATTR_REPARSE;
attr |= FILE_ATTRIBUTE_REPARSE_POINT;
}
return attr;
......@@ -753,16 +751,16 @@ static void build_encrypt_ctxt(struct smb2_encryption_neg_context *pneg_ctxt,
pneg_ctxt->Ciphers[0] = cipher_type;
}
static void build_compression_ctxt(struct smb2_compression_ctx *pneg_ctxt,
static void build_compression_ctxt(struct smb2_compression_capabilities_context *pneg_ctxt,
__le16 comp_algo)
{
pneg_ctxt->ContextType = SMB2_COMPRESSION_CAPABILITIES;
pneg_ctxt->DataLength =
cpu_to_le16(sizeof(struct smb2_compression_ctx)
cpu_to_le16(sizeof(struct smb2_compression_capabilities_context)
- sizeof(struct smb2_neg_context));
pneg_ctxt->Reserved = cpu_to_le32(0);
pneg_ctxt->CompressionAlgorithmCount = cpu_to_le16(1);
pneg_ctxt->Reserved1 = cpu_to_le32(0);
pneg_ctxt->Flags = cpu_to_le32(0);
pneg_ctxt->CompressionAlgorithms[0] = comp_algo;
}
......@@ -802,11 +800,11 @@ static void build_posix_ctxt(struct smb2_posix_neg_context *pneg_ctxt)
}
static void assemble_neg_contexts(struct ksmbd_conn *conn,
struct smb2_negotiate_rsp *rsp)
struct smb2_negotiate_rsp *rsp,
void *smb2_buf_len)
{
/* +4 is to account for the RFC1001 len field */
char *pneg_ctxt = (char *)rsp +
le32_to_cpu(rsp->NegotiateContextOffset) + 4;
le32_to_cpu(rsp->NegotiateContextOffset);
int neg_ctxt_cnt = 1;
int ctxt_size;
......@@ -815,7 +813,7 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
build_preauth_ctxt((struct smb2_preauth_neg_context *)pneg_ctxt,
conn->preauth_info->Preauth_HashId);
rsp->NegotiateContextCount = cpu_to_le16(neg_ctxt_cnt);
inc_rfc1001_len(rsp, AUTH_GSS_PADDING);
inc_rfc1001_len(smb2_buf_len, AUTH_GSS_PADDING);
ctxt_size = sizeof(struct smb2_preauth_neg_context);
/* Round to 8 byte boundary */
pneg_ctxt += round_up(sizeof(struct smb2_preauth_neg_context), 8);
......@@ -839,12 +837,12 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
ksmbd_debug(SMB,
"assemble SMB2_COMPRESSION_CAPABILITIES context\n");
/* Temporarily set to SMB3_COMPRESS_NONE */
build_compression_ctxt((struct smb2_compression_ctx *)pneg_ctxt,
build_compression_ctxt((struct smb2_compression_capabilities_context *)pneg_ctxt,
conn->compress_algorithm);
rsp->NegotiateContextCount = cpu_to_le16(++neg_ctxt_cnt);
ctxt_size += sizeof(struct smb2_compression_ctx) + 2;
ctxt_size += sizeof(struct smb2_compression_capabilities_context) + 2;
/* Round to 8 byte boundary */
pneg_ctxt += round_up(sizeof(struct smb2_compression_ctx) + 2,
pneg_ctxt += round_up(sizeof(struct smb2_compression_capabilities_context) + 2,
8);
}
......@@ -869,7 +867,7 @@ static void assemble_neg_contexts(struct ksmbd_conn *conn,
ctxt_size += sizeof(struct smb2_signing_capabilities) + 2;
}
inc_rfc1001_len(rsp, ctxt_size);
inc_rfc1001_len(smb2_buf_len, ctxt_size);
}
static __le32 decode_preauth_ctxt(struct ksmbd_conn *conn,
......@@ -918,7 +916,7 @@ static void decode_encrypt_ctxt(struct ksmbd_conn *conn,
}
static void decode_compress_ctxt(struct ksmbd_conn *conn,
struct smb2_compression_ctx *pneg_ctxt)
struct smb2_compression_capabilities_context *pneg_ctxt)
{
conn->compress_algorithm = SMB3_COMPRESS_NONE;
}
......@@ -939,8 +937,8 @@ static void decode_sign_cap_ctxt(struct ksmbd_conn *conn,
}
for (i = 0; i < sign_algo_cnt; i++) {
if (pneg_ctxt->SigningAlgorithms[i] == SIGNING_ALG_HMAC_SHA256 ||
pneg_ctxt->SigningAlgorithms[i] == SIGNING_ALG_AES_CMAC) {
if (pneg_ctxt->SigningAlgorithms[i] == SIGNING_ALG_HMAC_SHA256_LE ||
pneg_ctxt->SigningAlgorithms[i] == SIGNING_ALG_AES_CMAC_LE) {
ksmbd_debug(SMB, "Signing Algorithm ID = 0x%x\n",
pneg_ctxt->SigningAlgorithms[i]);
conn->signing_negotiated = true;
......@@ -952,14 +950,14 @@ static void decode_sign_cap_ctxt(struct ksmbd_conn *conn,
}
static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
struct smb2_negotiate_req *req)
struct smb2_negotiate_req *req,
int len_of_smb)
{
/* +4 is to account for the RFC1001 len field */
struct smb2_neg_context *pctx = (struct smb2_neg_context *)((char *)req + 4);
struct smb2_neg_context *pctx = (struct smb2_neg_context *)req;
int i = 0, len_of_ctxts;
int offset = le32_to_cpu(req->NegotiateContextOffset);
int neg_ctxt_cnt = le16_to_cpu(req->NegotiateContextCount);
int len_of_smb = be32_to_cpu(req->hdr.smb2_buf_length);
__le32 status = STATUS_INVALID_PARAMETER;
ksmbd_debug(SMB, "decoding %d negotiate contexts\n", neg_ctxt_cnt);
......@@ -1011,7 +1009,7 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
break;
decode_compress_ctxt(conn,
(struct smb2_compression_ctx *)pctx);
(struct smb2_compression_capabilities_context *)pctx);
} else if (pctx->ContextType == SMB2_NETNAME_NEGOTIATE_CONTEXT_ID) {
ksmbd_debug(SMB,
"deassemble SMB2_NETNAME_NEGOTIATE_CONTEXT_ID context\n");
......@@ -1044,8 +1042,8 @@ static __le32 deassemble_neg_contexts(struct ksmbd_conn *conn,
int smb2_handle_negotiate(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct smb2_negotiate_req *req = work->request_buf;
struct smb2_negotiate_rsp *rsp = work->response_buf;
struct smb2_negotiate_req *req = smb2_get_msg(work->request_buf);
struct smb2_negotiate_rsp *rsp = smb2_get_msg(work->response_buf);
int rc = 0;
unsigned int smb2_buf_len, smb2_neg_size;
__le32 status;
......@@ -1066,7 +1064,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
}
smb2_buf_len = get_rfc1002_len(work->request_buf);
smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects) - 4;
smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects);
if (smb2_neg_size > smb2_buf_len) {
rsp->hdr.Status = STATUS_INVALID_PARAMETER;
rc = -EINVAL;
......@@ -1115,7 +1113,8 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
goto err_out;
}
status = deassemble_neg_contexts(conn, req);
status = deassemble_neg_contexts(conn, req,
get_rfc1002_len(work->request_buf));
if (status != STATUS_SUCCESS) {
pr_err("deassemble_neg_contexts error(0x%x)\n",
status);
......@@ -1135,7 +1134,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
conn->preauth_info->Preauth_HashValue);
rsp->NegotiateContextOffset =
cpu_to_le32(OFFSET_OF_NEG_CONTEXT);
assemble_neg_contexts(conn, rsp);
assemble_neg_contexts(conn, rsp, work->response_buf);
break;
case SMB302_PROT_ID:
init_smb3_02_server(conn);
......@@ -1183,10 +1182,9 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
rsp->SecurityBufferOffset = cpu_to_le16(128);
rsp->SecurityBufferLength = cpu_to_le16(AUTH_GSS_LENGTH);
ksmbd_copy_gss_neg_header(((char *)(&rsp->hdr) +
sizeof(rsp->hdr.smb2_buf_length)) +
le16_to_cpu(rsp->SecurityBufferOffset));
inc_rfc1001_len(rsp, sizeof(struct smb2_negotiate_rsp) -
ksmbd_copy_gss_neg_header((char *)(&rsp->hdr) +
le16_to_cpu(rsp->SecurityBufferOffset));
inc_rfc1001_len(work->response_buf, sizeof(struct smb2_negotiate_rsp) -
sizeof(struct smb2_hdr) - sizeof(rsp->Buffer) +
AUTH_GSS_LENGTH);
rsp->SecurityMode = SMB2_NEGOTIATE_SIGNING_ENABLED_LE;
......@@ -1278,7 +1276,7 @@ static int ntlm_negotiate(struct ksmbd_work *work,
struct negotiate_message *negblob,
size_t negblob_len)
{
struct smb2_sess_setup_rsp *rsp = work->response_buf;
struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
struct challenge_message *chgblob;
unsigned char *spnego_blob = NULL;
u16 spnego_blob_len;
......@@ -1386,8 +1384,8 @@ static struct ksmbd_user *session_user(struct ksmbd_conn *conn,
static int ntlm_authenticate(struct ksmbd_work *work)
{
struct smb2_sess_setup_req *req = work->request_buf;
struct smb2_sess_setup_rsp *rsp = work->response_buf;
struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess = work->sess;
struct channel *chann = NULL;
......@@ -1410,7 +1408,7 @@ static int ntlm_authenticate(struct ksmbd_work *work)
memcpy((char *)&rsp->hdr.ProtocolId + sz, spnego_blob, spnego_blob_len);
rsp->SecurityBufferLength = cpu_to_le16(spnego_blob_len);
kfree(spnego_blob);
inc_rfc1001_len(rsp, spnego_blob_len - 1);
inc_rfc1001_len(work->response_buf, spnego_blob_len - 1);
}
user = session_user(conn, req);
......@@ -1522,8 +1520,8 @@ static int ntlm_authenticate(struct ksmbd_work *work)
#ifdef CONFIG_SMB_SERVER_KERBEROS5
static int krb5_authenticate(struct ksmbd_work *work)
{
struct smb2_sess_setup_req *req = work->request_buf;
struct smb2_sess_setup_rsp *rsp = work->response_buf;
struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess = work->sess;
char *in_blob, *out_blob;
......@@ -1538,8 +1536,7 @@ static int krb5_authenticate(struct ksmbd_work *work)
out_blob = (char *)&rsp->hdr.ProtocolId +
le16_to_cpu(rsp->SecurityBufferOffset);
out_len = work->response_sz -
offsetof(struct smb2_hdr, smb2_buf_length) -
le16_to_cpu(rsp->SecurityBufferOffset);
(le16_to_cpu(rsp->SecurityBufferOffset) + 4);
/* Check previous session */
prev_sess_id = le64_to_cpu(req->PreviousSessionId);
......@@ -1556,7 +1553,7 @@ static int krb5_authenticate(struct ksmbd_work *work)
return -EINVAL;
}
rsp->SecurityBufferLength = cpu_to_le16(out_len);
inc_rfc1001_len(rsp, out_len - 1);
inc_rfc1001_len(work->response_buf, out_len - 1);
if ((conn->sign || server_conf.enforced_signing) ||
(req->SecurityMode & SMB2_NEGOTIATE_SIGNING_REQUIRED))
......@@ -1612,8 +1609,8 @@ static int krb5_authenticate(struct ksmbd_work *work)
int smb2_sess_setup(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct smb2_sess_setup_req *req = work->request_buf;
struct smb2_sess_setup_rsp *rsp = work->response_buf;
struct smb2_sess_setup_req *req = smb2_get_msg(work->request_buf);
struct smb2_sess_setup_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_session *sess;
struct negotiate_message *negblob;
unsigned int negblob_len, negblob_off;
......@@ -1625,7 +1622,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
rsp->SessionFlags = 0;
rsp->SecurityBufferOffset = cpu_to_le16(72);
rsp->SecurityBufferLength = 0;
inc_rfc1001_len(rsp, 9);
inc_rfc1001_len(work->response_buf, 9);
if (!req->hdr.SessionId) {
sess = ksmbd_smb2_session_create();
......@@ -1699,7 +1696,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
negblob_off = le16_to_cpu(req->SecurityBufferOffset);
negblob_len = le16_to_cpu(req->SecurityBufferLength);
if (negblob_off < (offsetof(struct smb2_sess_setup_req, Buffer) - 4) ||
if (negblob_off < offsetof(struct smb2_sess_setup_req, Buffer) ||
negblob_len < offsetof(struct negotiate_message, NegotiateFlags))
return -EINVAL;
......@@ -1739,7 +1736,8 @@ int smb2_sess_setup(struct ksmbd_work *work)
* Note: here total size -1 is done as an
* adjustment for 0 size blob
*/
inc_rfc1001_len(rsp, le16_to_cpu(rsp->SecurityBufferLength) - 1);
inc_rfc1001_len(work->response_buf,
le16_to_cpu(rsp->SecurityBufferLength) - 1);
} else if (negblob->MessageType == NtLmAuthenticate) {
rc = ntlm_authenticate(work);
......@@ -1828,8 +1826,8 @@ int smb2_sess_setup(struct ksmbd_work *work)
int smb2_tree_connect(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct smb2_tree_connect_req *req = work->request_buf;
struct smb2_tree_connect_rsp *rsp = work->response_buf;
struct smb2_tree_connect_req *req = smb2_get_msg(work->request_buf);
struct smb2_tree_connect_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_session *sess = work->sess;
char *treename = NULL, *name = NULL;
struct ksmbd_tree_conn_status status;
......@@ -1894,7 +1892,7 @@ int smb2_tree_connect(struct ksmbd_work *work)
rsp->Reserved = 0;
/* default manual caching */
rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING;
inc_rfc1001_len(rsp, 16);
inc_rfc1001_len(work->response_buf, 16);
if (!IS_ERR(treename))
kfree(treename);
......@@ -1999,17 +1997,18 @@ static int smb2_create_open_flags(bool file_present, __le32 access,
*/
int smb2_tree_disconnect(struct ksmbd_work *work)
{
struct smb2_tree_disconnect_rsp *rsp = work->response_buf;
struct smb2_tree_disconnect_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_session *sess = work->sess;
struct ksmbd_tree_connect *tcon = work->tcon;
rsp->StructureSize = cpu_to_le16(4);
inc_rfc1001_len(rsp, 4);
inc_rfc1001_len(work->response_buf, 4);
ksmbd_debug(SMB, "request\n");
if (!tcon) {
struct smb2_tree_disconnect_req *req = work->request_buf;
struct smb2_tree_disconnect_req *req =
smb2_get_msg(work->request_buf);
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
......@@ -2031,11 +2030,11 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
int smb2_session_logoff(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct smb2_logoff_rsp *rsp = work->response_buf;
struct smb2_logoff_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_session *sess = work->sess;
rsp->StructureSize = cpu_to_le16(4);
inc_rfc1001_len(rsp, 4);
inc_rfc1001_len(work->response_buf, 4);
ksmbd_debug(SMB, "request\n");
......@@ -2048,7 +2047,7 @@ int smb2_session_logoff(struct ksmbd_work *work)
ksmbd_conn_wait_idle(conn);
if (ksmbd_tree_conn_session_logoff(sess)) {
struct smb2_logoff_req *req = work->request_buf;
struct smb2_logoff_req *req = smb2_get_msg(work->request_buf);
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
......@@ -2075,8 +2074,8 @@ int smb2_session_logoff(struct ksmbd_work *work)
*/
static noinline int create_smb2_pipe(struct ksmbd_work *work)
{
struct smb2_create_rsp *rsp = work->response_buf;
struct smb2_create_req *req = work->request_buf;
struct smb2_create_rsp *rsp = smb2_get_msg(work->response_buf);
struct smb2_create_req *req = smb2_get_msg(work->request_buf);
int id;
int err;
char *name;
......@@ -2099,7 +2098,7 @@ static noinline int create_smb2_pipe(struct ksmbd_work *work)
rsp->hdr.Status = STATUS_SUCCESS;
rsp->StructureSize = cpu_to_le16(89);
rsp->OplockLevel = SMB2_OPLOCK_LEVEL_NONE;
rsp->Reserved = 0;
rsp->Flags = 0;
rsp->CreateAction = cpu_to_le32(FILE_OPENED);
rsp->CreationTime = cpu_to_le64(0);
......@@ -2107,14 +2106,14 @@ static noinline int create_smb2_pipe(struct ksmbd_work *work)
rsp->ChangeTime = cpu_to_le64(0);
rsp->AllocationSize = cpu_to_le64(0);
rsp->EndofFile = cpu_to_le64(0);
rsp->FileAttributes = ATTR_NORMAL_LE;
rsp->FileAttributes = FILE_ATTRIBUTE_NORMAL_LE;
rsp->Reserved2 = 0;
rsp->VolatileFileId = cpu_to_le64(id);
rsp->PersistentFileId = 0;
rsp->CreateContextsOffset = 0;
rsp->CreateContextsLength = 0;
inc_rfc1001_len(rsp, 88); /* StructureSize - 1*/
inc_rfc1001_len(work->response_buf, 88); /* StructureSize - 1*/
kfree(name);
return 0;
......@@ -2353,7 +2352,7 @@ static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon,
struct xattr_dos_attrib da;
int rc;
fp->f_ci->m_fattr &= ~(ATTR_HIDDEN_LE | ATTR_SYSTEM_LE);
fp->f_ci->m_fattr &= ~(FILE_ATTRIBUTE_HIDDEN_LE | FILE_ATTRIBUTE_SYSTEM_LE);
/* get FileAttributes from XATTR_NAME_DOS_ATTRIBUTE */
if (!test_share_config_flag(tcon->share_conf,
......@@ -2463,7 +2462,7 @@ int smb2_open(struct ksmbd_work *work)
struct ksmbd_session *sess = work->sess;
struct ksmbd_tree_connect *tcon = work->tcon;
struct smb2_create_req *req;
struct smb2_create_rsp *rsp, *rsp_org;
struct smb2_create_rsp *rsp;
struct path path;
struct ksmbd_share_config *share = tcon->share_conf;
struct ksmbd_file *fp = NULL;
......@@ -2489,7 +2488,6 @@ int smb2_open(struct ksmbd_work *work)
umode_t posix_mode = 0;
__le32 daccess, maximal_access = 0;
rsp_org = work->response_buf;
WORK_BUFFERS(work, req, rsp);
if (req->hdr.NextCommand && !work->next_smb2_rcv_hdr_off &&
......@@ -2559,7 +2557,7 @@ int smb2_open(struct ksmbd_work *work)
if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE)
lc = parse_lease_state(req);
if (le32_to_cpu(req->ImpersonationLevel) > le32_to_cpu(IL_DELEGATE_LE)) {
if (le32_to_cpu(req->ImpersonationLevel) > le32_to_cpu(IL_DELEGATE)) {
pr_err("Invalid impersonationlevel : 0x%x\n",
le32_to_cpu(req->ImpersonationLevel));
rc = -EIO;
......@@ -2567,7 +2565,7 @@ int smb2_open(struct ksmbd_work *work)
goto err_out1;
}
if (req->CreateOptions && !(req->CreateOptions & CREATE_OPTIONS_MASK)) {
if (req->CreateOptions && !(req->CreateOptions & CREATE_OPTIONS_MASK_LE)) {
pr_err("Invalid create options : 0x%x\n",
le32_to_cpu(req->CreateOptions));
rc = -EINVAL;
......@@ -2609,7 +2607,7 @@ int smb2_open(struct ksmbd_work *work)
goto err_out1;
}
if (req->FileAttributes && !(req->FileAttributes & ATTR_MASK_LE)) {
if (req->FileAttributes && !(req->FileAttributes & FILE_ATTRIBUTE_MASK_LE)) {
pr_err("Invalid file attribute : 0x%x\n",
le32_to_cpu(req->FileAttributes));
rc = -EINVAL;
......@@ -2740,7 +2738,7 @@ int smb2_open(struct ksmbd_work *work)
}
if (req->CreateOptions & FILE_DIRECTORY_FILE_LE &&
req->FileAttributes & ATTR_NORMAL_LE) {
req->FileAttributes & FILE_ATTRIBUTE_NORMAL_LE) {
rsp->hdr.Status = STATUS_NOT_A_DIRECTORY;
rc = -EIO;
}
......@@ -3119,7 +3117,7 @@ int smb2_open(struct ksmbd_work *work)
opinfo = rcu_dereference(fp->f_opinfo);
rsp->OplockLevel = opinfo != NULL ? opinfo->level : 0;
rcu_read_unlock();
rsp->Reserved = 0;
rsp->Flags = 0;
rsp->CreateAction = cpu_to_le32(file_info);
rsp->CreationTime = cpu_to_le64(fp->create_time);
time = ksmbd_UnixTimeToNT(stat.atime);
......@@ -3140,7 +3138,7 @@ int smb2_open(struct ksmbd_work *work)
rsp->CreateContextsOffset = 0;
rsp->CreateContextsLength = 0;
inc_rfc1001_len(rsp_org, 88); /* StructureSize - 1*/
inc_rfc1001_len(work->response_buf, 88); /* StructureSize - 1*/
/* If lease is request send lease context response */
if (opinfo && opinfo->is_lease) {
......@@ -3155,7 +3153,8 @@ int smb2_open(struct ksmbd_work *work)
create_lease_buf(rsp->Buffer, opinfo->o_lease);
le32_add_cpu(&rsp->CreateContextsLength,
conn->vals->create_lease_size);
inc_rfc1001_len(rsp_org, conn->vals->create_lease_size);
inc_rfc1001_len(work->response_buf,
conn->vals->create_lease_size);
next_ptr = &lease_ccontext->Next;
next_off = conn->vals->create_lease_size;
}
......@@ -3175,7 +3174,8 @@ int smb2_open(struct ksmbd_work *work)
le32_to_cpu(maximal_access));
le32_add_cpu(&rsp->CreateContextsLength,
conn->vals->create_mxac_size);
inc_rfc1001_len(rsp_org, conn->vals->create_mxac_size);
inc_rfc1001_len(work->response_buf,
conn->vals->create_mxac_size);
if (next_ptr)
*next_ptr = cpu_to_le32(next_off);
next_ptr = &mxac_ccontext->Next;
......@@ -3193,7 +3193,8 @@ int smb2_open(struct ksmbd_work *work)
stat.ino, tcon->id);
le32_add_cpu(&rsp->CreateContextsLength,
conn->vals->create_disk_id_size);
inc_rfc1001_len(rsp_org, conn->vals->create_disk_id_size);
inc_rfc1001_len(work->response_buf,
conn->vals->create_disk_id_size);
if (next_ptr)
*next_ptr = cpu_to_le32(next_off);
next_ptr = &disk_id_ccontext->Next;
......@@ -3207,15 +3208,15 @@ int smb2_open(struct ksmbd_work *work)
fp);
le32_add_cpu(&rsp->CreateContextsLength,
conn->vals->create_posix_size);
inc_rfc1001_len(rsp_org, conn->vals->create_posix_size);
inc_rfc1001_len(work->response_buf,
conn->vals->create_posix_size);
if (next_ptr)
*next_ptr = cpu_to_le32(next_off);
}
if (contxt_cnt > 0) {
rsp->CreateContextsOffset =
cpu_to_le32(offsetof(struct smb2_create_rsp, Buffer)
- 4);
cpu_to_le32(offsetof(struct smb2_create_rsp, Buffer));
}
err_out:
......@@ -3422,9 +3423,9 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
ffdinfo->EaSize =
smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
if (ffdinfo->EaSize)
ffdinfo->ExtFileAttributes = ATTR_REPARSE_POINT_LE;
ffdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE;
if (d_info->hide_dot_file && d_info->name[0] == '.')
ffdinfo->ExtFileAttributes |= ATTR_HIDDEN_LE;
ffdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
memcpy(ffdinfo->FileName, conv_name, conv_len);
ffdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
break;
......@@ -3438,11 +3439,11 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
fbdinfo->EaSize =
smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
if (fbdinfo->EaSize)
fbdinfo->ExtFileAttributes = ATTR_REPARSE_POINT_LE;
fbdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE;
fbdinfo->ShortNameLength = 0;
fbdinfo->Reserved = 0;
if (d_info->hide_dot_file && d_info->name[0] == '.')
fbdinfo->ExtFileAttributes |= ATTR_HIDDEN_LE;
fbdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
memcpy(fbdinfo->FileName, conv_name, conv_len);
fbdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
break;
......@@ -3454,7 +3455,7 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
fdinfo = (struct file_directory_info *)kstat;
fdinfo->FileNameLength = cpu_to_le32(conv_len);
if (d_info->hide_dot_file && d_info->name[0] == '.')
fdinfo->ExtFileAttributes |= ATTR_HIDDEN_LE;
fdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
memcpy(fdinfo->FileName, conv_name, conv_len);
fdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
break;
......@@ -3478,11 +3479,11 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
dinfo->EaSize =
smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
if (dinfo->EaSize)
dinfo->ExtFileAttributes = ATTR_REPARSE_POINT_LE;
dinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE;
dinfo->Reserved = 0;
dinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino);
if (d_info->hide_dot_file && d_info->name[0] == '.')
dinfo->ExtFileAttributes |= ATTR_HIDDEN_LE;
dinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
memcpy(dinfo->FileName, conv_name, conv_len);
dinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
break;
......@@ -3496,13 +3497,13 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
fibdinfo->EaSize =
smb2_get_reparse_tag_special_file(ksmbd_kstat->kstat->mode);
if (fibdinfo->EaSize)
fibdinfo->ExtFileAttributes = ATTR_REPARSE_POINT_LE;
fibdinfo->ExtFileAttributes = FILE_ATTRIBUTE_REPARSE_POINT_LE;
fibdinfo->UniqueId = cpu_to_le64(ksmbd_kstat->kstat->ino);
fibdinfo->ShortNameLength = 0;
fibdinfo->Reserved = 0;
fibdinfo->Reserved2 = cpu_to_le16(0);
if (d_info->hide_dot_file && d_info->name[0] == '.')
fibdinfo->ExtFileAttributes |= ATTR_HIDDEN_LE;
fibdinfo->ExtFileAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
memcpy(fibdinfo->FileName, conv_name, conv_len);
fibdinfo->NextEntryOffset = cpu_to_le32(next_entry_offset);
break;
......@@ -3528,9 +3529,10 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
posix_info->Mode = cpu_to_le32(ksmbd_kstat->kstat->mode);
posix_info->Inode = cpu_to_le64(ksmbd_kstat->kstat->ino);
posix_info->DosAttributes =
S_ISDIR(ksmbd_kstat->kstat->mode) ? ATTR_DIRECTORY_LE : ATTR_ARCHIVE_LE;
S_ISDIR(ksmbd_kstat->kstat->mode) ?
FILE_ATTRIBUTE_DIRECTORY_LE : FILE_ATTRIBUTE_ARCHIVE_LE;
if (d_info->hide_dot_file && d_info->name[0] == '.')
posix_info->DosAttributes |= ATTR_HIDDEN_LE;
posix_info->DosAttributes |= FILE_ATTRIBUTE_HIDDEN_LE;
id_to_sid(from_kuid_munged(&init_user_ns, ksmbd_kstat->kstat->uid),
SIDNFS_USER, (struct smb_sid *)&posix_info->SidBuffer[0]);
id_to_sid(from_kgid_munged(&init_user_ns, ksmbd_kstat->kstat->gid),
......@@ -3816,7 +3818,7 @@ int smb2_query_dir(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct smb2_query_directory_req *req;
struct smb2_query_directory_rsp *rsp, *rsp_org;
struct smb2_query_directory_rsp *rsp;
struct ksmbd_share_config *share = work->tcon->share_conf;
struct ksmbd_file *dir_fp = NULL;
struct ksmbd_dir_info d_info;
......@@ -3826,7 +3828,6 @@ int smb2_query_dir(struct ksmbd_work *work)
int buffer_sz;
struct smb2_query_dir_private query_dir_private = {NULL, };
rsp_org = work->response_buf;
WORK_BUFFERS(work, req, rsp);
if (ksmbd_override_fsids(work)) {
......@@ -3947,7 +3948,7 @@ int smb2_query_dir(struct ksmbd_work *work)
rsp->OutputBufferOffset = cpu_to_le16(0);
rsp->OutputBufferLength = cpu_to_le32(0);
rsp->Buffer[0] = 0;
inc_rfc1001_len(rsp_org, 9);
inc_rfc1001_len(work->response_buf, 9);
} else {
((struct file_directory_info *)
((char *)rsp->Buffer + d_info.last_entry_offset))
......@@ -3956,7 +3957,7 @@ int smb2_query_dir(struct ksmbd_work *work)
rsp->StructureSize = cpu_to_le16(9);
rsp->OutputBufferOffset = cpu_to_le16(72);
rsp->OutputBufferLength = cpu_to_le32(d_info.data_count);
inc_rfc1001_len(rsp_org, 8 + d_info.data_count);
inc_rfc1001_len(work->response_buf, 8 + d_info.data_count);
}
kfree(srch_ptr);
......@@ -3999,26 +4000,28 @@ int smb2_query_dir(struct ksmbd_work *work)
* Return: 0 on success, otherwise error
*/
static int buffer_check_err(int reqOutputBufferLength,
struct smb2_query_info_rsp *rsp, int infoclass_size)
struct smb2_query_info_rsp *rsp,
void *rsp_org, int infoclass_size)
{
if (reqOutputBufferLength < le32_to_cpu(rsp->OutputBufferLength)) {
if (reqOutputBufferLength < infoclass_size) {
pr_err("Invalid Buffer Size Requested\n");
rsp->hdr.Status = STATUS_INFO_LENGTH_MISMATCH;
rsp->hdr.smb2_buf_length = cpu_to_be32(sizeof(struct smb2_hdr) - 4);
*(__be32 *)rsp_org = cpu_to_be32(sizeof(struct smb2_hdr));
return -EINVAL;
}
ksmbd_debug(SMB, "Buffer Overflow\n");
rsp->hdr.Status = STATUS_BUFFER_OVERFLOW;
rsp->hdr.smb2_buf_length = cpu_to_be32(sizeof(struct smb2_hdr) - 4 +
*(__be32 *)rsp_org = cpu_to_be32(sizeof(struct smb2_hdr) +
reqOutputBufferLength);
rsp->OutputBufferLength = cpu_to_le32(reqOutputBufferLength);
}
return 0;
}
static void get_standard_info_pipe(struct smb2_query_info_rsp *rsp)
static void get_standard_info_pipe(struct smb2_query_info_rsp *rsp,
void *rsp_org)
{
struct smb2_file_standard_info *sinfo;
......@@ -4031,10 +4034,11 @@ static void get_standard_info_pipe(struct smb2_query_info_rsp *rsp)
sinfo->Directory = 0;
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_standard_info));
inc_rfc1001_len(rsp, sizeof(struct smb2_file_standard_info));
inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_standard_info));
}
static void get_internal_info_pipe(struct smb2_query_info_rsp *rsp, u64 num)
static void get_internal_info_pipe(struct smb2_query_info_rsp *rsp, u64 num,
void *rsp_org)
{
struct smb2_file_internal_info *file_info;
......@@ -4044,12 +4048,13 @@ static void get_internal_info_pipe(struct smb2_query_info_rsp *rsp, u64 num)
file_info->IndexNumber = cpu_to_le64(num | (1ULL << 63));
rsp->OutputBufferLength =
cpu_to_le32(sizeof(struct smb2_file_internal_info));
inc_rfc1001_len(rsp, sizeof(struct smb2_file_internal_info));
inc_rfc1001_len(rsp_org, sizeof(struct smb2_file_internal_info));
}
static int smb2_get_info_file_pipe(struct ksmbd_session *sess,
struct smb2_query_info_req *req,
struct smb2_query_info_rsp *rsp)
struct smb2_query_info_rsp *rsp,
void *rsp_org)
{
u64 id;
int rc;
......@@ -4067,14 +4072,16 @@ static int smb2_get_info_file_pipe(struct ksmbd_session *sess,
switch (req->FileInfoClass) {
case FILE_STANDARD_INFORMATION:
get_standard_info_pipe(rsp);
get_standard_info_pipe(rsp, rsp_org);
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
rsp, FILE_STANDARD_INFORMATION_SIZE);
rsp, rsp_org,
FILE_STANDARD_INFORMATION_SIZE);
break;
case FILE_INTERNAL_INFORMATION:
get_internal_info_pipe(rsp, id);
get_internal_info_pipe(rsp, id, rsp_org);
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
rsp, FILE_INTERNAL_INFORMATION_SIZE);
rsp, rsp_org,
FILE_INTERNAL_INFORMATION_SIZE);
break;
default:
ksmbd_debug(SMB, "smb2_info_file_pipe for %u not supported\n",
......@@ -4688,7 +4695,7 @@ static int find_file_posix_info(struct smb2_query_info_rsp *rsp,
static int smb2_get_info_file(struct ksmbd_work *work,
struct smb2_query_info_req *req,
struct smb2_query_info_rsp *rsp, void *rsp_org)
struct smb2_query_info_rsp *rsp)
{
struct ksmbd_file *fp;
int fileinfoclass = 0;
......@@ -4699,7 +4706,8 @@ static int smb2_get_info_file(struct ksmbd_work *work,
if (test_share_config_flag(work->tcon->share_conf,
KSMBD_SHARE_FLAG_PIPE)) {
/* smb2 info file called for pipe */
return smb2_get_info_file_pipe(work->sess, req, rsp);
return smb2_get_info_file_pipe(work->sess, req, rsp,
work->response_buf);
}
if (work->next_smb2_rcv_hdr_off) {
......@@ -4724,77 +4732,77 @@ static int smb2_get_info_file(struct ksmbd_work *work,
switch (fileinfoclass) {
case FILE_ACCESS_INFORMATION:
get_file_access_info(rsp, fp, rsp_org);
get_file_access_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_ACCESS_INFORMATION_SIZE;
break;
case FILE_BASIC_INFORMATION:
rc = get_file_basic_info(rsp, fp, rsp_org);
rc = get_file_basic_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_BASIC_INFORMATION_SIZE;
break;
case FILE_STANDARD_INFORMATION:
get_file_standard_info(rsp, fp, rsp_org);
get_file_standard_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_STANDARD_INFORMATION_SIZE;
break;
case FILE_ALIGNMENT_INFORMATION:
get_file_alignment_info(rsp, rsp_org);
get_file_alignment_info(rsp, work->response_buf);
file_infoclass_size = FILE_ALIGNMENT_INFORMATION_SIZE;
break;
case FILE_ALL_INFORMATION:
rc = get_file_all_info(work, rsp, fp, rsp_org);
rc = get_file_all_info(work, rsp, fp, work->response_buf);
file_infoclass_size = FILE_ALL_INFORMATION_SIZE;
break;
case FILE_ALTERNATE_NAME_INFORMATION:
get_file_alternate_info(work, rsp, fp, rsp_org);
get_file_alternate_info(work, rsp, fp, work->response_buf);
file_infoclass_size = FILE_ALTERNATE_NAME_INFORMATION_SIZE;
break;
case FILE_STREAM_INFORMATION:
get_file_stream_info(work, rsp, fp, rsp_org);
get_file_stream_info(work, rsp, fp, work->response_buf);
file_infoclass_size = FILE_STREAM_INFORMATION_SIZE;
break;
case FILE_INTERNAL_INFORMATION:
get_file_internal_info(rsp, fp, rsp_org);
get_file_internal_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_INTERNAL_INFORMATION_SIZE;
break;
case FILE_NETWORK_OPEN_INFORMATION:
rc = get_file_network_open_info(rsp, fp, rsp_org);
rc = get_file_network_open_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_NETWORK_OPEN_INFORMATION_SIZE;
break;
case FILE_EA_INFORMATION:
get_file_ea_info(rsp, rsp_org);
get_file_ea_info(rsp, work->response_buf);
file_infoclass_size = FILE_EA_INFORMATION_SIZE;
break;
case FILE_FULL_EA_INFORMATION:
rc = smb2_get_ea(work, fp, req, rsp, rsp_org);
rc = smb2_get_ea(work, fp, req, rsp, work->response_buf);
file_infoclass_size = FILE_FULL_EA_INFORMATION_SIZE;
break;
case FILE_POSITION_INFORMATION:
get_file_position_info(rsp, fp, rsp_org);
get_file_position_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_POSITION_INFORMATION_SIZE;
break;
case FILE_MODE_INFORMATION:
get_file_mode_info(rsp, fp, rsp_org);
get_file_mode_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_MODE_INFORMATION_SIZE;
break;
case FILE_COMPRESSION_INFORMATION:
get_file_compression_info(rsp, fp, rsp_org);
get_file_compression_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_COMPRESSION_INFORMATION_SIZE;
break;
case FILE_ATTRIBUTE_TAG_INFORMATION:
rc = get_file_attribute_tag_info(rsp, fp, rsp_org);
rc = get_file_attribute_tag_info(rsp, fp, work->response_buf);
file_infoclass_size = FILE_ATTRIBUTE_TAG_INFORMATION_SIZE;
break;
case SMB_FIND_FILE_POSIX_INFO:
......@@ -4802,7 +4810,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
pr_err("client doesn't negotiate with SMB3.1.1 POSIX Extensions\n");
rc = -EOPNOTSUPP;
} else {
rc = find_file_posix_info(rsp, fp, rsp_org);
rc = find_file_posix_info(rsp, fp, work->response_buf);
file_infoclass_size = sizeof(struct smb311_posix_qinfo);
}
break;
......@@ -4813,7 +4821,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
}
if (!rc)
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
rsp,
rsp, work->response_buf,
file_infoclass_size);
ksmbd_fd_put(work, fp);
return rc;
......@@ -4821,7 +4829,7 @@ static int smb2_get_info_file(struct ksmbd_work *work,
static int smb2_get_info_filesystem(struct ksmbd_work *work,
struct smb2_query_info_req *req,
struct smb2_query_info_rsp *rsp, void *rsp_org)
struct smb2_query_info_rsp *rsp)
{
struct ksmbd_session *sess = work->sess;
struct ksmbd_conn *conn = sess->conn;
......@@ -4857,7 +4865,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->DeviceType = cpu_to_le32(stfs.f_type);
info->DeviceCharacteristics = cpu_to_le32(0x00000020);
rsp->OutputBufferLength = cpu_to_le32(8);
inc_rfc1001_len(rsp_org, 8);
inc_rfc1001_len(work->response_buf, 8);
fs_infoclass_size = FS_DEVICE_INFORMATION_SIZE;
break;
}
......@@ -4883,7 +4891,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->FileSystemNameLen = cpu_to_le32(len);
sz = sizeof(struct filesystem_attribute_info) - 2 + len;
rsp->OutputBufferLength = cpu_to_le32(sz);
inc_rfc1001_len(rsp_org, sz);
inc_rfc1001_len(work->response_buf, sz);
fs_infoclass_size = FS_ATTRIBUTE_INFORMATION_SIZE;
break;
}
......@@ -4891,11 +4899,18 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
{
struct filesystem_vol_info *info;
size_t sz;
unsigned int serial_crc = 0;
info = (struct filesystem_vol_info *)(rsp->Buffer);
info->VolumeCreationTime = 0;
serial_crc = crc32_le(serial_crc, share->name,
strlen(share->name));
serial_crc = crc32_le(serial_crc, share->path,
strlen(share->path));
serial_crc = crc32_le(serial_crc, ksmbd_netbios_name(),
strlen(ksmbd_netbios_name()));
/* Taking dummy value of serial number*/
info->SerialNumber = cpu_to_le32(0xbc3ac512);
info->SerialNumber = cpu_to_le32(serial_crc);
len = smbConvertToUTF16((__le16 *)info->VolumeLabel,
share->name, PATH_MAX,
conn->local_nls, 0);
......@@ -4904,7 +4919,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->Reserved = 0;
sz = sizeof(struct filesystem_vol_info) - 2 + len;
rsp->OutputBufferLength = cpu_to_le32(sz);
inc_rfc1001_len(rsp_org, sz);
inc_rfc1001_len(work->response_buf, sz);
fs_infoclass_size = FS_VOLUME_INFORMATION_SIZE;
break;
}
......@@ -4918,7 +4933,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->SectorsPerAllocationUnit = cpu_to_le32(1);
info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
rsp->OutputBufferLength = cpu_to_le32(24);
inc_rfc1001_len(rsp_org, 24);
inc_rfc1001_len(work->response_buf, 24);
fs_infoclass_size = FS_SIZE_INFORMATION_SIZE;
break;
}
......@@ -4935,7 +4950,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->SectorsPerAllocationUnit = cpu_to_le32(1);
info->BytesPerSector = cpu_to_le32(stfs.f_bsize);
rsp->OutputBufferLength = cpu_to_le32(32);
inc_rfc1001_len(rsp_org, 32);
inc_rfc1001_len(work->response_buf, 32);
fs_infoclass_size = FS_FULL_SIZE_INFORMATION_SIZE;
break;
}
......@@ -4956,7 +4971,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->extended_info.rel_date = 0;
memcpy(info->extended_info.version_string, "1.1.0", strlen("1.1.0"));
rsp->OutputBufferLength = cpu_to_le32(64);
inc_rfc1001_len(rsp_org, 64);
inc_rfc1001_len(work->response_buf, 64);
fs_infoclass_size = FS_OBJECT_ID_INFORMATION_SIZE;
break;
}
......@@ -4977,7 +4992,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->ByteOffsetForSectorAlignment = 0;
info->ByteOffsetForPartitionAlignment = 0;
rsp->OutputBufferLength = cpu_to_le32(28);
inc_rfc1001_len(rsp_org, 28);
inc_rfc1001_len(work->response_buf, 28);
fs_infoclass_size = FS_SECTOR_SIZE_INFORMATION_SIZE;
break;
}
......@@ -4999,7 +5014,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->DefaultQuotaLimit = cpu_to_le64(SMB2_NO_FID);
info->Padding = 0;
rsp->OutputBufferLength = cpu_to_le32(48);
inc_rfc1001_len(rsp_org, 48);
inc_rfc1001_len(work->response_buf, 48);
fs_infoclass_size = FS_CONTROL_INFORMATION_SIZE;
break;
}
......@@ -5020,7 +5035,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
info->TotalFileNodes = cpu_to_le64(stfs.f_files);
info->FreeFileNodes = cpu_to_le64(stfs.f_ffree);
rsp->OutputBufferLength = cpu_to_le32(56);
inc_rfc1001_len(rsp_org, 56);
inc_rfc1001_len(work->response_buf, 56);
fs_infoclass_size = FS_POSIX_INFORMATION_SIZE;
}
break;
......@@ -5030,7 +5045,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
return -EOPNOTSUPP;
}
rc = buffer_check_err(le32_to_cpu(req->OutputBufferLength),
rsp,
rsp, work->response_buf,
fs_infoclass_size);
path_put(&path);
return rc;
......@@ -5038,7 +5053,7 @@ static int smb2_get_info_filesystem(struct ksmbd_work *work,
static int smb2_get_info_sec(struct ksmbd_work *work,
struct smb2_query_info_req *req,
struct smb2_query_info_rsp *rsp, void *rsp_org)
struct smb2_query_info_rsp *rsp)
{
struct ksmbd_file *fp;
struct user_namespace *user_ns;
......@@ -5065,7 +5080,7 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
secdesclen = sizeof(struct smb_ntsd);
rsp->OutputBufferLength = cpu_to_le32(secdesclen);
inc_rfc1001_len(rsp_org, secdesclen);
inc_rfc1001_len(work->response_buf, secdesclen);
return 0;
}
......@@ -5107,7 +5122,7 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
return rc;
rsp->OutputBufferLength = cpu_to_le32(secdesclen);
inc_rfc1001_len(rsp_org, secdesclen);
inc_rfc1001_len(work->response_buf, secdesclen);
return 0;
}
......@@ -5120,10 +5135,9 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
int smb2_query_info(struct ksmbd_work *work)
{
struct smb2_query_info_req *req;
struct smb2_query_info_rsp *rsp, *rsp_org;
struct smb2_query_info_rsp *rsp;
int rc = 0;
rsp_org = work->response_buf;
WORK_BUFFERS(work, req, rsp);
ksmbd_debug(SMB, "GOT query info request\n");
......@@ -5131,15 +5145,15 @@ int smb2_query_info(struct ksmbd_work *work)
switch (req->InfoType) {
case SMB2_O_INFO_FILE:
ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILE\n");
rc = smb2_get_info_file(work, req, rsp, (void *)rsp_org);
rc = smb2_get_info_file(work, req, rsp);
break;
case SMB2_O_INFO_FILESYSTEM:
ksmbd_debug(SMB, "GOT SMB2_O_INFO_FILESYSTEM\n");
rc = smb2_get_info_filesystem(work, req, rsp, (void *)rsp_org);
rc = smb2_get_info_filesystem(work, req, rsp);
break;
case SMB2_O_INFO_SECURITY:
ksmbd_debug(SMB, "GOT SMB2_O_INFO_SECURITY\n");
rc = smb2_get_info_sec(work, req, rsp, (void *)rsp_org);
rc = smb2_get_info_sec(work, req, rsp);
break;
default:
ksmbd_debug(SMB, "InfoType %d not supported yet\n",
......@@ -5164,7 +5178,7 @@ int smb2_query_info(struct ksmbd_work *work)
}
rsp->StructureSize = cpu_to_le16(9);
rsp->OutputBufferOffset = cpu_to_le16(72);
inc_rfc1001_len(rsp_org, 8);
inc_rfc1001_len(work->response_buf, 8);
return 0;
}
......@@ -5177,8 +5191,8 @@ int smb2_query_info(struct ksmbd_work *work)
static noinline int smb2_close_pipe(struct ksmbd_work *work)
{
u64 id;
struct smb2_close_req *req = work->request_buf;
struct smb2_close_rsp *rsp = work->response_buf;
struct smb2_close_req *req = smb2_get_msg(work->request_buf);
struct smb2_close_rsp *rsp = smb2_get_msg(work->response_buf);
id = le64_to_cpu(req->VolatileFileId);
ksmbd_session_rpc_close(work->sess, id);
......@@ -5193,7 +5207,7 @@ static noinline int smb2_close_pipe(struct ksmbd_work *work)
rsp->AllocationSize = 0;
rsp->EndOfFile = 0;
rsp->Attributes = 0;
inc_rfc1001_len(rsp, 60);
inc_rfc1001_len(work->response_buf, 60);
return 0;
}
......@@ -5209,14 +5223,12 @@ int smb2_close(struct ksmbd_work *work)
u64 sess_id;
struct smb2_close_req *req;
struct smb2_close_rsp *rsp;
struct smb2_close_rsp *rsp_org;
struct ksmbd_conn *conn = work->conn;
struct ksmbd_file *fp;
struct inode *inode;
u64 time;
int err = 0;
rsp_org = work->response_buf;
WORK_BUFFERS(work, req, rsp);
if (test_share_config_flag(work->tcon->share_conf,
......@@ -5306,7 +5318,7 @@ int smb2_close(struct ksmbd_work *work)
rsp->hdr.Status = STATUS_FILE_CLOSED;
smb2_set_err_rsp(work);
} else {
inc_rfc1001_len(rsp_org, 60);
inc_rfc1001_len(work->response_buf, 60);
}
return 0;
......@@ -5320,11 +5332,11 @@ int smb2_close(struct ksmbd_work *work)
*/
int smb2_echo(struct ksmbd_work *work)
{
struct smb2_echo_rsp *rsp = work->response_buf;
struct smb2_echo_rsp *rsp = smb2_get_msg(work->response_buf);
rsp->StructureSize = cpu_to_le16(4);
rsp->Reserved = 0;
inc_rfc1001_len(rsp, 4);
inc_rfc1001_len(work->response_buf, 4);
return 0;
}
......@@ -5566,14 +5578,14 @@ static int set_file_basic_info(struct ksmbd_file *fp,
if (file_info->Attributes) {
if (!S_ISDIR(inode->i_mode) &&
file_info->Attributes & ATTR_DIRECTORY_LE) {
file_info->Attributes & FILE_ATTRIBUTE_DIRECTORY_LE) {
pr_err("can't change a file to a directory\n");
return -EINVAL;
}
if (!(S_ISDIR(inode->i_mode) && file_info->Attributes == ATTR_NORMAL_LE))
if (!(S_ISDIR(inode->i_mode) && file_info->Attributes == FILE_ATTRIBUTE_NORMAL_LE))
fp->f_ci->m_fattr = file_info->Attributes |
(fp->f_ci->m_fattr & ATTR_DIRECTORY_LE);
(fp->f_ci->m_fattr & FILE_ATTRIBUTE_DIRECTORY_LE);
}
if (test_share_config_flag(share, KSMBD_SHARE_FLAG_STORE_DOS_ATTRS) &&
......@@ -5794,9 +5806,7 @@ static int set_file_mode_info(struct ksmbd_file *fp,
mode = file_info->Mode;
if ((mode & ~FILE_MODE_INFO_MASK) ||
(mode & FILE_SYNCHRONOUS_IO_ALERT_LE &&
mode & FILE_SYNCHRONOUS_IO_NONALERT_LE)) {
if ((mode & ~FILE_MODE_INFO_MASK)) {
pr_err("Mode is not valid : 0x%x\n", le32_to_cpu(mode));
return -EINVAL;
}
......@@ -5943,14 +5953,13 @@ static int smb2_set_info_sec(struct ksmbd_file *fp, int addition_info,
int smb2_set_info(struct ksmbd_work *work)
{
struct smb2_set_info_req *req;
struct smb2_set_info_rsp *rsp, *rsp_org;
struct smb2_set_info_rsp *rsp;
struct ksmbd_file *fp;
int rc = 0;
unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
ksmbd_debug(SMB, "Received set info request\n");
rsp_org = work->response_buf;
if (work->next_smb2_rcv_hdr_off) {
req = ksmbd_req_buf_next(work);
rsp = ksmbd_resp_buf_next(work);
......@@ -5961,8 +5970,8 @@ int smb2_set_info(struct ksmbd_work *work)
pid = work->compound_pfid;
}
} else {
req = work->request_buf;
rsp = work->response_buf;
req = smb2_get_msg(work->request_buf);
rsp = smb2_get_msg(work->response_buf);
}
if (!has_file_id(id)) {
......@@ -6002,7 +6011,7 @@ int smb2_set_info(struct ksmbd_work *work)
goto err_out;
rsp->StructureSize = cpu_to_le16(2);
inc_rfc1001_len(rsp_org, 2);
inc_rfc1001_len(work->response_buf, 2);
ksmbd_fd_put(work, fp);
return 0;
......@@ -6042,12 +6051,12 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
int nbytes = 0, err;
u64 id;
struct ksmbd_rpc_command *rpc_resp;
struct smb2_read_req *req = work->request_buf;
struct smb2_read_rsp *rsp = work->response_buf;
struct smb2_read_req *req = smb2_get_msg(work->request_buf);
struct smb2_read_rsp *rsp = smb2_get_msg(work->response_buf);
id = le64_to_cpu(req->VolatileFileId);
inc_rfc1001_len(rsp, 16);
inc_rfc1001_len(work->response_buf, 16);
rpc_resp = ksmbd_rpc_read(work->sess, id);
if (rpc_resp) {
if (rpc_resp->flags != KSMBD_RPC_OK) {
......@@ -6066,7 +6075,7 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
rpc_resp->payload_sz);
nbytes = rpc_resp->payload_sz;
work->resp_hdr_sz = get_rfc1002_len(rsp) + 4;
work->resp_hdr_sz = get_rfc1002_len(work->response_buf) + 4;
work->aux_payload_sz = nbytes;
kvfree(rpc_resp);
}
......@@ -6076,8 +6085,8 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
rsp->Reserved = 0;
rsp->DataLength = cpu_to_le32(nbytes);
rsp->DataRemaining = 0;
rsp->Reserved2 = 0;
inc_rfc1001_len(rsp, nbytes);
rsp->Flags = 0;
inc_rfc1001_len(work->response_buf, nbytes);
return 0;
out:
......@@ -6127,14 +6136,13 @@ int smb2_read(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct smb2_read_req *req;
struct smb2_read_rsp *rsp, *rsp_org;
struct smb2_read_rsp *rsp;
struct ksmbd_file *fp;
loff_t offset;
size_t length, mincount;
ssize_t nbytes = 0, remain_bytes = 0;
int err = 0;
rsp_org = work->response_buf;
WORK_BUFFERS(work, req, rsp);
if (test_share_config_flag(work->tcon->share_conf,
......@@ -6215,11 +6223,11 @@ int smb2_read(struct ksmbd_work *work)
rsp->Reserved = 0;
rsp->DataLength = cpu_to_le32(nbytes);
rsp->DataRemaining = cpu_to_le32(remain_bytes);
rsp->Reserved2 = 0;
inc_rfc1001_len(rsp_org, 16);
work->resp_hdr_sz = get_rfc1002_len(rsp_org) + 4;
rsp->Flags = 0;
inc_rfc1001_len(work->response_buf, 16);
work->resp_hdr_sz = get_rfc1002_len(work->response_buf) + 4;
work->aux_payload_sz = nbytes;
inc_rfc1001_len(rsp_org, nbytes);
inc_rfc1001_len(work->response_buf, nbytes);
ksmbd_fd_put(work, fp);
return 0;
......@@ -6254,8 +6262,8 @@ int smb2_read(struct ksmbd_work *work)
*/
static noinline int smb2_write_pipe(struct ksmbd_work *work)
{
struct smb2_write_req *req = work->request_buf;
struct smb2_write_rsp *rsp = work->response_buf;
struct smb2_write_req *req = smb2_get_msg(work->request_buf);
struct smb2_write_rsp *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_rpc_command *rpc_resp;
u64 id = 0;
int err = 0, ret = 0;
......@@ -6266,13 +6274,14 @@ static noinline int smb2_write_pipe(struct ksmbd_work *work)
id = le64_to_cpu(req->VolatileFileId);
if (le16_to_cpu(req->DataOffset) ==
(offsetof(struct smb2_write_req, Buffer) - 4)) {
offsetof(struct smb2_write_req, Buffer)) {
data_buf = (char *)&req->Buffer[0];
} else {
if ((u64)le16_to_cpu(req->DataOffset) + length > get_rfc1002_len(req)) {
if ((u64)le16_to_cpu(req->DataOffset) + length >
get_rfc1002_len(work->request_buf)) {
pr_err("invalid write data offset %u, smb_len %u\n",
le16_to_cpu(req->DataOffset),
get_rfc1002_len(req));
get_rfc1002_len(work->request_buf));
err = -EINVAL;
goto out;
}
......@@ -6304,7 +6313,7 @@ static noinline int smb2_write_pipe(struct ksmbd_work *work)
rsp->DataLength = cpu_to_le32(length);
rsp->DataRemaining = 0;
rsp->Reserved2 = 0;
inc_rfc1001_len(rsp, 16);
inc_rfc1001_len(work->response_buf, 16);
return 0;
out:
if (err) {
......@@ -6372,7 +6381,7 @@ static ssize_t smb2_write_rdma_channel(struct ksmbd_work *work,
int smb2_write(struct ksmbd_work *work)
{
struct smb2_write_req *req;
struct smb2_write_rsp *rsp, *rsp_org;
struct smb2_write_rsp *rsp;
struct ksmbd_file *fp = NULL;
loff_t offset;
size_t length;
......@@ -6381,7 +6390,6 @@ int smb2_write(struct ksmbd_work *work)
bool writethrough = false;
int err = 0;
rsp_org = work->response_buf;
WORK_BUFFERS(work, req, rsp);
if (test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_PIPE)) {
......@@ -6424,13 +6432,14 @@ int smb2_write(struct ksmbd_work *work)
if (req->Channel != SMB2_CHANNEL_RDMA_V1 &&
req->Channel != SMB2_CHANNEL_RDMA_V1_INVALIDATE) {
if (le16_to_cpu(req->DataOffset) ==
(offsetof(struct smb2_write_req, Buffer) - 4)) {
offsetof(struct smb2_write_req, Buffer)) {
data_buf = (char *)&req->Buffer[0];
} else {
if ((u64)le16_to_cpu(req->DataOffset) + length > get_rfc1002_len(req)) {
if ((u64)le16_to_cpu(req->DataOffset) + length >
get_rfc1002_len(work->request_buf)) {
pr_err("invalid write data offset %u, smb_len %u\n",
le16_to_cpu(req->DataOffset),
get_rfc1002_len(req));
get_rfc1002_len(work->request_buf));
err = -EINVAL;
goto out;
}
......@@ -6468,7 +6477,7 @@ int smb2_write(struct ksmbd_work *work)
rsp->DataLength = cpu_to_le32(nbytes);
rsp->DataRemaining = 0;
rsp->Reserved2 = 0;
inc_rfc1001_len(rsp_org, 16);
inc_rfc1001_len(work->response_buf, 16);
ksmbd_fd_put(work, fp);
return 0;
......@@ -6502,10 +6511,9 @@ int smb2_write(struct ksmbd_work *work)
int smb2_flush(struct ksmbd_work *work)
{
struct smb2_flush_req *req;
struct smb2_flush_rsp *rsp, *rsp_org;
struct smb2_flush_rsp *rsp;
int err;
rsp_org = work->response_buf;
WORK_BUFFERS(work, req, rsp);
ksmbd_debug(SMB, "SMB2_FLUSH called for fid %llu\n",
......@@ -6519,7 +6527,7 @@ int smb2_flush(struct ksmbd_work *work)
rsp->StructureSize = cpu_to_le16(4);
rsp->Reserved = 0;
inc_rfc1001_len(rsp_org, 4);
inc_rfc1001_len(work->response_buf, 4);
return 0;
out:
......@@ -6540,7 +6548,7 @@ int smb2_flush(struct ksmbd_work *work)
int smb2_cancel(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct smb2_hdr *hdr = work->request_buf;
struct smb2_hdr *hdr = smb2_get_msg(work->request_buf);
struct smb2_hdr *chdr;
struct ksmbd_work *cancel_work = NULL;
int canceled = 0;
......@@ -6555,7 +6563,7 @@ int smb2_cancel(struct ksmbd_work *work)
spin_lock(&conn->request_lock);
list_for_each_entry(cancel_work, command_list,
async_request_entry) {
chdr = cancel_work->request_buf;
chdr = smb2_get_msg(cancel_work->request_buf);
if (cancel_work->async_id !=
le64_to_cpu(hdr->Id.AsyncId))
......@@ -6574,7 +6582,7 @@ int smb2_cancel(struct ksmbd_work *work)
spin_lock(&conn->request_lock);
list_for_each_entry(cancel_work, command_list, request_entry) {
chdr = cancel_work->request_buf;
chdr = smb2_get_msg(cancel_work->request_buf);
if (chdr->MessageId != hdr->MessageId ||
cancel_work == work)
......@@ -6709,8 +6717,8 @@ static inline bool lock_defer_pending(struct file_lock *fl)
*/
int smb2_lock(struct ksmbd_work *work)
{
struct smb2_lock_req *req = work->request_buf;
struct smb2_lock_rsp *rsp = work->response_buf;
struct smb2_lock_req *req = smb2_get_msg(work->request_buf);
struct smb2_lock_rsp *rsp = smb2_get_msg(work->response_buf);
struct smb2_lock_element *lock_ele;
struct ksmbd_file *fp = NULL;
struct file_lock *flock = NULL;
......@@ -7017,7 +7025,7 @@ int smb2_lock(struct ksmbd_work *work)
ksmbd_debug(SMB, "successful in taking lock\n");
rsp->hdr.Status = STATUS_SUCCESS;
rsp->Reserved = 0;
inc_rfc1001_len(rsp, 4);
inc_rfc1001_len(work->response_buf, 4);
ksmbd_fd_put(work, fp);
return 0;
......@@ -7312,7 +7320,7 @@ static int fsctl_validate_negotiate_info(struct ksmbd_conn *conn,
int ret = 0;
int dialect;
if (in_buf_len < sizeof(struct validate_negotiate_info_req) +
if (in_buf_len < offsetof(struct validate_negotiate_info_req, Dialects) +
le16_to_cpu(neg_req->DialectCount) * sizeof(__le16))
return -EINVAL;
......@@ -7435,9 +7443,9 @@ static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id,
old_fattr = fp->f_ci->m_fattr;
if (sparse->SetSparse)
fp->f_ci->m_fattr |= ATTR_SPARSE_FILE_LE;
fp->f_ci->m_fattr |= FILE_ATTRIBUTE_SPARSE_FILE_LE;
else
fp->f_ci->m_fattr &= ~ATTR_SPARSE_FILE_LE;
fp->f_ci->m_fattr &= ~FILE_ATTRIBUTE_SPARSE_FILE_LE;
if (fp->f_ci->m_fattr != old_fattr &&
test_share_config_flag(work->tcon->share_conf,
......@@ -7490,13 +7498,12 @@ static int fsctl_request_resume_key(struct ksmbd_work *work,
int smb2_ioctl(struct ksmbd_work *work)
{
struct smb2_ioctl_req *req;
struct smb2_ioctl_rsp *rsp, *rsp_org;
struct smb2_ioctl_rsp *rsp;
unsigned int cnt_code, nbytes = 0, out_buf_len, in_buf_len;
u64 id = KSMBD_NO_FID;
struct ksmbd_conn *conn = work->conn;
int ret = 0;
rsp_org = work->response_buf;
if (work->next_smb2_rcv_hdr_off) {
req = ksmbd_req_buf_next(work);
rsp = ksmbd_resp_buf_next(work);
......@@ -7506,8 +7513,8 @@ int smb2_ioctl(struct ksmbd_work *work)
id = work->compound_fid;
}
} else {
req = work->request_buf;
rsp = work->response_buf;
req = smb2_get_msg(work->request_buf);
rsp = smb2_get_msg(work->response_buf);
}
if (!has_file_id(id))
......@@ -7787,7 +7794,7 @@ int smb2_ioctl(struct ksmbd_work *work)
rsp->Reserved = cpu_to_le16(0);
rsp->Flags = cpu_to_le32(0);
rsp->Reserved2 = cpu_to_le32(0);
inc_rfc1001_len(rsp_org, 48 + nbytes);
inc_rfc1001_len(work->response_buf, 48 + nbytes);
return 0;
......@@ -7814,8 +7821,8 @@ int smb2_ioctl(struct ksmbd_work *work)
*/
static void smb20_oplock_break_ack(struct ksmbd_work *work)
{
struct smb2_oplock_break *req = work->request_buf;
struct smb2_oplock_break *rsp = work->response_buf;
struct smb2_oplock_break *req = smb2_get_msg(work->request_buf);
struct smb2_oplock_break *rsp = smb2_get_msg(work->response_buf);
struct ksmbd_file *fp;
struct oplock_info *opinfo = NULL;
__le32 err = 0;
......@@ -7922,7 +7929,7 @@ static void smb20_oplock_break_ack(struct ksmbd_work *work)
rsp->Reserved2 = 0;
rsp->VolatileFid = cpu_to_le64(volatile_id);
rsp->PersistentFid = cpu_to_le64(persistent_id);
inc_rfc1001_len(rsp, 24);
inc_rfc1001_len(work->response_buf, 24);
return;
err_out:
......@@ -7958,8 +7965,8 @@ static int check_lease_state(struct lease *lease, __le32 req_state)
static void smb21_lease_break_ack(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct smb2_lease_ack *req = work->request_buf;
struct smb2_lease_ack *rsp = work->response_buf;
struct smb2_lease_ack *req = smb2_get_msg(work->request_buf);
struct smb2_lease_ack *rsp = smb2_get_msg(work->response_buf);
struct oplock_info *opinfo;
__le32 err = 0;
int ret = 0;
......@@ -8071,7 +8078,7 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
memcpy(rsp->LeaseKey, req->LeaseKey, 16);
rsp->LeaseState = lease_state;
rsp->LeaseDuration = 0;
inc_rfc1001_len(rsp, 36);
inc_rfc1001_len(work->response_buf, 36);
return;
err_out:
......@@ -8092,8 +8099,8 @@ static void smb21_lease_break_ack(struct ksmbd_work *work)
*/
int smb2_oplock_break(struct ksmbd_work *work)
{
struct smb2_oplock_break *req = work->request_buf;
struct smb2_oplock_break *rsp = work->response_buf;
struct smb2_oplock_break *req = smb2_get_msg(work->request_buf);
struct smb2_oplock_break *rsp = smb2_get_msg(work->response_buf);
switch (le16_to_cpu(req->StructureSize)) {
case OP_BREAK_STRUCT_SIZE_20:
......@@ -8120,8 +8127,8 @@ int smb2_oplock_break(struct ksmbd_work *work)
*/
int smb2_notify(struct ksmbd_work *work)
{
struct smb2_notify_req *req;
struct smb2_notify_rsp *rsp;
struct smb2_change_notify_req *req;
struct smb2_change_notify_rsp *rsp;
WORK_BUFFERS(work, req, rsp);
......@@ -8145,7 +8152,7 @@ int smb2_notify(struct ksmbd_work *work)
*/
bool smb2_is_sign_req(struct ksmbd_work *work, unsigned int command)
{
struct smb2_hdr *rcv_hdr2 = work->request_buf;
struct smb2_hdr *rcv_hdr2 = smb2_get_msg(work->request_buf);
if ((rcv_hdr2->Flags & SMB2_FLAGS_SIGNED) &&
command != SMB2_NEGOTIATE_HE &&
......@@ -8164,22 +8171,22 @@ bool smb2_is_sign_req(struct ksmbd_work *work, unsigned int command)
*/
int smb2_check_sign_req(struct ksmbd_work *work)
{
struct smb2_hdr *hdr, *hdr_org;
struct smb2_hdr *hdr;
char signature_req[SMB2_SIGNATURE_SIZE];
char signature[SMB2_HMACSHA256_SIZE];
struct kvec iov[1];
size_t len;
hdr_org = hdr = work->request_buf;
hdr = smb2_get_msg(work->request_buf);
if (work->next_smb2_rcv_hdr_off)
hdr = ksmbd_req_buf_next(work);
if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off)
len = be32_to_cpu(hdr_org->smb2_buf_length);
len = get_rfc1002_len(work->request_buf);
else if (hdr->NextCommand)
len = le32_to_cpu(hdr->NextCommand);
else
len = be32_to_cpu(hdr_org->smb2_buf_length) -
len = get_rfc1002_len(work->request_buf) -
work->next_smb2_rcv_hdr_off;
memcpy(signature_req, hdr->Signature, SMB2_SIGNATURE_SIZE);
......@@ -8207,25 +8214,26 @@ int smb2_check_sign_req(struct ksmbd_work *work)
*/
void smb2_set_sign_rsp(struct ksmbd_work *work)
{
struct smb2_hdr *hdr, *hdr_org;
struct smb2_hdr *hdr;
struct smb2_hdr *req_hdr;
char signature[SMB2_HMACSHA256_SIZE];
struct kvec iov[2];
size_t len;
int n_vec = 1;
hdr_org = hdr = work->response_buf;
hdr = smb2_get_msg(work->response_buf);
if (work->next_smb2_rsp_hdr_off)
hdr = ksmbd_resp_buf_next(work);
req_hdr = ksmbd_req_buf_next(work);
if (!work->next_smb2_rsp_hdr_off) {
len = get_rfc1002_len(hdr_org);
len = get_rfc1002_len(work->response_buf);
if (req_hdr->NextCommand)
len = ALIGN(len, 8);
} else {
len = get_rfc1002_len(hdr_org) - work->next_smb2_rsp_hdr_off;
len = get_rfc1002_len(work->response_buf) -
work->next_smb2_rsp_hdr_off;
len = ALIGN(len, 8);
}
......@@ -8261,23 +8269,23 @@ int smb3_check_sign_req(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
char *signing_key;
struct smb2_hdr *hdr, *hdr_org;
struct smb2_hdr *hdr;
struct channel *chann;
char signature_req[SMB2_SIGNATURE_SIZE];
char signature[SMB2_CMACAES_SIZE];
struct kvec iov[1];
size_t len;
hdr_org = hdr = work->request_buf;
hdr = smb2_get_msg(work->request_buf);
if (work->next_smb2_rcv_hdr_off)
hdr = ksmbd_req_buf_next(work);
if (!hdr->NextCommand && !work->next_smb2_rcv_hdr_off)
len = be32_to_cpu(hdr_org->smb2_buf_length);
len = get_rfc1002_len(work->request_buf);
else if (hdr->NextCommand)
len = le32_to_cpu(hdr->NextCommand);
else
len = be32_to_cpu(hdr_org->smb2_buf_length) -
len = get_rfc1002_len(work->request_buf) -
work->next_smb2_rcv_hdr_off;
if (le16_to_cpu(hdr->Command) == SMB2_SESSION_SETUP_HE) {
......@@ -8318,8 +8326,7 @@ int smb3_check_sign_req(struct ksmbd_work *work)
void smb3_set_sign_rsp(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct smb2_hdr *req_hdr;
struct smb2_hdr *hdr, *hdr_org;
struct smb2_hdr *req_hdr, *hdr;
struct channel *chann;
char signature[SMB2_CMACAES_SIZE];
struct kvec iov[2];
......@@ -8327,18 +8334,19 @@ void smb3_set_sign_rsp(struct ksmbd_work *work)
size_t len;
char *signing_key;
hdr_org = hdr = work->response_buf;
hdr = smb2_get_msg(work->response_buf);
if (work->next_smb2_rsp_hdr_off)
hdr = ksmbd_resp_buf_next(work);
req_hdr = ksmbd_req_buf_next(work);
if (!work->next_smb2_rsp_hdr_off) {
len = get_rfc1002_len(hdr_org);
len = get_rfc1002_len(work->response_buf);
if (req_hdr->NextCommand)
len = ALIGN(len, 8);
} else {
len = get_rfc1002_len(hdr_org) - work->next_smb2_rsp_hdr_off;
len = get_rfc1002_len(work->response_buf) -
work->next_smb2_rsp_hdr_off;
len = ALIGN(len, 8);
}
......@@ -8391,7 +8399,7 @@ void smb3_preauth_hash_rsp(struct ksmbd_work *work)
if (le16_to_cpu(req->Command) == SMB2_NEGOTIATE_HE &&
conn->preauth_info)
ksmbd_gen_preauth_integrity_hash(conn, (char *)rsp,
ksmbd_gen_preauth_integrity_hash(conn, work->response_buf,
conn->preauth_info->Preauth_HashValue);
if (le16_to_cpu(rsp->Command) == SMB2_SESSION_SETUP_HE && sess) {
......@@ -8409,35 +8417,34 @@ void smb3_preauth_hash_rsp(struct ksmbd_work *work)
if (!hash_value)
return;
}
ksmbd_gen_preauth_integrity_hash(conn, (char *)rsp,
ksmbd_gen_preauth_integrity_hash(conn, work->response_buf,
hash_value);
}
}
static void fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, char *old_buf,
__le16 cipher_type)
static void fill_transform_hdr(void *tr_buf, char *old_buf, __le16 cipher_type)
{
struct smb2_hdr *hdr = (struct smb2_hdr *)old_buf;
struct smb2_transform_hdr *tr_hdr = tr_buf + 4;
struct smb2_hdr *hdr = smb2_get_msg(old_buf);
unsigned int orig_len = get_rfc1002_len(old_buf);
memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr));
memset(tr_buf, 0, sizeof(struct smb2_transform_hdr) + 4);
tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
tr_hdr->OriginalMessageSize = cpu_to_le32(orig_len);
tr_hdr->Flags = cpu_to_le16(0x01);
tr_hdr->Flags = cpu_to_le16(TRANSFORM_FLAG_ENCRYPTED);
if (cipher_type == SMB2_ENCRYPTION_AES128_GCM ||
cipher_type == SMB2_ENCRYPTION_AES256_GCM)
get_random_bytes(&tr_hdr->Nonce, SMB3_AES_GCM_NONCE);
else
get_random_bytes(&tr_hdr->Nonce, SMB3_AES_CCM_NONCE);
memcpy(&tr_hdr->SessionId, &hdr->SessionId, 8);
inc_rfc1001_len(tr_hdr, sizeof(struct smb2_transform_hdr) - 4);
inc_rfc1001_len(tr_hdr, orig_len);
inc_rfc1001_len(tr_buf, sizeof(struct smb2_transform_hdr));
inc_rfc1001_len(tr_buf, orig_len);
}
int smb3_encrypt_resp(struct ksmbd_work *work)
{
char *buf = work->response_buf;
struct smb2_transform_hdr *tr_hdr;
struct kvec iov[3];
int rc = -ENOMEM;
int buf_size = 0, rq_nvec = 2 + (work->aux_payload_sz ? 1 : 0);
......@@ -8445,15 +8452,15 @@ int smb3_encrypt_resp(struct ksmbd_work *work)
if (ARRAY_SIZE(iov) < rq_nvec)
return -ENOMEM;
tr_hdr = kzalloc(sizeof(struct smb2_transform_hdr), GFP_KERNEL);
if (!tr_hdr)
work->tr_buf = kzalloc(sizeof(struct smb2_transform_hdr) + 4, GFP_KERNEL);
if (!work->tr_buf)
return rc;
/* fill transform header */
fill_transform_hdr(tr_hdr, buf, work->conn->cipher_type);
fill_transform_hdr(work->tr_buf, buf, work->conn->cipher_type);
iov[0].iov_base = tr_hdr;
iov[0].iov_len = sizeof(struct smb2_transform_hdr);
iov[0].iov_base = work->tr_buf;
iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
buf_size += iov[0].iov_len - 4;
iov[1].iov_base = buf + 4;
......@@ -8473,15 +8480,14 @@ int smb3_encrypt_resp(struct ksmbd_work *work)
return rc;
memmove(buf, iov[1].iov_base, iov[1].iov_len);
tr_hdr->smb2_buf_length = cpu_to_be32(buf_size);
work->tr_buf = tr_hdr;
*(__be32 *)work->tr_buf = cpu_to_be32(buf_size);
return rc;
}
bool smb3_is_transform_hdr(void *buf)
{
struct smb2_transform_hdr *trhdr = buf;
struct smb2_transform_hdr *trhdr = smb2_get_msg(buf);
return trhdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM;
}
......@@ -8491,12 +8497,10 @@ int smb3_decrypt_req(struct ksmbd_work *work)
struct ksmbd_conn *conn = work->conn;
struct ksmbd_session *sess;
char *buf = work->request_buf;
struct smb2_hdr *hdr;
unsigned int pdu_length = get_rfc1002_len(buf);
struct kvec iov[2];
int buf_data_size = pdu_length + 4 -
sizeof(struct smb2_transform_hdr);
struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
int buf_data_size = pdu_length - sizeof(struct smb2_transform_hdr);
struct smb2_transform_hdr *tr_hdr = smb2_get_msg(buf);
int rc = 0;
if (buf_data_size < sizeof(struct smb2_hdr)) {
......@@ -8518,16 +8522,15 @@ int smb3_decrypt_req(struct ksmbd_work *work)
}
iov[0].iov_base = buf;
iov[0].iov_len = sizeof(struct smb2_transform_hdr);
iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr);
iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr) + 4;
iov[1].iov_len = buf_data_size;
rc = ksmbd_crypt_message(conn, iov, 2, 0);
if (rc)
return rc;
memmove(buf + 4, iov[1].iov_base, buf_data_size);
hdr = (struct smb2_hdr *)buf;
hdr->smb2_buf_length = cpu_to_be32(buf_data_size);
*(__be32 *)buf = cpu_to_be32(buf_data_size);
return rc;
}
......@@ -8535,7 +8538,7 @@ int smb3_decrypt_req(struct ksmbd_work *work)
bool smb3_11_final_sess_setup_resp(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
struct smb2_hdr *rsp = work->response_buf;
struct smb2_hdr *rsp = smb2_get_msg(work->response_buf);
if (conn->dialect < SMB30_PROT_ID)
return false;
......
......@@ -10,60 +10,6 @@
#include "ntlmssp.h"
#include "smbacl.h"
/*
* Note that, due to trying to use names similar to the protocol specifications,
* there are many mixed case field names in the structures below. Although
* this does not match typical Linux kernel style, it is necessary to be
* able to match against the protocol specfication.
*
* SMB2 commands
* Some commands have minimal (wct=0,bcc=0), or uninteresting, responses
* (ie no useful data other than the SMB error code itself) and are marked such.
* Knowing this helps avoid response buffer allocations and copy in some cases.
*/
/* List of commands in host endian */
#define SMB2_NEGOTIATE_HE 0x0000
#define SMB2_SESSION_SETUP_HE 0x0001
#define SMB2_LOGOFF_HE 0x0002 /* trivial request/resp */
#define SMB2_TREE_CONNECT_HE 0x0003
#define SMB2_TREE_DISCONNECT_HE 0x0004 /* trivial req/resp */
#define SMB2_CREATE_HE 0x0005
#define SMB2_CLOSE_HE 0x0006
#define SMB2_FLUSH_HE 0x0007 /* trivial resp */
#define SMB2_READ_HE 0x0008
#define SMB2_WRITE_HE 0x0009
#define SMB2_LOCK_HE 0x000A
#define SMB2_IOCTL_HE 0x000B
#define SMB2_CANCEL_HE 0x000C
#define SMB2_ECHO_HE 0x000D
#define SMB2_QUERY_DIRECTORY_HE 0x000E
#define SMB2_CHANGE_NOTIFY_HE 0x000F
#define SMB2_QUERY_INFO_HE 0x0010
#define SMB2_SET_INFO_HE 0x0011
#define SMB2_OPLOCK_BREAK_HE 0x0012
/* The same list in little endian */
#define SMB2_NEGOTIATE cpu_to_le16(SMB2_NEGOTIATE_HE)
#define SMB2_SESSION_SETUP cpu_to_le16(SMB2_SESSION_SETUP_HE)
#define SMB2_LOGOFF cpu_to_le16(SMB2_LOGOFF_HE)
#define SMB2_TREE_CONNECT cpu_to_le16(SMB2_TREE_CONNECT_HE)
#define SMB2_TREE_DISCONNECT cpu_to_le16(SMB2_TREE_DISCONNECT_HE)
#define SMB2_CREATE cpu_to_le16(SMB2_CREATE_HE)
#define SMB2_CLOSE cpu_to_le16(SMB2_CLOSE_HE)
#define SMB2_FLUSH cpu_to_le16(SMB2_FLUSH_HE)
#define SMB2_READ cpu_to_le16(SMB2_READ_HE)
#define SMB2_WRITE cpu_to_le16(SMB2_WRITE_HE)
#define SMB2_LOCK cpu_to_le16(SMB2_LOCK_HE)
#define SMB2_IOCTL cpu_to_le16(SMB2_IOCTL_HE)
#define SMB2_CANCEL cpu_to_le16(SMB2_CANCEL_HE)
#define SMB2_ECHO cpu_to_le16(SMB2_ECHO_HE)
#define SMB2_QUERY_DIRECTORY cpu_to_le16(SMB2_QUERY_DIRECTORY_HE)
#define SMB2_CHANGE_NOTIFY cpu_to_le16(SMB2_CHANGE_NOTIFY_HE)
#define SMB2_QUERY_INFO cpu_to_le16(SMB2_QUERY_INFO_HE)
#define SMB2_SET_INFO cpu_to_le16(SMB2_SET_INFO_HE)
#define SMB2_OPLOCK_BREAK cpu_to_le16(SMB2_OPLOCK_BREAK_HE)
/*Create Action Flags*/
#define FILE_SUPERSEDED 0x00000000
#define FILE_OPENED 0x00000001
......@@ -96,9 +42,6 @@
/* SMB2 Max Credits */
#define SMB2_MAX_CREDITS 8192
#define SMB2_CLIENT_GUID_SIZE 16
#define SMB2_CREATE_GUID_SIZE 16
/* Maximum buffer size value we can send with 1 credit */
#define SMB2_MAX_BUFFER_SIZE 65536
......@@ -107,87 +50,12 @@
/* BB FIXME - analyze following length BB */
#define MAX_SMB2_HDR_SIZE 0x78 /* 4 len + 64 hdr + (2*24 wct) + 2 bct + 2 pad */
#define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe) /* 'B''M''S' */
#define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd)
#define SMB21_DEFAULT_IOSIZE (1024 * 1024)
#define SMB3_DEFAULT_IOSIZE (4 * 1024 * 1024)
#define SMB3_DEFAULT_TRANS_SIZE (1024 * 1024)
#define SMB3_MIN_IOSIZE (64 * 1024)
#define SMB3_MAX_IOSIZE (8 * 1024 * 1024)
/*
* SMB2 Header Definition
*
* "MBZ" : Must be Zero
* "BB" : BugBug, Something to check/review/analyze later
* "PDU" : "Protocol Data Unit" (ie a network "frame")
*
*/
#define __SMB2_HEADER_STRUCTURE_SIZE 64
#define SMB2_HEADER_STRUCTURE_SIZE \
cpu_to_le16(__SMB2_HEADER_STRUCTURE_SIZE)
struct smb2_hdr {
__be32 smb2_buf_length; /* big endian on wire */
/*
* length is only two or three bytes - with
* one or two byte type preceding it that MBZ
*/
__le32 ProtocolId; /* 0xFE 'S' 'M' 'B' */
__le16 StructureSize; /* 64 */
__le16 CreditCharge; /* MBZ */
__le32 Status; /* Error from server */
__le16 Command;
__le16 CreditRequest; /* CreditResponse */
__le32 Flags;
__le32 NextCommand;
__le64 MessageId;
union {
struct {
__le32 ProcessId;
__le32 TreeId;
} __packed SyncId;
__le64 AsyncId;
} __packed Id;
__le64 SessionId;
__u8 Signature[16];
} __packed;
struct smb2_pdu {
struct smb2_hdr hdr;
__le16 StructureSize2; /* size of wct area (varies, request specific) */
} __packed;
#define SMB3_AES_CCM_NONCE 11
#define SMB3_AES_GCM_NONCE 12
struct smb2_transform_hdr {
__be32 smb2_buf_length; /* big endian on wire */
/*
* length is only two or three bytes - with
* one or two byte type preceding it that MBZ
*/
__le32 ProtocolId; /* 0xFD 'S' 'M' 'B' */
__u8 Signature[16];
__u8 Nonce[16];
__le32 OriginalMessageSize;
__u16 Reserved1;
__le16 Flags; /* EncryptionAlgorithm */
__le64 SessionId;
} __packed;
/*
* SMB2 flag definitions
*/
#define SMB2_FLAGS_SERVER_TO_REDIR cpu_to_le32(0x00000001)
#define SMB2_FLAGS_ASYNC_COMMAND cpu_to_le32(0x00000002)
#define SMB2_FLAGS_RELATED_OPERATIONS cpu_to_le32(0x00000004)
#define SMB2_FLAGS_SIGNED cpu_to_le32(0x00000008)
#define SMB2_FLAGS_DFS_OPERATIONS cpu_to_le32(0x10000000)
#define SMB2_FLAGS_REPLAY_OPERATIONS cpu_to_le32(0x20000000)
/*
* Definitions for SMB2 Protocol Data Units (network frames)
*
......@@ -209,425 +77,30 @@ struct smb2_err_rsp {
__u8 ErrorData[1]; /* variable length */
} __packed;
struct smb2_negotiate_req {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 36 */
__le16 DialectCount;
__le16 SecurityMode;
__le16 Reserved; /* MBZ */
__le32 Capabilities;
__u8 ClientGUID[SMB2_CLIENT_GUID_SIZE];
/* In SMB3.02 and earlier next three were MBZ le64 ClientStartTime */
__le32 NegotiateContextOffset; /* SMB3.1.1 only. MBZ earlier */
__le16 NegotiateContextCount; /* SMB3.1.1 only. MBZ earlier */
__le16 Reserved2;
__le16 Dialects[1]; /* One dialect (vers=) at a time for now */
} __packed;
/* SecurityMode flags */
#define SMB2_NEGOTIATE_SIGNING_ENABLED_LE cpu_to_le16(0x0001)
#define SMB2_NEGOTIATE_SIGNING_REQUIRED 0x0002
#define SMB2_NEGOTIATE_SIGNING_REQUIRED_LE cpu_to_le16(0x0002)
/* Capabilities flags */
#define SMB2_GLOBAL_CAP_DFS 0x00000001
#define SMB2_GLOBAL_CAP_LEASING 0x00000002 /* Resp only New to SMB2.1 */
#define SMB2_GLOBAL_CAP_LARGE_MTU 0X00000004 /* Resp only New to SMB2.1 */
#define SMB2_GLOBAL_CAP_MULTI_CHANNEL 0x00000008 /* New to SMB3 */
#define SMB2_GLOBAL_CAP_PERSISTENT_HANDLES 0x00000010 /* New to SMB3 */
#define SMB2_GLOBAL_CAP_DIRECTORY_LEASING 0x00000020 /* New to SMB3 */
#define SMB2_GLOBAL_CAP_ENCRYPTION 0x00000040 /* New to SMB3 */
/* Internal types */
#define SMB2_NT_FIND 0x00100000
#define SMB2_LARGE_FILES 0x00200000
#define SMB311_SALT_SIZE 32
/* Hash Algorithm Types */
#define SMB2_PREAUTH_INTEGRITY_SHA512 cpu_to_le16(0x0001)
#define PREAUTH_HASHVALUE_SIZE 64
struct preauth_integrity_info {
/* PreAuth integrity Hash ID */
__le16 Preauth_HashId;
/* PreAuth integrity Hash Value */
__u8 Preauth_HashValue[PREAUTH_HASHVALUE_SIZE];
__u8 Preauth_HashValue[SMB2_PREAUTH_HASH_SIZE];
};
/* offset is sizeof smb2_negotiate_rsp - 4 but rounded up to 8 bytes. */
/* offset is sizeof smb2_negotiate_rsp but rounded up to 8 bytes. */
#ifdef CONFIG_SMB_SERVER_KERBEROS5
/* sizeof(struct smb2_negotiate_rsp) - 4 =
/* sizeof(struct smb2_negotiate_rsp) =
* header(64) + response(64) + GSS_LENGTH(96) + GSS_PADDING(0)
*/
#define OFFSET_OF_NEG_CONTEXT 0xe0
#else
/* sizeof(struct smb2_negotiate_rsp) - 4 =
/* sizeof(struct smb2_negotiate_rsp) =
* header(64) + response(64) + GSS_LENGTH(74) + GSS_PADDING(6)
*/
#define OFFSET_OF_NEG_CONTEXT 0xd0
#endif
#define SMB2_PREAUTH_INTEGRITY_CAPABILITIES cpu_to_le16(1)
#define SMB2_ENCRYPTION_CAPABILITIES cpu_to_le16(2)
#define SMB2_COMPRESSION_CAPABILITIES cpu_to_le16(3)
#define SMB2_NETNAME_NEGOTIATE_CONTEXT_ID cpu_to_le16(5)
#define SMB2_SIGNING_CAPABILITIES cpu_to_le16(8)
#define SMB2_POSIX_EXTENSIONS_AVAILABLE cpu_to_le16(0x100)
struct smb2_neg_context {
__le16 ContextType;
__le16 DataLength;
__le32 Reserved;
/* Followed by array of data */
} __packed;
struct smb2_preauth_neg_context {
__le16 ContextType; /* 1 */
__le16 DataLength;
__le32 Reserved;
__le16 HashAlgorithmCount; /* 1 */
__le16 SaltLength;
__le16 HashAlgorithms; /* HashAlgorithms[0] since only one defined */
__u8 Salt[SMB311_SALT_SIZE];
} __packed;
/* Encryption Algorithms Ciphers */
#define SMB2_ENCRYPTION_AES128_CCM cpu_to_le16(0x0001)
#define SMB2_ENCRYPTION_AES128_GCM cpu_to_le16(0x0002)
#define SMB2_ENCRYPTION_AES256_CCM cpu_to_le16(0x0003)
#define SMB2_ENCRYPTION_AES256_GCM cpu_to_le16(0x0004)
struct smb2_encryption_neg_context {
__le16 ContextType; /* 2 */
__le16 DataLength;
__le32 Reserved;
/* CipherCount usally 2, but can be 3 when AES256-GCM enabled */
__le16 CipherCount; /* AES-128-GCM and AES-128-CCM by default */
__le16 Ciphers[];
} __packed;
#define SMB3_COMPRESS_NONE cpu_to_le16(0x0000)
#define SMB3_COMPRESS_LZNT1 cpu_to_le16(0x0001)
#define SMB3_COMPRESS_LZ77 cpu_to_le16(0x0002)
#define SMB3_COMPRESS_LZ77_HUFF cpu_to_le16(0x0003)
struct smb2_compression_ctx {
__le16 ContextType; /* 3 */
__le16 DataLength;
__le32 Reserved;
__le16 CompressionAlgorithmCount;
__u16 Padding;
__le32 Reserved1;
__le16 CompressionAlgorithms[];
} __packed;
#define POSIX_CTXT_DATA_LEN 16
struct smb2_posix_neg_context {
__le16 ContextType; /* 0x100 */
__le16 DataLength;
__le32 Reserved;
__u8 Name[16]; /* POSIX ctxt GUID 93AD25509CB411E7B42383DE968BCD7C */
} __packed;
struct smb2_netname_neg_context {
__le16 ContextType; /* 0x100 */
__le16 DataLength;
__le32 Reserved;
__le16 NetName[]; /* hostname of target converted to UCS-2 */
} __packed;
/* Signing algorithms */
#define SIGNING_ALG_HMAC_SHA256 cpu_to_le16(0)
#define SIGNING_ALG_AES_CMAC cpu_to_le16(1)
#define SIGNING_ALG_AES_GMAC cpu_to_le16(2)
struct smb2_signing_capabilities {
__le16 ContextType; /* 8 */
__le16 DataLength;
__le32 Reserved;
__le16 SigningAlgorithmCount;
__le16 SigningAlgorithms[];
} __packed;
struct smb2_negotiate_rsp {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 65 */
__le16 SecurityMode;
__le16 DialectRevision;
__le16 NegotiateContextCount; /* Prior to SMB3.1.1 was Reserved & MBZ */
__u8 ServerGUID[16];
__le32 Capabilities;
__le32 MaxTransactSize;
__le32 MaxReadSize;
__le32 MaxWriteSize;
__le64 SystemTime; /* MBZ */
__le64 ServerStartTime;
__le16 SecurityBufferOffset;
__le16 SecurityBufferLength;
__le32 NegotiateContextOffset; /* Pre:SMB3.1.1 was reserved/ignored */
__u8 Buffer[1]; /* variable length GSS security buffer */
} __packed;
/* Flags */
#define SMB2_SESSION_REQ_FLAG_BINDING 0x01
#define SMB2_SESSION_REQ_FLAG_ENCRYPT_DATA 0x04
#define SMB2_SESSION_EXPIRED (0)
#define SMB2_SESSION_IN_PROGRESS BIT(0)
#define SMB2_SESSION_VALID BIT(1)
/* Flags */
#define SMB2_SESSION_REQ_FLAG_BINDING 0x01
#define SMB2_SESSION_REQ_FLAG_ENCRYPT_DATA 0x04
struct smb2_sess_setup_req {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 25 */
__u8 Flags;
__u8 SecurityMode;
__le32 Capabilities;
__le32 Channel;
__le16 SecurityBufferOffset;
__le16 SecurityBufferLength;
__le64 PreviousSessionId;
__u8 Buffer[1]; /* variable length GSS security buffer */
} __packed;
/* Flags/Reserved for SMB3.1.1 */
#define SMB2_SHAREFLAG_CLUSTER_RECONNECT 0x0001
/* Currently defined SessionFlags */
#define SMB2_SESSION_FLAG_IS_GUEST_LE cpu_to_le16(0x0001)
#define SMB2_SESSION_FLAG_IS_NULL_LE cpu_to_le16(0x0002)
#define SMB2_SESSION_FLAG_ENCRYPT_DATA_LE cpu_to_le16(0x0004)
struct smb2_sess_setup_rsp {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 9 */
__le16 SessionFlags;
__le16 SecurityBufferOffset;
__le16 SecurityBufferLength;
__u8 Buffer[1]; /* variable length GSS security buffer */
} __packed;
struct smb2_logoff_req {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 4 */
__le16 Reserved;
} __packed;
struct smb2_logoff_rsp {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 4 */
__le16 Reserved;
} __packed;
struct smb2_tree_connect_req {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 9 */
__le16 Reserved; /* Flags in SMB3.1.1 */
__le16 PathOffset;
__le16 PathLength;
__u8 Buffer[1]; /* variable length */
} __packed;
struct smb2_tree_connect_rsp {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 16 */
__u8 ShareType; /* see below */
__u8 Reserved;
__le32 ShareFlags; /* see below */
__le32 Capabilities; /* see below */
__le32 MaximalAccess;
} __packed;
/* Possible ShareType values */
#define SMB2_SHARE_TYPE_DISK 0x01
#define SMB2_SHARE_TYPE_PIPE 0x02
#define SMB2_SHARE_TYPE_PRINT 0x03
/*
* Possible ShareFlags - exactly one and only one of the first 4 caching flags
* must be set (any of the remaining, SHI1005, flags may be set individually
* or in combination.
*/
#define SMB2_SHAREFLAG_MANUAL_CACHING 0x00000000
#define SMB2_SHAREFLAG_AUTO_CACHING 0x00000010
#define SMB2_SHAREFLAG_VDO_CACHING 0x00000020
#define SMB2_SHAREFLAG_NO_CACHING 0x00000030
#define SHI1005_FLAGS_DFS 0x00000001
#define SHI1005_FLAGS_DFS_ROOT 0x00000002
#define SHI1005_FLAGS_RESTRICT_EXCLUSIVE_OPENS 0x00000100
#define SHI1005_FLAGS_FORCE_SHARED_DELETE 0x00000200
#define SHI1005_FLAGS_ALLOW_NAMESPACE_CACHING 0x00000400
#define SHI1005_FLAGS_ACCESS_BASED_DIRECTORY_ENUM 0x00000800
#define SHI1005_FLAGS_FORCE_LEVELII_OPLOCK 0x00001000
#define SHI1005_FLAGS_ENABLE_HASH 0x00002000
/* Possible share capabilities */
#define SMB2_SHARE_CAP_DFS cpu_to_le32(0x00000008)
struct smb2_tree_disconnect_req {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 4 */
__le16 Reserved;
} __packed;
struct smb2_tree_disconnect_rsp {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 4 */
__le16 Reserved;
} __packed;
#define ATTR_READONLY_LE cpu_to_le32(ATTR_READONLY)
#define ATTR_HIDDEN_LE cpu_to_le32(ATTR_HIDDEN)
#define ATTR_SYSTEM_LE cpu_to_le32(ATTR_SYSTEM)
#define ATTR_DIRECTORY_LE cpu_to_le32(ATTR_DIRECTORY)
#define ATTR_ARCHIVE_LE cpu_to_le32(ATTR_ARCHIVE)
#define ATTR_NORMAL_LE cpu_to_le32(ATTR_NORMAL)
#define ATTR_TEMPORARY_LE cpu_to_le32(ATTR_TEMPORARY)
#define ATTR_SPARSE_FILE_LE cpu_to_le32(ATTR_SPARSE)
#define ATTR_REPARSE_POINT_LE cpu_to_le32(ATTR_REPARSE)
#define ATTR_COMPRESSED_LE cpu_to_le32(ATTR_COMPRESSED)
#define ATTR_OFFLINE_LE cpu_to_le32(ATTR_OFFLINE)
#define ATTR_NOT_CONTENT_INDEXED_LE cpu_to_le32(ATTR_NOT_CONTENT_INDEXED)
#define ATTR_ENCRYPTED_LE cpu_to_le32(ATTR_ENCRYPTED)
#define ATTR_INTEGRITY_STREAML_LE cpu_to_le32(0x00008000)
#define ATTR_NO_SCRUB_DATA_LE cpu_to_le32(0x00020000)
#define ATTR_MASK_LE cpu_to_le32(0x00007FB7)
/* Oplock levels */
#define SMB2_OPLOCK_LEVEL_NONE 0x00
#define SMB2_OPLOCK_LEVEL_II 0x01
#define SMB2_OPLOCK_LEVEL_EXCLUSIVE 0x08
#define SMB2_OPLOCK_LEVEL_BATCH 0x09
#define SMB2_OPLOCK_LEVEL_LEASE 0xFF
/* Non-spec internal type */
#define SMB2_OPLOCK_LEVEL_NOCHANGE 0x99
/* Desired Access Flags */
#define FILE_READ_DATA_LE cpu_to_le32(0x00000001)
#define FILE_LIST_DIRECTORY_LE cpu_to_le32(0x00000001)
#define FILE_WRITE_DATA_LE cpu_to_le32(0x00000002)
#define FILE_ADD_FILE_LE cpu_to_le32(0x00000002)
#define FILE_APPEND_DATA_LE cpu_to_le32(0x00000004)
#define FILE_ADD_SUBDIRECTORY_LE cpu_to_le32(0x00000004)
#define FILE_READ_EA_LE cpu_to_le32(0x00000008)
#define FILE_WRITE_EA_LE cpu_to_le32(0x00000010)
#define FILE_EXECUTE_LE cpu_to_le32(0x00000020)
#define FILE_TRAVERSE_LE cpu_to_le32(0x00000020)
#define FILE_DELETE_CHILD_LE cpu_to_le32(0x00000040)
#define FILE_READ_ATTRIBUTES_LE cpu_to_le32(0x00000080)
#define FILE_WRITE_ATTRIBUTES_LE cpu_to_le32(0x00000100)
#define FILE_DELETE_LE cpu_to_le32(0x00010000)
#define FILE_READ_CONTROL_LE cpu_to_le32(0x00020000)
#define FILE_WRITE_DAC_LE cpu_to_le32(0x00040000)
#define FILE_WRITE_OWNER_LE cpu_to_le32(0x00080000)
#define FILE_SYNCHRONIZE_LE cpu_to_le32(0x00100000)
#define FILE_ACCESS_SYSTEM_SECURITY_LE cpu_to_le32(0x01000000)
#define FILE_MAXIMAL_ACCESS_LE cpu_to_le32(0x02000000)
#define FILE_GENERIC_ALL_LE cpu_to_le32(0x10000000)
#define FILE_GENERIC_EXECUTE_LE cpu_to_le32(0x20000000)
#define FILE_GENERIC_WRITE_LE cpu_to_le32(0x40000000)
#define FILE_GENERIC_READ_LE cpu_to_le32(0x80000000)
#define DESIRED_ACCESS_MASK cpu_to_le32(0xF21F01FF)
/* ShareAccess Flags */
#define FILE_SHARE_READ_LE cpu_to_le32(0x00000001)
#define FILE_SHARE_WRITE_LE cpu_to_le32(0x00000002)
#define FILE_SHARE_DELETE_LE cpu_to_le32(0x00000004)
#define FILE_SHARE_ALL_LE cpu_to_le32(0x00000007)
/* CreateDisposition Flags */
#define FILE_SUPERSEDE_LE cpu_to_le32(0x00000000)
#define FILE_OPEN_LE cpu_to_le32(0x00000001)
#define FILE_CREATE_LE cpu_to_le32(0x00000002)
#define FILE_OPEN_IF_LE cpu_to_le32(0x00000003)
#define FILE_OVERWRITE_LE cpu_to_le32(0x00000004)
#define FILE_OVERWRITE_IF_LE cpu_to_le32(0x00000005)
#define FILE_CREATE_MASK_LE cpu_to_le32(0x00000007)
#define FILE_READ_DESIRED_ACCESS_LE (FILE_READ_DATA_LE | \
FILE_READ_EA_LE | \
FILE_GENERIC_READ_LE)
#define FILE_WRITE_DESIRE_ACCESS_LE (FILE_WRITE_DATA_LE | \
FILE_APPEND_DATA_LE | \
FILE_WRITE_EA_LE | \
FILE_WRITE_ATTRIBUTES_LE | \
FILE_GENERIC_WRITE_LE)
/* Impersonation Levels */
#define IL_ANONYMOUS_LE cpu_to_le32(0x00000000)
#define IL_IDENTIFICATION_LE cpu_to_le32(0x00000001)
#define IL_IMPERSONATION_LE cpu_to_le32(0x00000002)
#define IL_DELEGATE_LE cpu_to_le32(0x00000003)
/* Create Context Values */
#define SMB2_CREATE_EA_BUFFER "ExtA" /* extended attributes */
#define SMB2_CREATE_SD_BUFFER "SecD" /* security descriptor */
#define SMB2_CREATE_DURABLE_HANDLE_REQUEST "DHnQ"
#define SMB2_CREATE_DURABLE_HANDLE_RECONNECT "DHnC"
#define SMB2_CREATE_ALLOCATION_SIZE "AlSi"
#define SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST "MxAc"
#define SMB2_CREATE_TIMEWARP_REQUEST "TWrp"
#define SMB2_CREATE_QUERY_ON_DISK_ID "QFid"
#define SMB2_CREATE_REQUEST_LEASE "RqLs"
#define SMB2_CREATE_DURABLE_HANDLE_REQUEST_V2 "DH2Q"
#define SMB2_CREATE_DURABLE_HANDLE_RECONNECT_V2 "DH2C"
#define SMB2_CREATE_APP_INSTANCE_ID "\x45\xBC\xA6\x6A\xEF\xA7\xF7\x4A\x90\x08\xFA\x46\x2E\x14\x4D\x74"
#define SMB2_CREATE_APP_INSTANCE_VERSION "\xB9\x82\xD0\xB7\x3B\x56\x07\x4F\xA0\x7B\x52\x4A\x81\x16\xA0\x10"
#define SVHDX_OPEN_DEVICE_CONTEXT 0x83CE6F1AD851E0986E34401CC9BCFCE9
#define SMB2_CREATE_TAG_POSIX "\x93\xAD\x25\x50\x9C\xB4\x11\xE7\xB4\x23\x83\xDE\x96\x8B\xCD\x7C"
struct smb2_create_req {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 57 */
__u8 SecurityFlags;
__u8 RequestedOplockLevel;
__le32 ImpersonationLevel;
__le64 SmbCreateFlags;
__le64 Reserved;
__le32 DesiredAccess;
__le32 FileAttributes;
__le32 ShareAccess;
__le32 CreateDisposition;
__le32 CreateOptions;
__le16 NameOffset;
__le16 NameLength;
__le32 CreateContextsOffset;
__le32 CreateContextsLength;
__u8 Buffer[0];
} __packed;
struct smb2_create_rsp {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 89 */
__u8 OplockLevel;
__u8 Reserved;
__le32 CreateAction;
__le64 CreationTime;
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le64 AllocationSize;
__le64 EndofFile;
__le32 FileAttributes;
__le32 Reserved2;
__le64 PersistentFileId;
__le64 VolatileFileId;
__le32 CreateContextsOffset;
__le32 CreateContextsLength;
__u8 Buffer[1];
} __packed;
struct create_context {
__le32 Next;
__le16 NameOffset;
__le16 NameLength;
__le16 Reserved;
__le16 DataOffset;
__le32 DataLength;
__u8 Buffer[0];
} __packed;
struct create_durable_req_v2 {
struct create_context ccontext;
__u8 Name[8];
......@@ -743,22 +216,21 @@ struct create_posix_rsp {
#define SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE cpu_to_le32(0x02)
#define SMB2_LEASE_KEY_SIZE 16
struct lease_context {
__le64 LeaseKeyLow;
__le64 LeaseKeyHigh;
__u8 LeaseKey[SMB2_LEASE_KEY_SIZE];
__le32 LeaseState;
__le32 LeaseFlags;
__le64 LeaseDuration;
} __packed;
struct lease_context_v2 {
__le64 LeaseKeyLow;
__le64 LeaseKeyHigh;
__u8 LeaseKey[SMB2_LEASE_KEY_SIZE];
__le32 LeaseState;
__le32 LeaseFlags;
__le64 LeaseDuration;
__le64 ParentLeaseKeyLow;
__le64 ParentLeaseKeyHigh;
__u8 ParentLeaseKey[SMB2_LEASE_KEY_SIZE];
__le16 Epoch;
__le16 Reserved;
} __packed;
......@@ -776,114 +248,12 @@ struct create_lease_v2 {
__u8 Pad[4];
} __packed;
/* Currently defined values for close flags */
#define SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB cpu_to_le16(0x0001)
struct smb2_close_req {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 24 */
__le16 Flags;
__le32 Reserved;
__le64 PersistentFileId;
__le64 VolatileFileId;
} __packed;
struct smb2_close_rsp {
struct smb2_hdr hdr;
__le16 StructureSize; /* 60 */
__le16 Flags;
__le32 Reserved;
__le64 CreationTime;
__le64 LastAccessTime;
__le64 LastWriteTime;
__le64 ChangeTime;
__le64 AllocationSize; /* Beginning of FILE_STANDARD_INFO equivalent */
__le64 EndOfFile;
__le32 Attributes;
} __packed;
struct smb2_flush_req {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 24 */
__le16 Reserved1;
__le32 Reserved2;
__le64 PersistentFileId;
__le64 VolatileFileId;
} __packed;
struct smb2_flush_rsp {
struct smb2_hdr hdr;
__le16 StructureSize;
__le16 Reserved;
} __packed;
struct smb2_buffer_desc_v1 {
__le64 offset;
__le32 token;
__le32 length;
} __packed;
#define SMB2_CHANNEL_NONE cpu_to_le32(0x00000000)
#define SMB2_CHANNEL_RDMA_V1 cpu_to_le32(0x00000001)
#define SMB2_CHANNEL_RDMA_V1_INVALIDATE cpu_to_le32(0x00000002)
struct smb2_read_req {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 49 */
__u8 Padding; /* offset from start of SMB2 header to place read */
__u8 Reserved;
__le32 Length;
__le64 Offset;
__le64 PersistentFileId;
__le64 VolatileFileId;
__le32 MinimumCount;
__le32 Channel; /* Reserved MBZ */
__le32 RemainingBytes;
__le16 ReadChannelInfoOffset; /* Reserved MBZ */
__le16 ReadChannelInfoLength; /* Reserved MBZ */
__u8 Buffer[1];
} __packed;
struct smb2_read_rsp {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 17 */
__u8 DataOffset;
__u8 Reserved;
__le32 DataLength;
__le32 DataRemaining;
__u32 Reserved2;
__u8 Buffer[1];
} __packed;
/* For write request Flags field below the following flag is defined: */
#define SMB2_WRITEFLAG_WRITE_THROUGH 0x00000001
struct smb2_write_req {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 49 */
__le16 DataOffset; /* offset from start of SMB2 header to write data */
__le32 Length;
__le64 Offset;
__le64 PersistentFileId;
__le64 VolatileFileId;
__le32 Channel; /* Reserved MBZ */
__le32 RemainingBytes;
__le16 WriteChannelInfoOffset; /* Reserved MBZ */
__le16 WriteChannelInfoLength; /* Reserved MBZ */
__le32 Flags;
__u8 Buffer[1];
} __packed;
struct smb2_write_rsp {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 17 */
__u8 DataOffset;
__u8 Reserved;
__le32 DataLength;
__le32 DataRemaining;
__u32 Reserved2;
__u8 Buffer[1];
} __packed;
#define SMB2_0_IOCTL_IS_FSCTL 0x00000001
struct duplicate_extents_to_file {
......@@ -1033,43 +403,6 @@ struct reparse_data_buffer {
__u8 DataBuffer[]; /* Variable Length */
} __packed;
/* Completion Filter flags for Notify */
#define FILE_NOTIFY_CHANGE_FILE_NAME 0x00000001
#define FILE_NOTIFY_CHANGE_DIR_NAME 0x00000002
#define FILE_NOTIFY_CHANGE_NAME 0x00000003
#define FILE_NOTIFY_CHANGE_ATTRIBUTES 0x00000004
#define FILE_NOTIFY_CHANGE_SIZE 0x00000008
#define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
#define FILE_NOTIFY_CHANGE_LAST_ACCESS 0x00000020
#define FILE_NOTIFY_CHANGE_CREATION 0x00000040
#define FILE_NOTIFY_CHANGE_EA 0x00000080
#define FILE_NOTIFY_CHANGE_SECURITY 0x00000100
#define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200
#define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400
#define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800
/* Flags */
#define SMB2_WATCH_TREE 0x0001
struct smb2_notify_req {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 32 */
__le16 Flags;
__le32 OutputBufferLength;
__le64 PersistentFileId;
__le64 VolatileFileId;
__u32 CompletionFileter;
__u32 Reserved;
} __packed;
struct smb2_notify_rsp {
struct smb2_hdr hdr;
__le16 StructureSize; /* Must be 9 */
__le16 OutputBufferOffset;
__le32 OutputBufferLength;
__u8 Buffer[1];
} __packed;
/* SMB2 Notify Action Flags */
#define FILE_ACTION_ADDED 0x00000001
#define FILE_ACTION_REMOVED 0x00000002
......@@ -1528,7 +861,7 @@ struct smb2_file_pos_info {
__le64 CurrentByteOffset;
} __packed;
#define FILE_MODE_INFO_MASK cpu_to_le32(0x0000103e)
#define FILE_MODE_INFO_MASK cpu_to_le32(0x0000100e)
struct smb2_file_mode_info {
__le32 Mode;
......@@ -1705,4 +1038,13 @@ int smb2_ioctl(struct ksmbd_work *work);
int smb2_oplock_break(struct ksmbd_work *work);
int smb2_notify(struct ksmbd_work *ksmbd_work);
/*
* Get the body of the smb2 message excluding the 4 byte rfc1002 headers
* from request/response buffer.
*/
static inline void *smb2_get_msg(void *buf)
{
return buf + 4;
}
#endif /* _SMB2PDU_H */
......@@ -132,7 +132,7 @@ int ksmbd_lookup_protocol_idx(char *str)
*/
int ksmbd_verify_smb_message(struct ksmbd_work *work)
{
struct smb2_hdr *smb2_hdr = work->request_buf + work->next_smb2_rcv_hdr_off;
struct smb2_hdr *smb2_hdr = ksmbd_req_buf_next(work);
struct smb_hdr *hdr;
if (smb2_hdr->ProtocolId == SMB2_PROTO_NUMBER)
......@@ -239,14 +239,14 @@ int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count)
static int ksmbd_negotiate_smb_dialect(void *buf)
{
int smb_buf_length = get_rfc1002_len(buf);
__le32 proto = ((struct smb2_hdr *)buf)->ProtocolId;
__le32 proto = ((struct smb2_hdr *)smb2_get_msg(buf))->ProtocolId;
if (proto == SMB2_PROTO_NUMBER) {
struct smb2_negotiate_req *req;
int smb2_neg_size =
offsetof(struct smb2_negotiate_req, Dialects) - 4;
offsetof(struct smb2_negotiate_req, Dialects);
req = (struct smb2_negotiate_req *)buf;
req = (struct smb2_negotiate_req *)smb2_get_msg(buf);
if (smb2_neg_size > smb_buf_length)
goto err_out;
......@@ -445,11 +445,12 @@ int ksmbd_smb_negotiate_common(struct ksmbd_work *work, unsigned int command)
struct ksmbd_conn *conn = work->conn;
int ret;
conn->dialect = ksmbd_negotiate_smb_dialect(work->request_buf);
conn->dialect =
ksmbd_negotiate_smb_dialect(work->request_buf);
ksmbd_debug(SMB, "conn->dialect 0x%x\n", conn->dialect);
if (command == SMB2_NEGOTIATE_HE) {
struct smb2_hdr *smb2_hdr = work->request_buf;
struct smb2_hdr *smb2_hdr = smb2_get_msg(work->request_buf);
if (smb2_hdr->ProtocolId != SMB2_PROTO_NUMBER) {
ksmbd_debug(SMB, "Downgrade to SMB1 negotiation\n");
......
......@@ -10,6 +10,7 @@
#include "glob.h"
#include "nterr.h"
#include "../smbfs_common/smb2pdu.h"
#include "smb2pdu.h"
/* ksmbd's Specific ERRNO */
......@@ -32,17 +33,6 @@
#define SMB302_VERSION_STRING "3.02"
#define SMB311_VERSION_STRING "3.1.1"
/* Dialects */
#define SMB10_PROT_ID 0x00
#define SMB20_PROT_ID 0x0202
#define SMB21_PROT_ID 0x0210
/* multi-protocol negotiate request */
#define SMB2X_PROT_ID 0x02FF
#define SMB30_PROT_ID 0x0300
#define SMB302_PROT_ID 0x0302
#define SMB311_PROT_ID 0x0311
#define BAD_PROT_ID 0xFFFF
#define SMB_ECHO_INTERVAL (60 * HZ)
#define CIFS_DEFAULT_IOSIZE (64 * 1024)
......@@ -59,21 +49,6 @@
/*
* File Attribute flags
*/
#define ATTR_READONLY 0x0001
#define ATTR_HIDDEN 0x0002
#define ATTR_SYSTEM 0x0004
#define ATTR_VOLUME 0x0008
#define ATTR_DIRECTORY 0x0010
#define ATTR_ARCHIVE 0x0020
#define ATTR_DEVICE 0x0040
#define ATTR_NORMAL 0x0080
#define ATTR_TEMPORARY 0x0100
#define ATTR_SPARSE 0x0200
#define ATTR_REPARSE 0x0400
#define ATTR_COMPRESSED 0x0800
#define ATTR_OFFLINE 0x1000
#define ATTR_NOT_CONTENT_INDEXED 0x2000
#define ATTR_ENCRYPTED 0x4000
#define ATTR_POSIX_SEMANTICS 0x01000000
#define ATTR_BACKUP_SEMANTICS 0x02000000
#define ATTR_DELETE_ON_CLOSE 0x04000000
......@@ -82,23 +57,6 @@
#define ATTR_NO_BUFFERING 0x20000000
#define ATTR_WRITE_THROUGH 0x80000000
#define ATTR_READONLY_LE cpu_to_le32(ATTR_READONLY)
#define ATTR_HIDDEN_LE cpu_to_le32(ATTR_HIDDEN)
#define ATTR_SYSTEM_LE cpu_to_le32(ATTR_SYSTEM)
#define ATTR_DIRECTORY_LE cpu_to_le32(ATTR_DIRECTORY)
#define ATTR_ARCHIVE_LE cpu_to_le32(ATTR_ARCHIVE)
#define ATTR_NORMAL_LE cpu_to_le32(ATTR_NORMAL)
#define ATTR_TEMPORARY_LE cpu_to_le32(ATTR_TEMPORARY)
#define ATTR_SPARSE_FILE_LE cpu_to_le32(ATTR_SPARSE)
#define ATTR_REPARSE_POINT_LE cpu_to_le32(ATTR_REPARSE)
#define ATTR_COMPRESSED_LE cpu_to_le32(ATTR_COMPRESSED)
#define ATTR_OFFLINE_LE cpu_to_le32(ATTR_OFFLINE)
#define ATTR_NOT_CONTENT_INDEXED_LE cpu_to_le32(ATTR_NOT_CONTENT_INDEXED)
#define ATTR_ENCRYPTED_LE cpu_to_le32(ATTR_ENCRYPTED)
#define ATTR_INTEGRITY_STREAML_LE cpu_to_le32(0x00008000)
#define ATTR_NO_SCRUB_DATA_LE cpu_to_le32(0x00020000)
#define ATTR_MASK_LE cpu_to_le32(0x00007FB7)
/* 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 */
......@@ -160,11 +118,6 @@
/* file_execute, file_read_attributes*/
/* write_dac, and delete. */
#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_READ_RIGHTS (FILE_READ_DATA | FILE_READ_EA \
| FILE_READ_ATTRIBUTES \
| DELETE | READ_CONTROL | WRITE_DAC \
......@@ -477,12 +430,6 @@ struct smb_version_cmds {
int (*proc)(struct ksmbd_work *swork);
};
static inline size_t
smb2_hdr_size_no_buflen(struct smb_version_values *vals)
{
return vals->header_size - 4;
}
int ksmbd_min_protocol(void);
int ksmbd_max_protocol(void);
......
......@@ -484,7 +484,7 @@ static int smb_direct_check_recvmsg(struct smb_direct_recvmsg *recvmsg)
struct smb_direct_data_transfer *req =
(struct smb_direct_data_transfer *)recvmsg->packet;
struct smb2_hdr *hdr = (struct smb2_hdr *)(recvmsg->packet
+ le32_to_cpu(req->data_offset) - 4);
+ le32_to_cpu(req->data_offset));
ksmbd_debug(RDMA,
"CreditGranted: %u, CreditRequested: %u, DataLength: %u, RemainingDataLength: %u, SMB: %x, Command: %u\n",
le16_to_cpu(req->credits_granted),
......@@ -2043,7 +2043,6 @@ int ksmbd_rdma_destroy(void)
smb_direct_listener.cm_id = NULL;
if (smb_direct_wq) {
flush_workqueue(smb_direct_wq);
destroy_workqueue(smb_direct_wq);
smb_direct_wq = NULL;
}
......
......@@ -1013,7 +1013,7 @@ int ksmbd_vfs_zero_data(struct ksmbd_work *work, struct ksmbd_file *fp,
loff_t off, loff_t len)
{
smb_break_all_levII_oplock(work, fp, 1);
if (fp->f_ci->m_fattr & ATTR_SPARSE_FILE_LE)
if (fp->f_ci->m_fattr & FILE_ATTRIBUTE_SPARSE_FILE_LE)
return vfs_fallocate(fp->filp,
FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
off, len);
......@@ -1624,7 +1624,7 @@ void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat)
time = ksmbd_UnixTimeToNT(kstat->ctime);
info->ChangeTime = cpu_to_le64(time);
if (ksmbd_kstat->file_attributes & ATTR_DIRECTORY_LE) {
if (ksmbd_kstat->file_attributes & FILE_ATTRIBUTE_DIRECTORY_LE) {
info->EndOfFile = 0;
info->AllocationSize = 0;
} else {
......@@ -1654,9 +1654,9 @@ int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work,
* or that acl is disable in server's filesystem and the config is yes.
*/
if (S_ISDIR(ksmbd_kstat->kstat->mode))
ksmbd_kstat->file_attributes = ATTR_DIRECTORY_LE;
ksmbd_kstat->file_attributes = FILE_ATTRIBUTE_DIRECTORY_LE;
else
ksmbd_kstat->file_attributes = ATTR_ARCHIVE_LE;
ksmbd_kstat->file_attributes = FILE_ATTRIBUTE_ARCHIVE_LE;
if (test_share_config_flag(work->tcon->share_conf,
KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) {
......
......@@ -25,48 +25,9 @@ enum {
};
/* CreateOptions */
/* Flag is set, it must not be a file , valid for directory only */
#define FILE_DIRECTORY_FILE_LE cpu_to_le32(0x00000001)
#define FILE_WRITE_THROUGH_LE cpu_to_le32(0x00000002)
#define FILE_SEQUENTIAL_ONLY_LE cpu_to_le32(0x00000004)
/* Should not buffer on server*/
#define FILE_NO_INTERMEDIATE_BUFFERING_LE cpu_to_le32(0x00000008)
/* MBZ */
#define FILE_SYNCHRONOUS_IO_ALERT_LE cpu_to_le32(0x00000010)
/* MBZ */
#define FILE_SYNCHRONOUS_IO_NONALERT_LE cpu_to_le32(0x00000020)
/* Flaf must not be set for directory */
#define FILE_NON_DIRECTORY_FILE_LE cpu_to_le32(0x00000040)
/* Should be zero */
#define CREATE_TREE_CONNECTION cpu_to_le32(0x00000080)
#define FILE_COMPLETE_IF_OPLOCKED_LE cpu_to_le32(0x00000100)
#define FILE_NO_EA_KNOWLEDGE_LE cpu_to_le32(0x00000200)
#define FILE_OPEN_REMOTE_INSTANCE cpu_to_le32(0x00000400)
/**
* Doc says this is obsolete "open for recovery" flag should be zero
* in any case.
*/
#define CREATE_OPEN_FOR_RECOVERY cpu_to_le32(0x00000400)
#define FILE_RANDOM_ACCESS_LE cpu_to_le32(0x00000800)
#define FILE_DELETE_ON_CLOSE_LE cpu_to_le32(0x00001000)
#define FILE_OPEN_BY_FILE_ID_LE cpu_to_le32(0x00002000)
#define FILE_OPEN_FOR_BACKUP_INTENT_LE cpu_to_le32(0x00004000)
#define FILE_NO_COMPRESSION_LE cpu_to_le32(0x00008000)
/* Should be zero*/
#define FILE_OPEN_REQUIRING_OPLOCK cpu_to_le32(0x00010000)
#define FILE_DISALLOW_EXCLUSIVE cpu_to_le32(0x00020000)
#define FILE_RESERVE_OPFILTER_LE cpu_to_le32(0x00100000)
#define FILE_OPEN_REPARSE_POINT_LE cpu_to_le32(0x00200000)
#define FILE_OPEN_NO_RECALL_LE cpu_to_le32(0x00400000)
/* Should be zero */
#define FILE_OPEN_FOR_FREE_SPACE_QUERY_LE cpu_to_le32(0x00800000)
#define CREATE_OPTIONS_MASK cpu_to_le32(0x00FFFFFF)
#define CREATE_OPTION_READONLY 0x10000000
/* system. NB not sent over wire */
#define CREATE_OPTION_SPECIAL 0x20000000
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册