Skip to content

Commit

Permalink
ksmbd: check outstanding simultaneous SMB operations
Browse files Browse the repository at this point in the history
Signed-off-by: Namjae Jeon <[email protected]>
  • Loading branch information
namjaejeon committed Nov 4, 2024
1 parent 877b368 commit 76046e5
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 10 deletions.
1 change: 1 addition & 0 deletions connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
atomic_set(&conn->req_running, 0);
atomic_set(&conn->r_count, 0);
atomic_set(&conn->refcnt, 1);
atomic_set(&conn->mux_smb_requests, 0);
conn->total_credits = 1;
conn->outstanding_credits = 0;

Expand Down
1 change: 1 addition & 0 deletions connection.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ struct ksmbd_conn {
__le16 signing_algorithm;
bool binding;
atomic_t refcnt;
atomic_t mux_smb_requests;
};

struct ksmbd_conn_ops {
Expand Down
16 changes: 10 additions & 6 deletions server.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ static void handle_ksmbd_work(struct work_struct *wk)

ksmbd_conn_try_dequeue_request(work);
ksmbd_free_work_struct(work);
atomic_dec(&conn->mux_smb_requests);
/*
* Checking waitqueue to dropping pending requests on
* disconnection. waitqueue_active is safe because it
Expand All @@ -291,6 +292,15 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
struct ksmbd_work *work;
int err;

err = ksmbd_init_smb_server(conn);
if (err)
return 0;

if (atomic_inc_return(&conn->mux_smb_requests) >= conn->vals->max_credits) {
atomic_dec_return(&conn->mux_smb_requests);
return ENOSPC;
}

work = ksmbd_alloc_work_struct();
if (!work) {
pr_err("allocation for work failed\n");
Expand All @@ -301,12 +311,6 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
work->request_buf = conn->request_buf;
conn->request_buf = NULL;

err = ksmbd_init_smb_server(work);
if (err) {
ksmbd_free_work_struct(work);
return 0;
}

ksmbd_conn_enqueue_request(work);
atomic_inc(&conn->r_count);
/* update activity on connection */
Expand Down
1 change: 1 addition & 0 deletions smb1ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ static struct smb_version_values smb1_server_values = {
.cap_large_files = CAP_LARGE_FILES,
.signing_enabled = SECMODE_SIGN_ENABLED,
.signing_required = SECMODE_SIGN_REQUIRED,
.max_credits = SMB2_MAX_CREDITS,
};

static struct smb_version_ops smb1_server_ops = {
Expand Down
10 changes: 7 additions & 3 deletions smb_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,10 @@ static struct smb_version_ops smb1_server_ops = {
.set_rsp_status = set_smb1_rsp_status,
};

static struct smb_version_values smb1_server_values = {
.max_credits = SMB2_MAX_CREDITS,
};

static int smb1_negotiate(struct ksmbd_work *work)
{
return ksmbd_smb_negotiate_common(work, SMB_COM_NEGOTIATE);
Expand All @@ -436,19 +440,19 @@ static struct smb_version_cmds smb1_server_cmds[1] = {

static int init_smb1_server(struct ksmbd_conn *conn)
{
conn->vals = &smb1_server_values;
conn->ops = &smb1_server_ops;
conn->cmds = smb1_server_cmds;
conn->max_cmds = ARRAY_SIZE(smb1_server_cmds);
return 0;
}
#endif

int ksmbd_init_smb_server(struct ksmbd_work *work)
int ksmbd_init_smb_server(struct ksmbd_conn *conn)
{
struct ksmbd_conn *conn = work->conn;
__le32 proto;

proto = *(__le32 *)((struct smb_hdr *)work->request_buf)->Protocol;
proto = *(__le32 *)((struct smb_hdr *)conn->request_buf)->Protocol;
if (conn->need_neg == false) {
if (proto == SMB1_PROTO_NUMBER)
return -EINVAL;
Expand Down
2 changes: 1 addition & 1 deletion smb_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ bool ksmbd_smb_request(struct ksmbd_conn *conn);

int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count);

int ksmbd_init_smb_server(struct ksmbd_work *work);
int ksmbd_init_smb_server(struct ksmbd_conn *conn);

bool ksmbd_pdu_size_has_room(unsigned int pdu);

Expand Down

0 comments on commit 76046e5

Please sign in to comment.