Skip to content

Commit 53ec4a7

Browse files
committed
Merge tag 'v6.19-rc1-ksmbd-server-fixes' of git://git.samba.org/ksmbd
Pull smb server fixes from Steve French: - Fix set xattr name validation - Fix session refcount leak - Minor cleanup - smbdirect (RDMA) fixes: improve receive completion, and connect * tag 'v6.19-rc1-ksmbd-server-fixes' of git://git.samba.org/ksmbd: ksmbd: fix buffer validation by including null terminator size in EA length ksmbd: Fix refcount leak when invalid session is found on session lookup ksmbd: remove redundant DACL check in smb_check_perm_dacl ksmbd: convert comma to semicolon smb: server: defer the initial recv completion logic to smb_direct_negotiate_recv_work() smb: server: initialize recv_io->cqe.done = recv_done just once smb: smbdirect: introduce smbdirect_socket.connect.{lock,work}
2 parents 115fada + 95d7a89 commit 53ec4a7

6 files changed

Lines changed: 164 additions & 36 deletions

File tree

fs/smb/common/smbdirect/smbdirect_socket.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,14 @@ struct smbdirect_socket {
132132

133133
struct smbdirect_socket_parameters parameters;
134134

135+
/*
136+
* The state for connect/negotiation
137+
*/
138+
struct {
139+
spinlock_t lock;
140+
struct work_struct work;
141+
} connect;
142+
135143
/*
136144
* The state for keepalive and timeout handling
137145
*/
@@ -353,6 +361,10 @@ static __always_inline void smbdirect_socket_init(struct smbdirect_socket *sc)
353361
INIT_WORK(&sc->disconnect_work, __smbdirect_socket_disabled_work);
354362
disable_work_sync(&sc->disconnect_work);
355363

364+
spin_lock_init(&sc->connect.lock);
365+
INIT_WORK(&sc->connect.work, __smbdirect_socket_disabled_work);
366+
disable_work_sync(&sc->connect.work);
367+
356368
INIT_WORK(&sc->idle.immediate_work, __smbdirect_socket_disabled_work);
357369
disable_work_sync(&sc->idle.immediate_work);
358370
INIT_DELAYED_WORK(&sc->idle.timer_work, __smbdirect_socket_disabled_work);

fs/smb/server/mgmt/user_session.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,10 @@ struct ksmbd_session *ksmbd_session_lookup_all(struct ksmbd_conn *conn,
325325
sess = ksmbd_session_lookup(conn, id);
326326
if (!sess && conn->binding)
327327
sess = ksmbd_session_lookup_slowpath(id);
328-
if (sess && sess->state != SMB2_SESSION_VALID)
328+
if (sess && sess->state != SMB2_SESSION_VALID) {
329+
ksmbd_user_session_put(sess);
329330
sess = NULL;
331+
}
330332
return sess;
331333
}
332334

fs/smb/server/smb2pdu.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2363,7 +2363,7 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
23632363
int rc = 0;
23642364
unsigned int next = 0;
23652365

2366-
if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength +
2366+
if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + 1 +
23672367
le16_to_cpu(eabuf->EaValueLength))
23682368
return -EINVAL;
23692369

@@ -2440,7 +2440,7 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
24402440
break;
24412441
}
24422442

2443-
if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength +
2443+
if (buf_len < sizeof(struct smb2_ea_info) + eabuf->EaNameLength + 1 +
24442444
le16_to_cpu(eabuf->EaValueLength)) {
24452445
rc = -EINVAL;
24462446
break;

fs/smb/server/smbacl.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,9 +1307,6 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
13071307
granted |= le32_to_cpu(ace->access_req);
13081308
ace = (struct smb_ace *)((char *)ace + le16_to_cpu(ace->size));
13091309
}
1310-
1311-
if (!pdacl->num_aces)
1312-
granted = GENERIC_ALL_FLAGS;
13131310
}
13141311

13151312
if (!uid)

fs/smb/server/transport_rdma.c

Lines changed: 146 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ static void smb_direct_disconnect_rdma_work(struct work_struct *work)
242242
* disable[_delayed]_work_sync()
243243
*/
244244
disable_work(&sc->disconnect_work);
245+
disable_work(&sc->connect.work);
245246
disable_work(&sc->recv_io.posted.refill_work);
246247
disable_delayed_work(&sc->idle.timer_work);
247248
disable_work(&sc->idle.immediate_work);
@@ -297,6 +298,7 @@ smb_direct_disconnect_rdma_connection(struct smbdirect_socket *sc)
297298
* not queued again but here we don't block and avoid
298299
* disable[_delayed]_work_sync()
299300
*/
301+
disable_work(&sc->connect.work);
300302
disable_work(&sc->recv_io.posted.refill_work);
301303
disable_work(&sc->idle.immediate_work);
302304
disable_delayed_work(&sc->idle.timer_work);
@@ -467,6 +469,7 @@ static void free_transport(struct smb_direct_transport *t)
467469
*/
468470
smb_direct_disconnect_wake_up_all(sc);
469471

472+
disable_work_sync(&sc->connect.work);
470473
disable_work_sync(&sc->recv_io.posted.refill_work);
471474
disable_delayed_work_sync(&sc->idle.timer_work);
472475
disable_work_sync(&sc->idle.immediate_work);
@@ -635,28 +638,8 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
635638

636639
switch (sc->recv_io.expected) {
637640
case SMBDIRECT_EXPECT_NEGOTIATE_REQ:
638-
if (wc->byte_len < sizeof(struct smbdirect_negotiate_req)) {
639-
put_recvmsg(sc, recvmsg);
640-
smb_direct_disconnect_rdma_connection(sc);
641-
return;
642-
}
643-
sc->recv_io.reassembly.full_packet_received = true;
644-
/*
645-
* Some drivers (at least mlx5_ib) might post a
646-
* recv completion before RDMA_CM_EVENT_ESTABLISHED,
647-
* we need to adjust our expectation in that case.
648-
*/
649-
if (!sc->first_error && sc->status == SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING)
650-
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED;
651-
if (SMBDIRECT_CHECK_STATUS_WARN(sc, SMBDIRECT_SOCKET_NEGOTIATE_NEEDED)) {
652-
put_recvmsg(sc, recvmsg);
653-
smb_direct_disconnect_rdma_connection(sc);
654-
return;
655-
}
656-
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING;
657-
enqueue_reassembly(sc, recvmsg, 0);
658-
wake_up(&sc->status_wait);
659-
return;
641+
/* see smb_direct_negotiate_recv_done */
642+
break;
660643
case SMBDIRECT_EXPECT_DATA_TRANSFER: {
661644
struct smbdirect_data_transfer *data_transfer =
662645
(struct smbdirect_data_transfer *)recvmsg->packet;
@@ -742,6 +725,126 @@ static void recv_done(struct ib_cq *cq, struct ib_wc *wc)
742725
smb_direct_disconnect_rdma_connection(sc);
743726
}
744727

728+
static void smb_direct_negotiate_recv_work(struct work_struct *work);
729+
730+
static void smb_direct_negotiate_recv_done(struct ib_cq *cq, struct ib_wc *wc)
731+
{
732+
struct smbdirect_recv_io *recv_io =
733+
container_of(wc->wr_cqe, struct smbdirect_recv_io, cqe);
734+
struct smbdirect_socket *sc = recv_io->socket;
735+
unsigned long flags;
736+
737+
/*
738+
* reset the common recv_done for later reuse.
739+
*/
740+
recv_io->cqe.done = recv_done;
741+
742+
if (wc->status != IB_WC_SUCCESS || wc->opcode != IB_WC_RECV) {
743+
put_recvmsg(sc, recv_io);
744+
if (wc->status != IB_WC_WR_FLUSH_ERR) {
745+
pr_err("Negotiate Recv error. status='%s (%d)' opcode=%d\n",
746+
ib_wc_status_msg(wc->status), wc->status,
747+
wc->opcode);
748+
smb_direct_disconnect_rdma_connection(sc);
749+
}
750+
return;
751+
}
752+
753+
ksmbd_debug(RDMA, "Negotiate Recv completed. status='%s (%d)', opcode=%d\n",
754+
ib_wc_status_msg(wc->status), wc->status,
755+
wc->opcode);
756+
757+
ib_dma_sync_single_for_cpu(sc->ib.dev,
758+
recv_io->sge.addr,
759+
recv_io->sge.length,
760+
DMA_FROM_DEVICE);
761+
762+
/*
763+
* This is an internal error!
764+
*/
765+
if (WARN_ON_ONCE(sc->recv_io.expected != SMBDIRECT_EXPECT_NEGOTIATE_REQ)) {
766+
put_recvmsg(sc, recv_io);
767+
smb_direct_disconnect_rdma_connection(sc);
768+
return;
769+
}
770+
771+
/*
772+
* Don't reset timer to the keepalive interval in
773+
* this will be done in smb_direct_negotiate_recv_work.
774+
*/
775+
776+
/*
777+
* Only remember the recv_io if it has enough bytes,
778+
* this gives smb_direct_negotiate_recv_work enough
779+
* information in order to disconnect if it was not
780+
* valid.
781+
*/
782+
sc->recv_io.reassembly.full_packet_received = true;
783+
if (wc->byte_len >= sizeof(struct smbdirect_negotiate_req))
784+
enqueue_reassembly(sc, recv_io, 0);
785+
else
786+
put_recvmsg(sc, recv_io);
787+
788+
/*
789+
* Some drivers (at least mlx5_ib and irdma in roce mode)
790+
* might post a recv completion before RDMA_CM_EVENT_ESTABLISHED,
791+
* we need to adjust our expectation in that case.
792+
*
793+
* So we defer further processing of the negotiation
794+
* to smb_direct_negotiate_recv_work().
795+
*
796+
* If we are already in SMBDIRECT_SOCKET_NEGOTIATE_NEEDED
797+
* we queue the work directly otherwise
798+
* smb_direct_cm_handler() will do it, when
799+
* RDMA_CM_EVENT_ESTABLISHED arrived.
800+
*/
801+
spin_lock_irqsave(&sc->connect.lock, flags);
802+
if (!sc->first_error) {
803+
INIT_WORK(&sc->connect.work, smb_direct_negotiate_recv_work);
804+
if (sc->status == SMBDIRECT_SOCKET_NEGOTIATE_NEEDED)
805+
queue_work(sc->workqueue, &sc->connect.work);
806+
}
807+
spin_unlock_irqrestore(&sc->connect.lock, flags);
808+
}
809+
810+
static void smb_direct_negotiate_recv_work(struct work_struct *work)
811+
{
812+
struct smbdirect_socket *sc =
813+
container_of(work, struct smbdirect_socket, connect.work);
814+
const struct smbdirect_socket_parameters *sp = &sc->parameters;
815+
struct smbdirect_recv_io *recv_io;
816+
817+
if (sc->first_error)
818+
return;
819+
820+
ksmbd_debug(RDMA, "Negotiate Recv Work running\n");
821+
822+
/*
823+
* Reset timer to the keepalive interval in
824+
* order to trigger our next keepalive message.
825+
*/
826+
sc->idle.keepalive = SMBDIRECT_KEEPALIVE_NONE;
827+
mod_delayed_work(sc->workqueue, &sc->idle.timer_work,
828+
msecs_to_jiffies(sp->keepalive_interval_msec));
829+
830+
/*
831+
* If smb_direct_negotiate_recv_done() detected an
832+
* invalid request we want to disconnect.
833+
*/
834+
recv_io = get_first_reassembly(sc);
835+
if (!recv_io) {
836+
smb_direct_disconnect_rdma_connection(sc);
837+
return;
838+
}
839+
840+
if (SMBDIRECT_CHECK_STATUS_WARN(sc, SMBDIRECT_SOCKET_NEGOTIATE_NEEDED)) {
841+
smb_direct_disconnect_rdma_connection(sc);
842+
return;
843+
}
844+
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_RUNNING;
845+
wake_up(&sc->status_wait);
846+
}
847+
745848
static int smb_direct_post_recv(struct smbdirect_socket *sc,
746849
struct smbdirect_recv_io *recvmsg)
747850
{
@@ -758,7 +861,6 @@ static int smb_direct_post_recv(struct smbdirect_socket *sc,
758861
return ret;
759862
recvmsg->sge.length = sp->max_recv_size;
760863
recvmsg->sge.lkey = sc->ib.pd->local_dma_lkey;
761-
recvmsg->cqe.done = recv_done;
762864

763865
wr.wr_cqe = &recvmsg->cqe;
764866
wr.next = NULL;
@@ -1732,25 +1834,35 @@ static int smb_direct_cm_handler(struct rdma_cm_id *cm_id,
17321834
struct rdma_cm_event *event)
17331835
{
17341836
struct smbdirect_socket *sc = cm_id->context;
1837+
unsigned long flags;
17351838

17361839
ksmbd_debug(RDMA, "RDMA CM event. cm_id=%p event=%s (%d)\n",
17371840
cm_id, rdma_event_msg(event->event), event->event);
17381841

17391842
switch (event->event) {
17401843
case RDMA_CM_EVENT_ESTABLISHED: {
17411844
/*
1742-
* Some drivers (at least mlx5_ib) might post a
1743-
* recv completion before RDMA_CM_EVENT_ESTABLISHED,
1845+
* Some drivers (at least mlx5_ib and irdma in roce mode)
1846+
* might post a recv completion before RDMA_CM_EVENT_ESTABLISHED,
17441847
* we need to adjust our expectation in that case.
17451848
*
1746-
* As we already started the negotiation, we just
1747-
* ignore RDMA_CM_EVENT_ESTABLISHED here.
1849+
* If smb_direct_negotiate_recv_done was called first
1850+
* it initialized sc->connect.work only for us to
1851+
* start, so that we turned into
1852+
* SMBDIRECT_SOCKET_NEGOTIATE_NEEDED, before
1853+
* smb_direct_negotiate_recv_work() runs.
1854+
*
1855+
* If smb_direct_negotiate_recv_done didn't happen
1856+
* yet. sc->connect.work is still be disabled and
1857+
* queue_work() is a no-op.
17481858
*/
1749-
if (!sc->first_error && sc->status > SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING)
1750-
break;
17511859
if (SMBDIRECT_CHECK_STATUS_DISCONNECT(sc, SMBDIRECT_SOCKET_RDMA_CONNECT_RUNNING))
17521860
break;
17531861
sc->status = SMBDIRECT_SOCKET_NEGOTIATE_NEEDED;
1862+
spin_lock_irqsave(&sc->connect.lock, flags);
1863+
if (!sc->first_error)
1864+
queue_work(sc->workqueue, &sc->connect.work);
1865+
spin_unlock_irqrestore(&sc->connect.lock, flags);
17541866
wake_up(&sc->status_wait);
17551867
break;
17561868
}
@@ -1921,6 +2033,7 @@ static int smb_direct_prepare_negotiation(struct smbdirect_socket *sc)
19212033
recvmsg = get_free_recvmsg(sc);
19222034
if (!recvmsg)
19232035
return -ENOMEM;
2036+
recvmsg->cqe.done = smb_direct_negotiate_recv_done;
19242037

19252038
ret = smb_direct_post_recv(sc, recvmsg);
19262039
if (ret) {
@@ -2339,6 +2452,7 @@ static int smb_direct_prepare(struct ksmbd_transport *t)
23392452

23402453
static int smb_direct_connect(struct smbdirect_socket *sc)
23412454
{
2455+
struct smbdirect_recv_io *recv_io;
23422456
int ret;
23432457

23442458
ret = smb_direct_init_params(sc);
@@ -2353,6 +2467,9 @@ static int smb_direct_connect(struct smbdirect_socket *sc)
23532467
return ret;
23542468
}
23552469

2470+
list_for_each_entry(recv_io, &sc->recv_io.free.list, list)
2471+
recv_io->cqe.done = recv_done;
2472+
23562473
ret = smb_direct_create_qpair(sc);
23572474
if (ret) {
23582475
pr_err("Can't accept RDMA client: %d\n", ret);

fs/smb/server/vfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
702702
rd.old_parent = NULL;
703703
rd.new_parent = new_path.dentry;
704704
rd.flags = flags;
705-
rd.delegated_inode = NULL,
705+
rd.delegated_inode = NULL;
706706
err = start_renaming_dentry(&rd, lookup_flags, old_child, &new_last);
707707
if (err)
708708
goto out_drop_write;

0 commit comments

Comments
 (0)