Skip to content

Commit fbc0283

Browse files
IEncinas10martinetd
authored andcommitted
9p/trans_fd: mark concurrent read and writes to p9_conn->err
Writes for the error value of a connection are spinlock-protected inside p9_conn_cancel, but lockless reads are present elsewhere to avoid performing unnecessary work after an error has been met. Mark the write and lockless reads to make KCSAN happy. Mark the write as exclusive following the recommendation in "Lock-Protected Writes with Lockless Reads" in tools/memory-model/Documentation/access-marking.txt while we are at it. Mark p9_fd_request and p9_conn_cancel m->err reads despite the fact that they do not race with concurrent writes for stylistic reasons. Reported-by: syzbot+d69a7cc8c683c2cb7506@syzkaller.appspotmail.com Reported-by: syzbot+483d6c9b9231ea7e1851@syzkaller.appspotmail.com Signed-off-by: Ignacio Encinas <ignacio@iencinas.com> Message-ID: <20250318-p9_conn_err_benign_data_race-v3-1-290bb18335cc@iencinas.com> Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
1 parent ad6d455 commit fbc0283

File tree

1 file changed

+10
-7
lines changed

1 file changed

+10
-7
lines changed

net/9p/trans_fd.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,13 @@ static void p9_conn_cancel(struct p9_conn *m, int err)
192192

193193
spin_lock(&m->req_lock);
194194

195-
if (m->err) {
195+
if (READ_ONCE(m->err)) {
196196
spin_unlock(&m->req_lock);
197197
return;
198198
}
199199

200-
m->err = err;
200+
WRITE_ONCE(m->err, err);
201+
ASSERT_EXCLUSIVE_WRITER(m->err);
201202

202203
list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) {
203204
list_move(&req->req_list, &cancel_list);
@@ -284,7 +285,7 @@ static void p9_read_work(struct work_struct *work)
284285

285286
m = container_of(work, struct p9_conn, rq);
286287

287-
if (m->err < 0)
288+
if (READ_ONCE(m->err) < 0)
288289
return;
289290

290291
p9_debug(P9_DEBUG_TRANS, "start mux %p pos %zd\n", m, m->rc.offset);
@@ -451,7 +452,7 @@ static void p9_write_work(struct work_struct *work)
451452

452453
m = container_of(work, struct p9_conn, wq);
453454

454-
if (m->err < 0) {
455+
if (READ_ONCE(m->err) < 0) {
455456
clear_bit(Wworksched, &m->wsched);
456457
return;
457458
}
@@ -623,7 +624,7 @@ static void p9_poll_mux(struct p9_conn *m)
623624
__poll_t n;
624625
int err = -ECONNRESET;
625626

626-
if (m->err < 0)
627+
if (READ_ONCE(m->err) < 0)
627628
return;
628629

629630
n = p9_fd_poll(m->client, NULL, &err);
@@ -666,6 +667,7 @@ static void p9_poll_mux(struct p9_conn *m)
666667
static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
667668
{
668669
__poll_t n;
670+
int err;
669671
struct p9_trans_fd *ts = client->trans;
670672
struct p9_conn *m = &ts->conn;
671673

@@ -674,9 +676,10 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req)
674676

675677
spin_lock(&m->req_lock);
676678

677-
if (m->err < 0) {
679+
err = READ_ONCE(m->err);
680+
if (err < 0) {
678681
spin_unlock(&m->req_lock);
679-
return m->err;
682+
return err;
680683
}
681684

682685
WRITE_ONCE(req->status, REQ_STATUS_UNSENT);

0 commit comments

Comments
 (0)