-
-
Save xrivendell7/865a5d95635b9dde886a3f3eb156b7f9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
================================================================== | |
BUG: KASAN: slab-use-after-free in sk_to_full_sk include/net/inet_sock.h:320 [inline] | |
BUG: KASAN: slab-use-after-free in ip_finish_output+0x61/0x210 net/ipv4/ip_output.c:320 | |
Read of size 1 at addr ffff888131b9d012 by task swapper/2/0 | |
CPU: 2 PID: 0 Comm: swapper/2 Not tainted 6.8.0-rc1-00202-gaa2b2eb39348-dirty #3 | |
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-debian-1.16.2-1 04/01/2014 | |
Call Trace: | |
<IRQ> | |
__dump_stack lib/dump_stack.c:88 [inline] | |
dump_stack_lvl+0xfe/0x160 lib/dump_stack.c:106 | |
print_address_description mm/kasan/report.c:377 [inline] | |
print_report+0x15f/0x540 mm/kasan/report.c:488 | |
kasan_report+0xd2/0x110 mm/kasan/report.c:601 | |
__asan_load1+0x53/0x60 mm/kasan/generic.c:259 | |
sk_to_full_sk include/net/inet_sock.h:320 [inline] | |
ip_finish_output+0x61/0x210 net/ipv4/ip_output.c:320 | |
NF_HOOK_COND include/linux/netfilter.h:303 [inline] | |
ip_output+0x113/0x250 net/ipv4/ip_output.c:433 | |
dst_output include/net/dst.h:451 [inline] | |
ip_local_out+0x72/0x90 net/ipv4/ip_output.c:129 | |
ipvlan_process_v4_outbound+0x2a1/0x380 drivers/net/ipvlan/ipvlan_core.c:442 | |
ipvlan_process_outbound drivers/net/ipvlan/ipvlan_core.c:540 [inline] | |
ipvlan_xmit_mode_l3 drivers/net/ipvlan/ipvlan_core.c:602 [inline] | |
ipvlan_queue_xmit+0x650/0x990 drivers/net/ipvlan/ipvlan_core.c:668 | |
ipvlan_start_xmit+0x35/0xb0 drivers/net/ipvlan/ipvlan_main.c:222 | |
__netdev_start_xmit include/linux/netdevice.h:4989 [inline] | |
netdev_start_xmit include/linux/netdevice.h:5003 [inline] | |
xmit_one net/core/dev.c:3547 [inline] | |
dev_hard_start_xmit+0x108/0x250 net/core/dev.c:3563 | |
sch_direct_xmit+0x236/0x410 net/sched/sch_generic.c:342 | |
qdisc_restart net/sched/sch_generic.c:407 [inline] | |
__qdisc_run+0x6dd/0x1100 net/sched/sch_generic.c:415 | |
qdisc_run+0x115/0x340 include/net/pkt_sched.h:125 | |
net_tx_action+0x239/0x2c0 net/core/dev.c:5197 | |
__do_softirq+0x105/0x27a kernel/softirq.c:553 | |
invoke_softirq kernel/softirq.c:427 [inline] | |
__irq_exit_rcu kernel/softirq.c:632 [inline] | |
irq_exit_rcu+0x49/0xa0 kernel/softirq.c:644 | |
sysvec_apic_timer_interrupt+0x7a/0x90 arch/x86/kernel/apic/apic.c:1076 | |
</IRQ> | |
<TASK> | |
asm_sysvec_apic_timer_interrupt+0x1f/0x30 arch/x86/include/asm/idtentry.h:649 | |
RIP: 0010:native_irq_disable arch/x86/include/asm/irqflags.h:37 [inline] | |
RIP: 0010:arch_local_irq_disable arch/x86/include/asm/irqflags.h:72 [inline] | |
RIP: 0010:default_idle+0x17/0x20 arch/x86/kernel/process.c:743 | |
Code: 00 4d 29 c8 4c 01 c7 4c 29 c2 e9 76 ff ff ff cc cc cc cc f3 0f 1e fa 55 48 89 e5 66 90 0f 00 2d ff 5f 32 00 f3 0f 1e fa fb f4 <fa> 5d c3 66 0f 1f 44 00 00 f3 0f 1e fa 55 48 89 e5 e8 d3 ff ff ff | |
RSP: 0018:ffff88800a037e10 EFLAGS: 00000246 | |
RAX: ffff888064d2d0d0 RBX: ffff88800a01b180 RCX: dffffc0000000000 | |
RDX: 0000000000000001 RSI: 0000000000000004 RDI: 00000000000a8aa4 | |
RBP: ffff88800a037e10 R08: ffff888064d2d0d3 R09: 1ffff1100c9a5a1a | |
R10: ffffed100c9a5a1b R11: ffffed100c9a5a1b R12: ffffffff88acc868 | |
R13: 0000000000000000 R14: 0000000000000002 R15: 0000000000000000 | |
arch_cpu_idle+0xd/0x10 arch/x86/kernel/process.c:779 | |
default_idle_call+0x2f/0x40 kernel/sched/idle.c:97 | |
cpuidle_idle_call kernel/sched/idle.c:170 [inline] | |
do_idle+0x147/0x350 kernel/sched/idle.c:312 | |
cpu_startup_entry+0x35/0x40 kernel/sched/idle.c:410 | |
start_secondary+0xaf/0xb0 arch/x86/kernel/smpboot.c:336 | |
secondary_startup_64_no_verify+0x15f/0x16b | |
</TASK> | |
Allocated by task 10632: | |
kasan_save_stack mm/kasan/common.c:47 [inline] | |
kasan_save_track+0x30/0x60 mm/kasan/common.c:68 | |
kasan_save_alloc_info+0x69/0x70 mm/kasan/generic.c:626 | |
poison_kmalloc_redzone mm/kasan/common.c:372 [inline] | |
__kasan_kmalloc+0x82/0x90 mm/kasan/common.c:389 | |
kasan_kmalloc include/linux/kasan.h:211 [inline] | |
__do_kmalloc_node mm/slub.c:3981 [inline] | |
__kmalloc+0x1b1/0x340 mm/slub.c:3994 | |
kmalloc include/linux/slab.h:594 [inline] | |
sk_prot_alloc+0x97/0x1c0 net/core/sock.c:2079 | |
sk_alloc+0x41/0x3a0 net/core/sock.c:2132 | |
packet_create+0xce/0x4d0 net/packet/af_packet.c:3352 | |
__sock_create+0x2e8/0x510 net/socket.c:1571 | |
sock_create net/socket.c:1622 [inline] | |
__sys_socket_create net/socket.c:1659 [inline] | |
__sys_socket+0xf8/0x2a0 net/socket.c:1706 | |
__do_sys_socket net/socket.c:1720 [inline] | |
__se_sys_socket net/socket.c:1718 [inline] | |
__x64_sys_socket+0x4b/0x60 net/socket.c:1718 | |
do_syscall_x64 arch/x86/entry/common.c:52 [inline] | |
do_syscall_64+0x59/0x120 arch/x86/entry/common.c:83 | |
entry_SYSCALL_64_after_hwframe+0x63/0x6b | |
Freed by task 0: | |
kasan_save_stack mm/kasan/common.c:47 [inline] | |
kasan_save_track+0x30/0x60 mm/kasan/common.c:68 | |
kasan_save_free_info+0x52/0x60 mm/kasan/generic.c:640 | |
poison_slab_object+0xfe/0x160 mm/kasan/common.c:241 | |
__kasan_slab_free+0x18/0x50 mm/kasan/common.c:257 | |
kasan_slab_free include/linux/kasan.h:184 [inline] | |
slab_free_hook mm/slub.c:2121 [inline] | |
slab_free mm/slub.c:4299 [inline] | |
kfree+0xab/0x1d0 mm/slub.c:4409 | |
sk_prot_free net/core/sock.c:2115 [inline] | |
__sk_destruct+0x3bc/0x530 net/core/sock.c:2207 | |
sk_destruct net/core/sock.c:2222 [inline] | |
__sk_free+0x2bc/0x300 net/core/sock.c:2233 | |
sock_wfree+0x1aa/0x3c0 | |
skb_orphan include/linux/skbuff.h:3127 [inline] | |
ip_defrag+0x123/0x1330 net/ipv4/ip_fragment.c:490 | |
nf_ct_ipv4_gather_frags net/ipv4/netfilter/nf_defrag_ipv4.c:32 [inline] | |
ipv4_conntrack_defrag+0x2f3/0x360 net/ipv4/netfilter/nf_defrag_ipv4.c:87 | |
nf_hook_entry_hookfn include/linux/netfilter.h:154 [inline] | |
nf_hook_slow+0x93/0x1c0 net/netfilter/core.c:626 | |
nf_hook include/linux/netfilter.h:269 [inline] | |
__ip_local_out+0x36c/0x390 net/ipv4/ip_output.c:118 | |
ip_local_out+0x30/0x90 net/ipv4/ip_output.c:127 | |
ipvlan_process_v4_outbound+0x2a1/0x380 drivers/net/ipvlan/ipvlan_core.c:442 | |
ipvlan_process_outbound drivers/net/ipvlan/ipvlan_core.c:540 [inline] | |
ipvlan_xmit_mode_l3 drivers/net/ipvlan/ipvlan_core.c:602 [inline] | |
ipvlan_queue_xmit+0x650/0x990 drivers/net/ipvlan/ipvlan_core.c:668 | |
ipvlan_start_xmit+0x35/0xb0 drivers/net/ipvlan/ipvlan_main.c:222 | |
__netdev_start_xmit include/linux/netdevice.h:4989 [inline] | |
netdev_start_xmit include/linux/netdevice.h:5003 [inline] | |
xmit_one net/core/dev.c:3547 [inline] | |
dev_hard_start_xmit+0x108/0x250 net/core/dev.c:3563 | |
sch_direct_xmit+0x236/0x410 net/sched/sch_generic.c:342 | |
qdisc_restart net/sched/sch_generic.c:407 [inline] | |
__qdisc_run+0x6dd/0x1100 net/sched/sch_generic.c:415 | |
qdisc_run+0x115/0x340 include/net/pkt_sched.h:125 | |
net_tx_action+0x239/0x2c0 net/core/dev.c:5197 | |
__do_softirq+0x105/0x27a kernel/softirq.c:553 | |
The buggy address belongs to the object at ffff888131b9d000 | |
which belongs to the cache kmalloc-2k of size 2048 | |
The buggy address is located 18 bytes inside of | |
freed 2048-byte region [ffff888131b9d000, ffff888131b9d800) | |
The buggy address belongs to the physical page: | |
page:ffffea0004c6e600 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x131b98 | |
head:ffffea0004c6e600 order:3 entire_mapcount:0 nr_pages_mapped:0 pincount:0 | |
anon flags: 0x57ff00000000840(slab|head|node=1|zone=2|lastcpupid=0x7ff) | |
page_type: 0xffffffff() | |
raw: 057ff00000000840 ffff888009442f00 0000000000000000 dead000000000001 | |
raw: 0000000000000000 0000000000080008 00000001ffffffff 0000000000000000 | |
page dumped because: kasan: bad access detected | |
Memory state around the buggy address: | |
ffff888131b9cf00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc | |
ffff888131b9cf80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc | |
>ffff888131b9d000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb | |
^ | |
ffff888131b9d080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb | |
ffff888131b9d100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb | |
================================================================== | |
---------------- | |
Code disassembly (best guess): | |
0: 00 4d 29 add %cl,0x29(%rbp) | |
3: c8 4c 01 c7 enter $0x14c,$0xc7 | |
7: 4c 29 c2 sub %r8,%rdx | |
a: e9 76 ff ff ff jmp 0xffffff85 | |
f: cc int3 | |
10: cc int3 | |
11: cc int3 | |
12: cc int3 | |
13: f3 0f 1e fa endbr64 | |
17: 55 push %rbp | |
18: 48 89 e5 mov %rsp,%rbp | |
1b: 66 90 xchg %ax,%ax | |
1d: 0f 00 2d ff 5f 32 00 verw 0x325fff(%rip) # 0x326023 | |
24: f3 0f 1e fa endbr64 | |
28: fb sti | |
29: f4 hlt | |
* 2a: fa cli <-- trapping instruction | |
2b: 5d pop %rbp | |
2c: c3 ret | |
2d: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) | |
33: f3 0f 1e fa endbr64 | |
37: 55 push %rbp | |
38: 48 89 e5 mov %rsp,%rbp | |
3b: e8 d3 ff ff ff call 0x13 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE | |
#include <arpa/inet.h> | |
#include <dirent.h> | |
#include <endian.h> | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <net/if.h> | |
#include <net/if_arp.h> | |
#include <netinet/in.h> | |
#include <sched.h> | |
#include <signal.h> | |
#include <stdarg.h> | |
#include <stdbool.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/ioctl.h> | |
#include <sys/mount.h> | |
#include <sys/prctl.h> | |
#include <sys/resource.h> | |
#include <sys/socket.h> | |
#include <sys/stat.h> | |
#include <sys/syscall.h> | |
#include <sys/time.h> | |
#include <sys/types.h> | |
#include <sys/uio.h> | |
#include <sys/wait.h> | |
#include <time.h> | |
#include <unistd.h> | |
#include <linux/capability.h> | |
#include <linux/genetlink.h> | |
#include <linux/if_addr.h> | |
#include <linux/if_ether.h> | |
#include <linux/if_link.h> | |
#include <linux/if_tun.h> | |
#include <linux/in6.h> | |
#include <linux/ip.h> | |
#include <linux/neighbour.h> | |
#include <linux/net.h> | |
#include <linux/netlink.h> | |
#include <linux/rtnetlink.h> | |
#include <linux/tcp.h> | |
#include <linux/veth.h> | |
static unsigned long long procid; | |
static void sleep_ms(uint64_t ms) { | |
usleep(ms * 1000); | |
} | |
static uint64_t current_time_ms(void) { | |
struct timespec ts; | |
if (clock_gettime(CLOCK_MONOTONIC, &ts)) | |
exit(1); | |
return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000; | |
} | |
static bool write_file(const char* file, const char* what, ...) { | |
char buf[1024]; | |
va_list args; | |
va_start(args, what); | |
vsnprintf(buf, sizeof(buf), what, args); | |
va_end(args); | |
buf[sizeof(buf) - 1] = 0; | |
int len = strlen(buf); | |
int fd = open(file, O_WRONLY | O_CLOEXEC); | |
if (fd == -1) | |
return false; | |
if (write(fd, buf, len) != len) { | |
int err = errno; | |
close(fd); | |
errno = err; | |
return false; | |
} | |
close(fd); | |
return true; | |
} | |
struct nlmsg { | |
char* pos; | |
int nesting; | |
struct nlattr* nested[8]; | |
char buf[4096]; | |
}; | |
static void netlink_init(struct nlmsg* nlmsg, | |
int typ, | |
int flags, | |
const void* data, | |
int size) { | |
memset(nlmsg, 0, sizeof(*nlmsg)); | |
struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf; | |
hdr->nlmsg_type = typ; | |
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags; | |
memcpy(hdr + 1, data, size); | |
nlmsg->pos = (char*)(hdr + 1) + NLMSG_ALIGN(size); | |
} | |
static void netlink_attr(struct nlmsg* nlmsg, | |
int typ, | |
const void* data, | |
int size) { | |
struct nlattr* attr = (struct nlattr*)nlmsg->pos; | |
attr->nla_len = sizeof(*attr) + size; | |
attr->nla_type = typ; | |
if (size > 0) | |
memcpy(attr + 1, data, size); | |
nlmsg->pos += NLMSG_ALIGN(attr->nla_len); | |
} | |
static void netlink_nest(struct nlmsg* nlmsg, int typ) { | |
struct nlattr* attr = (struct nlattr*)nlmsg->pos; | |
attr->nla_type = typ; | |
nlmsg->pos += sizeof(*attr); | |
nlmsg->nested[nlmsg->nesting++] = attr; | |
} | |
static void netlink_done(struct nlmsg* nlmsg) { | |
struct nlattr* attr = nlmsg->nested[--nlmsg->nesting]; | |
attr->nla_len = nlmsg->pos - (char*)attr; | |
} | |
static int netlink_send_ext(struct nlmsg* nlmsg, | |
int sock, | |
uint16_t reply_type, | |
int* reply_len, | |
bool dofail) { | |
if (nlmsg->pos > nlmsg->buf + sizeof(nlmsg->buf) || nlmsg->nesting) | |
exit(1); | |
struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf; | |
hdr->nlmsg_len = nlmsg->pos - nlmsg->buf; | |
struct sockaddr_nl addr; | |
memset(&addr, 0, sizeof(addr)); | |
addr.nl_family = AF_NETLINK; | |
ssize_t n = sendto(sock, nlmsg->buf, hdr->nlmsg_len, 0, | |
(struct sockaddr*)&addr, sizeof(addr)); | |
if (n != (ssize_t)hdr->nlmsg_len) { | |
if (dofail) | |
exit(1); | |
return -1; | |
} | |
n = recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0); | |
if (reply_len) | |
*reply_len = 0; | |
if (n < 0) { | |
if (dofail) | |
exit(1); | |
return -1; | |
} | |
if (n < (ssize_t)sizeof(struct nlmsghdr)) { | |
errno = EINVAL; | |
if (dofail) | |
exit(1); | |
return -1; | |
} | |
if (hdr->nlmsg_type == NLMSG_DONE) | |
return 0; | |
if (reply_len && hdr->nlmsg_type == reply_type) { | |
*reply_len = n; | |
return 0; | |
} | |
if (n < (ssize_t)(sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr))) { | |
errno = EINVAL; | |
if (dofail) | |
exit(1); | |
return -1; | |
} | |
if (hdr->nlmsg_type != NLMSG_ERROR) { | |
errno = EINVAL; | |
if (dofail) | |
exit(1); | |
return -1; | |
} | |
errno = -((struct nlmsgerr*)(hdr + 1))->error; | |
return -errno; | |
} | |
static int netlink_send(struct nlmsg* nlmsg, int sock) { | |
return netlink_send_ext(nlmsg, sock, 0, NULL, true); | |
} | |
static int netlink_query_family_id(struct nlmsg* nlmsg, | |
int sock, | |
const char* family_name, | |
bool dofail) { | |
struct genlmsghdr genlhdr; | |
memset(&genlhdr, 0, sizeof(genlhdr)); | |
genlhdr.cmd = CTRL_CMD_GETFAMILY; | |
netlink_init(nlmsg, GENL_ID_CTRL, 0, &genlhdr, sizeof(genlhdr)); | |
netlink_attr(nlmsg, CTRL_ATTR_FAMILY_NAME, family_name, | |
strnlen(family_name, GENL_NAMSIZ - 1) + 1); | |
int n = 0; | |
int err = netlink_send_ext(nlmsg, sock, GENL_ID_CTRL, &n, dofail); | |
if (err < 0) { | |
return -1; | |
} | |
uint16_t id = 0; | |
struct nlattr* attr = (struct nlattr*)(nlmsg->buf + NLMSG_HDRLEN + | |
NLMSG_ALIGN(sizeof(genlhdr))); | |
for (; (char*)attr < nlmsg->buf + n; | |
attr = (struct nlattr*)((char*)attr + NLMSG_ALIGN(attr->nla_len))) { | |
if (attr->nla_type == CTRL_ATTR_FAMILY_ID) { | |
id = *(uint16_t*)(attr + 1); | |
break; | |
} | |
} | |
if (!id) { | |
errno = EINVAL; | |
return -1; | |
} | |
recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0); | |
return id; | |
} | |
static int netlink_next_msg(struct nlmsg* nlmsg, | |
unsigned int offset, | |
unsigned int total_len) { | |
struct nlmsghdr* hdr = (struct nlmsghdr*)(nlmsg->buf + offset); | |
if (offset == total_len || offset + hdr->nlmsg_len > total_len) | |
return -1; | |
return hdr->nlmsg_len; | |
} | |
static void netlink_add_device_impl(struct nlmsg* nlmsg, | |
const char* type, | |
const char* name, | |
bool up) { | |
struct ifinfomsg hdr; | |
memset(&hdr, 0, sizeof(hdr)); | |
if (up) | |
hdr.ifi_flags = hdr.ifi_change = IFF_UP; | |
netlink_init(nlmsg, RTM_NEWLINK, NLM_F_EXCL | NLM_F_CREATE, &hdr, | |
sizeof(hdr)); | |
if (name) | |
netlink_attr(nlmsg, IFLA_IFNAME, name, strlen(name)); | |
netlink_nest(nlmsg, IFLA_LINKINFO); | |
netlink_attr(nlmsg, IFLA_INFO_KIND, type, strlen(type)); | |
} | |
static void netlink_add_device(struct nlmsg* nlmsg, | |
int sock, | |
const char* type, | |
const char* name) { | |
netlink_add_device_impl(nlmsg, type, name, false); | |
netlink_done(nlmsg); | |
int err = netlink_send(nlmsg, sock); | |
if (err < 0) { | |
} | |
} | |
static void netlink_add_veth(struct nlmsg* nlmsg, | |
int sock, | |
const char* name, | |
const char* peer) { | |
netlink_add_device_impl(nlmsg, "veth", name, false); | |
netlink_nest(nlmsg, IFLA_INFO_DATA); | |
netlink_nest(nlmsg, VETH_INFO_PEER); | |
nlmsg->pos += sizeof(struct ifinfomsg); | |
netlink_attr(nlmsg, IFLA_IFNAME, peer, strlen(peer)); | |
netlink_done(nlmsg); | |
netlink_done(nlmsg); | |
netlink_done(nlmsg); | |
int err = netlink_send(nlmsg, sock); | |
if (err < 0) { | |
} | |
} | |
static void netlink_add_xfrm(struct nlmsg* nlmsg, int sock, const char* name) { | |
netlink_add_device_impl(nlmsg, "xfrm", name, true); | |
netlink_nest(nlmsg, IFLA_INFO_DATA); | |
int if_id = 1; | |
netlink_attr(nlmsg, 2, &if_id, sizeof(if_id)); | |
netlink_done(nlmsg); | |
netlink_done(nlmsg); | |
int err = netlink_send(nlmsg, sock); | |
if (err < 0) { | |
} | |
} | |
static void netlink_add_hsr(struct nlmsg* nlmsg, | |
int sock, | |
const char* name, | |
const char* slave1, | |
const char* slave2) { | |
netlink_add_device_impl(nlmsg, "hsr", name, false); | |
netlink_nest(nlmsg, IFLA_INFO_DATA); | |
int ifindex1 = if_nametoindex(slave1); | |
netlink_attr(nlmsg, IFLA_HSR_SLAVE1, &ifindex1, sizeof(ifindex1)); | |
int ifindex2 = if_nametoindex(slave2); | |
netlink_attr(nlmsg, IFLA_HSR_SLAVE2, &ifindex2, sizeof(ifindex2)); | |
netlink_done(nlmsg); | |
netlink_done(nlmsg); | |
int err = netlink_send(nlmsg, sock); | |
if (err < 0) { | |
} | |
} | |
static void netlink_add_linked(struct nlmsg* nlmsg, | |
int sock, | |
const char* type, | |
const char* name, | |
const char* link) { | |
netlink_add_device_impl(nlmsg, type, name, false); | |
netlink_done(nlmsg); | |
int ifindex = if_nametoindex(link); | |
netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex)); | |
int err = netlink_send(nlmsg, sock); | |
if (err < 0) { | |
} | |
} | |
static void netlink_add_vlan(struct nlmsg* nlmsg, | |
int sock, | |
const char* name, | |
const char* link, | |
uint16_t id, | |
uint16_t proto) { | |
netlink_add_device_impl(nlmsg, "vlan", name, false); | |
netlink_nest(nlmsg, IFLA_INFO_DATA); | |
netlink_attr(nlmsg, IFLA_VLAN_ID, &id, sizeof(id)); | |
netlink_attr(nlmsg, IFLA_VLAN_PROTOCOL, &proto, sizeof(proto)); | |
netlink_done(nlmsg); | |
netlink_done(nlmsg); | |
int ifindex = if_nametoindex(link); | |
netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex)); | |
int err = netlink_send(nlmsg, sock); | |
if (err < 0) { | |
} | |
} | |
static void netlink_add_macvlan(struct nlmsg* nlmsg, | |
int sock, | |
const char* name, | |
const char* link) { | |
netlink_add_device_impl(nlmsg, "macvlan", name, false); | |
netlink_nest(nlmsg, IFLA_INFO_DATA); | |
uint32_t mode = MACVLAN_MODE_BRIDGE; | |
netlink_attr(nlmsg, IFLA_MACVLAN_MODE, &mode, sizeof(mode)); | |
netlink_done(nlmsg); | |
netlink_done(nlmsg); | |
int ifindex = if_nametoindex(link); | |
netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex)); | |
int err = netlink_send(nlmsg, sock); | |
if (err < 0) { | |
} | |
} | |
static void netlink_add_geneve(struct nlmsg* nlmsg, | |
int sock, | |
const char* name, | |
uint32_t vni, | |
struct in_addr* addr4, | |
struct in6_addr* addr6) { | |
netlink_add_device_impl(nlmsg, "geneve", name, false); | |
netlink_nest(nlmsg, IFLA_INFO_DATA); | |
netlink_attr(nlmsg, IFLA_GENEVE_ID, &vni, sizeof(vni)); | |
if (addr4) | |
netlink_attr(nlmsg, IFLA_GENEVE_REMOTE, addr4, sizeof(*addr4)); | |
if (addr6) | |
netlink_attr(nlmsg, IFLA_GENEVE_REMOTE6, addr6, sizeof(*addr6)); | |
netlink_done(nlmsg); | |
netlink_done(nlmsg); | |
int err = netlink_send(nlmsg, sock); | |
if (err < 0) { | |
} | |
} | |
#define IFLA_IPVLAN_FLAGS 2 | |
#define IPVLAN_MODE_L3S 2 | |
#undef IPVLAN_F_VEPA | |
#define IPVLAN_F_VEPA 2 | |
static void netlink_add_ipvlan(struct nlmsg* nlmsg, | |
int sock, | |
const char* name, | |
const char* link, | |
uint16_t mode, | |
uint16_t flags) { | |
netlink_add_device_impl(nlmsg, "ipvlan", name, false); | |
netlink_nest(nlmsg, IFLA_INFO_DATA); | |
netlink_attr(nlmsg, IFLA_IPVLAN_MODE, &mode, sizeof(mode)); | |
netlink_attr(nlmsg, IFLA_IPVLAN_FLAGS, &flags, sizeof(flags)); | |
netlink_done(nlmsg); | |
netlink_done(nlmsg); | |
int ifindex = if_nametoindex(link); | |
netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex)); | |
int err = netlink_send(nlmsg, sock); | |
if (err < 0) { | |
} | |
} | |
static void netlink_device_change(struct nlmsg* nlmsg, | |
int sock, | |
const char* name, | |
bool up, | |
const char* master, | |
const void* mac, | |
int macsize, | |
const char* new_name) { | |
struct ifinfomsg hdr; | |
memset(&hdr, 0, sizeof(hdr)); | |
if (up) | |
hdr.ifi_flags = hdr.ifi_change = IFF_UP; | |
hdr.ifi_index = if_nametoindex(name); | |
netlink_init(nlmsg, RTM_NEWLINK, 0, &hdr, sizeof(hdr)); | |
if (new_name) | |
netlink_attr(nlmsg, IFLA_IFNAME, new_name, strlen(new_name)); | |
if (master) { | |
int ifindex = if_nametoindex(master); | |
netlink_attr(nlmsg, IFLA_MASTER, &ifindex, sizeof(ifindex)); | |
} | |
if (macsize) | |
netlink_attr(nlmsg, IFLA_ADDRESS, mac, macsize); | |
int err = netlink_send(nlmsg, sock); | |
if (err < 0) { | |
} | |
} | |
static int netlink_add_addr(struct nlmsg* nlmsg, | |
int sock, | |
const char* dev, | |
const void* addr, | |
int addrsize) { | |
struct ifaddrmsg hdr; | |
memset(&hdr, 0, sizeof(hdr)); | |
hdr.ifa_family = addrsize == 4 ? AF_INET : AF_INET6; | |
hdr.ifa_prefixlen = addrsize == 4 ? 24 : 120; | |
hdr.ifa_scope = RT_SCOPE_UNIVERSE; | |
hdr.ifa_index = if_nametoindex(dev); | |
netlink_init(nlmsg, RTM_NEWADDR, NLM_F_CREATE | NLM_F_REPLACE, &hdr, | |
sizeof(hdr)); | |
netlink_attr(nlmsg, IFA_LOCAL, addr, addrsize); | |
netlink_attr(nlmsg, IFA_ADDRESS, addr, addrsize); | |
return netlink_send(nlmsg, sock); | |
} | |
static void netlink_add_addr4(struct nlmsg* nlmsg, | |
int sock, | |
const char* dev, | |
const char* addr) { | |
struct in_addr in_addr; | |
inet_pton(AF_INET, addr, &in_addr); | |
int err = netlink_add_addr(nlmsg, sock, dev, &in_addr, sizeof(in_addr)); | |
if (err < 0) { | |
} | |
} | |
static void netlink_add_addr6(struct nlmsg* nlmsg, | |
int sock, | |
const char* dev, | |
const char* addr) { | |
struct in6_addr in6_addr; | |
inet_pton(AF_INET6, addr, &in6_addr); | |
int err = netlink_add_addr(nlmsg, sock, dev, &in6_addr, sizeof(in6_addr)); | |
if (err < 0) { | |
} | |
} | |
static struct nlmsg nlmsg; | |
#define DEVLINK_FAMILY_NAME "devlink" | |
#define DEVLINK_CMD_PORT_GET 5 | |
#define DEVLINK_ATTR_BUS_NAME 1 | |
#define DEVLINK_ATTR_DEV_NAME 2 | |
#define DEVLINK_ATTR_NETDEV_NAME 7 | |
static struct nlmsg nlmsg2; | |
static void initialize_devlink_ports(const char* bus_name, | |
const char* dev_name, | |
const char* netdev_prefix) { | |
struct genlmsghdr genlhdr; | |
int len, total_len, id, err, offset; | |
uint16_t netdev_index; | |
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); | |
if (sock == -1) | |
exit(1); | |
int rtsock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); | |
if (rtsock == -1) | |
exit(1); | |
id = netlink_query_family_id(&nlmsg, sock, DEVLINK_FAMILY_NAME, true); | |
if (id == -1) | |
goto error; | |
memset(&genlhdr, 0, sizeof(genlhdr)); | |
genlhdr.cmd = DEVLINK_CMD_PORT_GET; | |
netlink_init(&nlmsg, id, NLM_F_DUMP, &genlhdr, sizeof(genlhdr)); | |
netlink_attr(&nlmsg, DEVLINK_ATTR_BUS_NAME, bus_name, strlen(bus_name) + 1); | |
netlink_attr(&nlmsg, DEVLINK_ATTR_DEV_NAME, dev_name, strlen(dev_name) + 1); | |
err = netlink_send_ext(&nlmsg, sock, id, &total_len, true); | |
if (err < 0) { | |
goto error; | |
} | |
offset = 0; | |
netdev_index = 0; | |
while ((len = netlink_next_msg(&nlmsg, offset, total_len)) != -1) { | |
struct nlattr* attr = (struct nlattr*)(nlmsg.buf + offset + NLMSG_HDRLEN + | |
NLMSG_ALIGN(sizeof(genlhdr))); | |
for (; (char*)attr < nlmsg.buf + offset + len; | |
attr = (struct nlattr*)((char*)attr + NLMSG_ALIGN(attr->nla_len))) { | |
if (attr->nla_type == DEVLINK_ATTR_NETDEV_NAME) { | |
char* port_name; | |
char netdev_name[IFNAMSIZ]; | |
port_name = (char*)(attr + 1); | |
snprintf(netdev_name, sizeof(netdev_name), "%s%d", netdev_prefix, | |
netdev_index); | |
netlink_device_change(&nlmsg2, rtsock, port_name, true, 0, 0, 0, | |
netdev_name); | |
break; | |
} | |
} | |
offset += len; | |
netdev_index++; | |
} | |
error: | |
close(rtsock); | |
close(sock); | |
} | |
#define DEV_IPV4 "172.20.20.%d" | |
#define DEV_IPV6 "fe80::%02x" | |
#define DEV_MAC 0x00aaaaaaaaaa | |
static void netdevsim_add(unsigned int addr, unsigned int port_count) { | |
write_file("/sys/bus/netdevsim/del_device", "%u", addr); | |
if (write_file("/sys/bus/netdevsim/new_device", "%u %u", addr, port_count)) { | |
char buf[32]; | |
snprintf(buf, sizeof(buf), "netdevsim%d", addr); | |
initialize_devlink_ports("netdevsim", buf, "netdevsim"); | |
} | |
} | |
#define WG_GENL_NAME "wireguard" | |
enum wg_cmd { | |
WG_CMD_GET_DEVICE, | |
WG_CMD_SET_DEVICE, | |
}; | |
enum wgdevice_attribute { | |
WGDEVICE_A_UNSPEC, | |
WGDEVICE_A_IFINDEX, | |
WGDEVICE_A_IFNAME, | |
WGDEVICE_A_PRIVATE_KEY, | |
WGDEVICE_A_PUBLIC_KEY, | |
WGDEVICE_A_FLAGS, | |
WGDEVICE_A_LISTEN_PORT, | |
WGDEVICE_A_FWMARK, | |
WGDEVICE_A_PEERS, | |
}; | |
enum wgpeer_attribute { | |
WGPEER_A_UNSPEC, | |
WGPEER_A_PUBLIC_KEY, | |
WGPEER_A_PRESHARED_KEY, | |
WGPEER_A_FLAGS, | |
WGPEER_A_ENDPOINT, | |
WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, | |
WGPEER_A_LAST_HANDSHAKE_TIME, | |
WGPEER_A_RX_BYTES, | |
WGPEER_A_TX_BYTES, | |
WGPEER_A_ALLOWEDIPS, | |
WGPEER_A_PROTOCOL_VERSION, | |
}; | |
enum wgallowedip_attribute { | |
WGALLOWEDIP_A_UNSPEC, | |
WGALLOWEDIP_A_FAMILY, | |
WGALLOWEDIP_A_IPADDR, | |
WGALLOWEDIP_A_CIDR_MASK, | |
}; | |
static void netlink_wireguard_setup(void) { | |
const char ifname_a[] = "wg0"; | |
const char ifname_b[] = "wg1"; | |
const char ifname_c[] = "wg2"; | |
const char private_a[] = | |
"\xa0\x5c\xa8\x4f\x6c\x9c\x8e\x38\x53\xe2\xfd\x7a\x70\xae\x0f\xb2\x0f\xa1" | |
"\x52\x60\x0c\xb0\x08\x45\x17\x4f\x08\x07\x6f\x8d\x78\x43"; | |
const char private_b[] = | |
"\xb0\x80\x73\xe8\xd4\x4e\x91\xe3\xda\x92\x2c\x22\x43\x82\x44\xbb\x88\x5c" | |
"\x69\xe2\x69\xc8\xe9\xd8\x35\xb1\x14\x29\x3a\x4d\xdc\x6e"; | |
const char private_c[] = | |
"\xa0\xcb\x87\x9a\x47\xf5\xbc\x64\x4c\x0e\x69\x3f\xa6\xd0\x31\xc7\x4a\x15" | |
"\x53\xb6\xe9\x01\xb9\xff\x2f\x51\x8c\x78\x04\x2f\xb5\x42"; | |
const char public_a[] = | |
"\x97\x5c\x9d\x81\xc9\x83\xc8\x20\x9e\xe7\x81\x25\x4b\x89\x9f\x8e\xd9\x25" | |
"\xae\x9f\x09\x23\xc2\x3c\x62\xf5\x3c\x57\xcd\xbf\x69\x1c"; | |
const char public_b[] = | |
"\xd1\x73\x28\x99\xf6\x11\xcd\x89\x94\x03\x4d\x7f\x41\x3d\xc9\x57\x63\x0e" | |
"\x54\x93\xc2\x85\xac\xa4\x00\x65\xcb\x63\x11\xbe\x69\x6b"; | |
const char public_c[] = | |
"\xf4\x4d\xa3\x67\xa8\x8e\xe6\x56\x4f\x02\x02\x11\x45\x67\x27\x08\x2f\x5c" | |
"\xeb\xee\x8b\x1b\xf5\xeb\x73\x37\x34\x1b\x45\x9b\x39\x22"; | |
const uint16_t listen_a = 20001; | |
const uint16_t listen_b = 20002; | |
const uint16_t listen_c = 20003; | |
const uint16_t af_inet = AF_INET; | |
const uint16_t af_inet6 = AF_INET6; | |
const struct sockaddr_in endpoint_b_v4 = { | |
.sin_family = AF_INET, | |
.sin_port = htons(listen_b), | |
.sin_addr = {htonl(INADDR_LOOPBACK)}}; | |
const struct sockaddr_in endpoint_c_v4 = { | |
.sin_family = AF_INET, | |
.sin_port = htons(listen_c), | |
.sin_addr = {htonl(INADDR_LOOPBACK)}}; | |
struct sockaddr_in6 endpoint_a_v6 = {.sin6_family = AF_INET6, | |
.sin6_port = htons(listen_a)}; | |
endpoint_a_v6.sin6_addr = in6addr_loopback; | |
struct sockaddr_in6 endpoint_c_v6 = {.sin6_family = AF_INET6, | |
.sin6_port = htons(listen_c)}; | |
endpoint_c_v6.sin6_addr = in6addr_loopback; | |
const struct in_addr first_half_v4 = {0}; | |
const struct in_addr second_half_v4 = {(uint32_t)htonl(128 << 24)}; | |
const struct in6_addr first_half_v6 = {{{0}}}; | |
const struct in6_addr second_half_v6 = {{{0x80}}}; | |
const uint8_t half_cidr = 1; | |
const uint16_t persistent_keepalives[] = {1, 3, 7, 9, 14, 19}; | |
struct genlmsghdr genlhdr = {.cmd = WG_CMD_SET_DEVICE, .version = 1}; | |
int sock; | |
int id, err; | |
sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); | |
if (sock == -1) { | |
return; | |
} | |
id = netlink_query_family_id(&nlmsg, sock, WG_GENL_NAME, true); | |
if (id == -1) | |
goto error; | |
netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr)); | |
netlink_attr(&nlmsg, WGDEVICE_A_IFNAME, ifname_a, strlen(ifname_a) + 1); | |
netlink_attr(&nlmsg, WGDEVICE_A_PRIVATE_KEY, private_a, 32); | |
netlink_attr(&nlmsg, WGDEVICE_A_LISTEN_PORT, &listen_a, 2); | |
netlink_nest(&nlmsg, NLA_F_NESTED | WGDEVICE_A_PEERS); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_b, 32); | |
netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_b_v4, | |
sizeof(endpoint_b_v4)); | |
netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, | |
&persistent_keepalives[0], 2); | |
netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v4, | |
sizeof(first_half_v4)); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); | |
netlink_done(&nlmsg); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v6, | |
sizeof(first_half_v6)); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); | |
netlink_done(&nlmsg); | |
netlink_done(&nlmsg); | |
netlink_done(&nlmsg); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_c, 32); | |
netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_c_v6, | |
sizeof(endpoint_c_v6)); | |
netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, | |
&persistent_keepalives[1], 2); | |
netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v4, | |
sizeof(second_half_v4)); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); | |
netlink_done(&nlmsg); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v6, | |
sizeof(second_half_v6)); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); | |
netlink_done(&nlmsg); | |
netlink_done(&nlmsg); | |
netlink_done(&nlmsg); | |
netlink_done(&nlmsg); | |
err = netlink_send(&nlmsg, sock); | |
if (err < 0) { | |
} | |
netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr)); | |
netlink_attr(&nlmsg, WGDEVICE_A_IFNAME, ifname_b, strlen(ifname_b) + 1); | |
netlink_attr(&nlmsg, WGDEVICE_A_PRIVATE_KEY, private_b, 32); | |
netlink_attr(&nlmsg, WGDEVICE_A_LISTEN_PORT, &listen_b, 2); | |
netlink_nest(&nlmsg, NLA_F_NESTED | WGDEVICE_A_PEERS); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_a, 32); | |
netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_a_v6, | |
sizeof(endpoint_a_v6)); | |
netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, | |
&persistent_keepalives[2], 2); | |
netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v4, | |
sizeof(first_half_v4)); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); | |
netlink_done(&nlmsg); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v6, | |
sizeof(first_half_v6)); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); | |
netlink_done(&nlmsg); | |
netlink_done(&nlmsg); | |
netlink_done(&nlmsg); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_c, 32); | |
netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_c_v4, | |
sizeof(endpoint_c_v4)); | |
netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, | |
&persistent_keepalives[3], 2); | |
netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v4, | |
sizeof(second_half_v4)); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); | |
netlink_done(&nlmsg); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v6, | |
sizeof(second_half_v6)); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); | |
netlink_done(&nlmsg); | |
netlink_done(&nlmsg); | |
netlink_done(&nlmsg); | |
netlink_done(&nlmsg); | |
err = netlink_send(&nlmsg, sock); | |
if (err < 0) { | |
} | |
netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr)); | |
netlink_attr(&nlmsg, WGDEVICE_A_IFNAME, ifname_c, strlen(ifname_c) + 1); | |
netlink_attr(&nlmsg, WGDEVICE_A_PRIVATE_KEY, private_c, 32); | |
netlink_attr(&nlmsg, WGDEVICE_A_LISTEN_PORT, &listen_c, 2); | |
netlink_nest(&nlmsg, NLA_F_NESTED | WGDEVICE_A_PEERS); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_a, 32); | |
netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_a_v6, | |
sizeof(endpoint_a_v6)); | |
netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, | |
&persistent_keepalives[4], 2); | |
netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v4, | |
sizeof(first_half_v4)); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); | |
netlink_done(&nlmsg); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v6, | |
sizeof(first_half_v6)); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); | |
netlink_done(&nlmsg); | |
netlink_done(&nlmsg); | |
netlink_done(&nlmsg); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_b, 32); | |
netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_b_v4, | |
sizeof(endpoint_b_v4)); | |
netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, | |
&persistent_keepalives[5], 2); | |
netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v4, | |
sizeof(second_half_v4)); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); | |
netlink_done(&nlmsg); | |
netlink_nest(&nlmsg, NLA_F_NESTED | 0); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v6, | |
sizeof(second_half_v6)); | |
netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1); | |
netlink_done(&nlmsg); | |
netlink_done(&nlmsg); | |
netlink_done(&nlmsg); | |
netlink_done(&nlmsg); | |
err = netlink_send(&nlmsg, sock); | |
if (err < 0) { | |
} | |
error: | |
close(sock); | |
} | |
static void initialize_netdevices(void) { | |
char netdevsim[16]; | |
sprintf(netdevsim, "netdevsim%d", (int)procid); | |
struct { | |
const char* type; | |
const char* dev; | |
} devtypes[] = { | |
{"ip6gretap", "ip6gretap0"}, {"bridge", "bridge0"}, {"vcan", "vcan0"}, | |
{"bond", "bond0"}, {"team", "team0"}, {"dummy", "dummy0"}, | |
{"nlmon", "nlmon0"}, {"caif", "caif0"}, {"batadv", "batadv0"}, | |
{"vxcan", "vxcan1"}, {"veth", 0}, {"wireguard", "wg0"}, | |
{"wireguard", "wg1"}, {"wireguard", "wg2"}, | |
}; | |
const char* devmasters[] = {"bridge", "bond", "team", "batadv"}; | |
struct { | |
const char* name; | |
int macsize; | |
bool noipv6; | |
} devices[] = { | |
{"lo", ETH_ALEN}, | |
{"sit0", 0}, | |
{"bridge0", ETH_ALEN}, | |
{"vcan0", 0, true}, | |
{"tunl0", 0}, | |
{"gre0", 0}, | |
{"gretap0", ETH_ALEN}, | |
{"ip_vti0", 0}, | |
{"ip6_vti0", 0}, | |
{"ip6tnl0", 0}, | |
{"ip6gre0", 0}, | |
{"ip6gretap0", ETH_ALEN}, | |
{"erspan0", ETH_ALEN}, | |
{"bond0", ETH_ALEN}, | |
{"veth0", ETH_ALEN}, | |
{"veth1", ETH_ALEN}, | |
{"team0", ETH_ALEN}, | |
{"veth0_to_bridge", ETH_ALEN}, | |
{"veth1_to_bridge", ETH_ALEN}, | |
{"veth0_to_bond", ETH_ALEN}, | |
{"veth1_to_bond", ETH_ALEN}, | |
{"veth0_to_team", ETH_ALEN}, | |
{"veth1_to_team", ETH_ALEN}, | |
{"veth0_to_hsr", ETH_ALEN}, | |
{"veth1_to_hsr", ETH_ALEN}, | |
{"hsr0", 0}, | |
{"dummy0", ETH_ALEN}, | |
{"nlmon0", 0}, | |
{"vxcan0", 0, true}, | |
{"vxcan1", 0, true}, | |
{"caif0", ETH_ALEN}, | |
{"batadv0", ETH_ALEN}, | |
{netdevsim, ETH_ALEN}, | |
{"xfrm0", ETH_ALEN}, | |
{"veth0_virt_wifi", ETH_ALEN}, | |
{"veth1_virt_wifi", ETH_ALEN}, | |
{"virt_wifi0", ETH_ALEN}, | |
{"veth0_vlan", ETH_ALEN}, | |
{"veth1_vlan", ETH_ALEN}, | |
{"vlan0", ETH_ALEN}, | |
{"vlan1", ETH_ALEN}, | |
{"macvlan0", ETH_ALEN}, | |
{"macvlan1", ETH_ALEN}, | |
{"ipvlan0", ETH_ALEN}, | |
{"ipvlan1", ETH_ALEN}, | |
{"veth0_macvtap", ETH_ALEN}, | |
{"veth1_macvtap", ETH_ALEN}, | |
{"macvtap0", ETH_ALEN}, | |
{"macsec0", ETH_ALEN}, | |
{"veth0_to_batadv", ETH_ALEN}, | |
{"veth1_to_batadv", ETH_ALEN}, | |
{"batadv_slave_0", ETH_ALEN}, | |
{"batadv_slave_1", ETH_ALEN}, | |
{"geneve0", ETH_ALEN}, | |
{"geneve1", ETH_ALEN}, | |
{"wg0", 0}, | |
{"wg1", 0}, | |
{"wg2", 0}, | |
}; | |
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); | |
if (sock == -1) | |
exit(1); | |
unsigned i; | |
for (i = 0; i < sizeof(devtypes) / sizeof(devtypes[0]); i++) | |
netlink_add_device(&nlmsg, sock, devtypes[i].type, devtypes[i].dev); | |
for (i = 0; i < sizeof(devmasters) / (sizeof(devmasters[0])); i++) { | |
char master[32], slave0[32], veth0[32], slave1[32], veth1[32]; | |
sprintf(slave0, "%s_slave_0", devmasters[i]); | |
sprintf(veth0, "veth0_to_%s", devmasters[i]); | |
netlink_add_veth(&nlmsg, sock, slave0, veth0); | |
sprintf(slave1, "%s_slave_1", devmasters[i]); | |
sprintf(veth1, "veth1_to_%s", devmasters[i]); | |
netlink_add_veth(&nlmsg, sock, slave1, veth1); | |
sprintf(master, "%s0", devmasters[i]); | |
netlink_device_change(&nlmsg, sock, slave0, false, master, 0, 0, NULL); | |
netlink_device_change(&nlmsg, sock, slave1, false, master, 0, 0, NULL); | |
} | |
netlink_add_xfrm(&nlmsg, sock, "xfrm0"); | |
netlink_device_change(&nlmsg, sock, "bridge_slave_0", true, 0, 0, 0, NULL); | |
netlink_device_change(&nlmsg, sock, "bridge_slave_1", true, 0, 0, 0, NULL); | |
netlink_add_veth(&nlmsg, sock, "hsr_slave_0", "veth0_to_hsr"); | |
netlink_add_veth(&nlmsg, sock, "hsr_slave_1", "veth1_to_hsr"); | |
netlink_add_hsr(&nlmsg, sock, "hsr0", "hsr_slave_0", "hsr_slave_1"); | |
netlink_device_change(&nlmsg, sock, "hsr_slave_0", true, 0, 0, 0, NULL); | |
netlink_device_change(&nlmsg, sock, "hsr_slave_1", true, 0, 0, 0, NULL); | |
netlink_add_veth(&nlmsg, sock, "veth0_virt_wifi", "veth1_virt_wifi"); | |
netlink_add_linked(&nlmsg, sock, "virt_wifi", "virt_wifi0", | |
"veth1_virt_wifi"); | |
netlink_add_veth(&nlmsg, sock, "veth0_vlan", "veth1_vlan"); | |
netlink_add_vlan(&nlmsg, sock, "vlan0", "veth0_vlan", 0, htons(ETH_P_8021Q)); | |
netlink_add_vlan(&nlmsg, sock, "vlan1", "veth0_vlan", 1, htons(ETH_P_8021AD)); | |
netlink_add_macvlan(&nlmsg, sock, "macvlan0", "veth1_vlan"); | |
netlink_add_macvlan(&nlmsg, sock, "macvlan1", "veth1_vlan"); | |
netlink_add_ipvlan(&nlmsg, sock, "ipvlan0", "veth0_vlan", IPVLAN_MODE_L2, 0); | |
netlink_add_ipvlan(&nlmsg, sock, "ipvlan1", "veth0_vlan", IPVLAN_MODE_L3S, | |
IPVLAN_F_VEPA); | |
netlink_add_veth(&nlmsg, sock, "veth0_macvtap", "veth1_macvtap"); | |
netlink_add_linked(&nlmsg, sock, "macvtap", "macvtap0", "veth0_macvtap"); | |
netlink_add_linked(&nlmsg, sock, "macsec", "macsec0", "veth1_macvtap"); | |
char addr[32]; | |
sprintf(addr, DEV_IPV4, 14 + 10); | |
struct in_addr geneve_addr4; | |
if (inet_pton(AF_INET, addr, &geneve_addr4) <= 0) | |
exit(1); | |
struct in6_addr geneve_addr6; | |
if (inet_pton(AF_INET6, "fc00::01", &geneve_addr6) <= 0) | |
exit(1); | |
netlink_add_geneve(&nlmsg, sock, "geneve0", 0, &geneve_addr4, 0); | |
netlink_add_geneve(&nlmsg, sock, "geneve1", 1, 0, &geneve_addr6); | |
netdevsim_add((int)procid, 4); | |
netlink_wireguard_setup(); | |
for (i = 0; i < sizeof(devices) / (sizeof(devices[0])); i++) { | |
char addr[32]; | |
sprintf(addr, DEV_IPV4, i + 10); | |
netlink_add_addr4(&nlmsg, sock, devices[i].name, addr); | |
if (!devices[i].noipv6) { | |
sprintf(addr, DEV_IPV6, i + 10); | |
netlink_add_addr6(&nlmsg, sock, devices[i].name, addr); | |
} | |
uint64_t macaddr = DEV_MAC + ((i + 10ull) << 40); | |
netlink_device_change(&nlmsg, sock, devices[i].name, true, 0, &macaddr, | |
devices[i].macsize, NULL); | |
} | |
close(sock); | |
} | |
static void initialize_netdevices_init(void) { | |
int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); | |
if (sock == -1) | |
exit(1); | |
struct { | |
const char* type; | |
int macsize; | |
bool noipv6; | |
bool noup; | |
} devtypes[] = { | |
{"nr", 7, true}, | |
{"rose", 5, true, true}, | |
}; | |
unsigned i; | |
for (i = 0; i < sizeof(devtypes) / sizeof(devtypes[0]); i++) { | |
char dev[32], addr[32]; | |
sprintf(dev, "%s%d", devtypes[i].type, (int)procid); | |
sprintf(addr, "172.30.%d.%d", i, (int)procid + 1); | |
netlink_add_addr4(&nlmsg, sock, dev, addr); | |
if (!devtypes[i].noipv6) { | |
sprintf(addr, "fe88::%02x:%02x", i, (int)procid + 1); | |
netlink_add_addr6(&nlmsg, sock, dev, addr); | |
} | |
int macsize = devtypes[i].macsize; | |
uint64_t macaddr = 0xbbbbbb + | |
((unsigned long long)i << (8 * (macsize - 2))) + | |
(procid << (8 * (macsize - 1))); | |
netlink_device_change(&nlmsg, sock, dev, !devtypes[i].noup, 0, &macaddr, | |
macsize, NULL); | |
} | |
close(sock); | |
} | |
#define MAX_FDS 30 | |
static long syz_genetlink_get_family_id(volatile long name, | |
volatile long sock_arg) { | |
int fd = sock_arg; | |
if (fd < 0) { | |
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); | |
if (fd == -1) { | |
return -1; | |
} | |
} | |
struct nlmsg nlmsg_tmp; | |
int ret = netlink_query_family_id(&nlmsg_tmp, fd, (char*)name, false); | |
if ((int)sock_arg < 0) | |
close(fd); | |
if (ret < 0) { | |
return -1; | |
} | |
return ret; | |
} | |
static void setup_common() { | |
if (mount(0, "/sys/fs/fuse/connections", "fusectl", 0, 0)) { | |
} | |
} | |
static void setup_binderfs() { | |
if (mkdir("/dev/binderfs", 0777)) { | |
} | |
if (mount("binder", "/dev/binderfs", "binder", 0, NULL)) { | |
} | |
if (symlink("/dev/binderfs", "./binderfs")) { | |
} | |
} | |
static void loop(); | |
static void sandbox_common() { | |
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); | |
setsid(); | |
struct rlimit rlim; | |
rlim.rlim_cur = rlim.rlim_max = (200 << 20); | |
setrlimit(RLIMIT_AS, &rlim); | |
rlim.rlim_cur = rlim.rlim_max = 32 << 20; | |
setrlimit(RLIMIT_MEMLOCK, &rlim); | |
rlim.rlim_cur = rlim.rlim_max = 136 << 20; | |
setrlimit(RLIMIT_FSIZE, &rlim); | |
rlim.rlim_cur = rlim.rlim_max = 1 << 20; | |
setrlimit(RLIMIT_STACK, &rlim); | |
rlim.rlim_cur = rlim.rlim_max = 128 << 20; | |
setrlimit(RLIMIT_CORE, &rlim); | |
rlim.rlim_cur = rlim.rlim_max = 256; | |
setrlimit(RLIMIT_NOFILE, &rlim); | |
if (unshare(CLONE_NEWNS)) { | |
} | |
if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) { | |
} | |
if (unshare(CLONE_NEWIPC)) { | |
} | |
if (unshare(0x02000000)) { | |
} | |
if (unshare(CLONE_NEWUTS)) { | |
} | |
if (unshare(CLONE_SYSVSEM)) { | |
} | |
typedef struct { | |
const char* name; | |
const char* value; | |
} sysctl_t; | |
static const sysctl_t sysctls[] = { | |
{"/proc/sys/kernel/shmmax", "16777216"}, | |
{"/proc/sys/kernel/shmall", "536870912"}, | |
{"/proc/sys/kernel/shmmni", "1024"}, | |
{"/proc/sys/kernel/msgmax", "8192"}, | |
{"/proc/sys/kernel/msgmni", "1024"}, | |
{"/proc/sys/kernel/msgmnb", "1024"}, | |
{"/proc/sys/kernel/sem", "1024 1048576 500 1024"}, | |
}; | |
unsigned i; | |
for (i = 0; i < sizeof(sysctls) / sizeof(sysctls[0]); i++) | |
write_file(sysctls[i].name, sysctls[i].value); | |
} | |
static int wait_for_loop(int pid) { | |
if (pid < 0) | |
exit(1); | |
int status = 0; | |
while (waitpid(-1, &status, __WALL) != pid) { | |
} | |
return WEXITSTATUS(status); | |
} | |
static void drop_caps(void) { | |
struct __user_cap_header_struct cap_hdr = {}; | |
struct __user_cap_data_struct cap_data[2] = {}; | |
cap_hdr.version = _LINUX_CAPABILITY_VERSION_3; | |
cap_hdr.pid = getpid(); | |
if (syscall(SYS_capget, &cap_hdr, &cap_data)) | |
exit(1); | |
const int drop = (1 << CAP_SYS_PTRACE) | (1 << CAP_SYS_NICE); | |
cap_data[0].effective &= ~drop; | |
cap_data[0].permitted &= ~drop; | |
cap_data[0].inheritable &= ~drop; | |
if (syscall(SYS_capset, &cap_hdr, &cap_data)) | |
exit(1); | |
} | |
static int do_sandbox_none(void) { | |
if (unshare(CLONE_NEWPID)) { | |
} | |
int pid = fork(); | |
if (pid != 0) | |
return wait_for_loop(pid); | |
setup_common(); | |
sandbox_common(); | |
drop_caps(); | |
initialize_netdevices_init(); | |
if (unshare(CLONE_NEWNET)) { | |
} | |
write_file("/proc/sys/net/ipv4/ping_group_range", "0 65535"); | |
initialize_netdevices(); | |
setup_binderfs(); | |
loop(); | |
exit(1); | |
} | |
static void kill_and_wait(int pid, int* status) { | |
kill(-pid, SIGKILL); | |
kill(pid, SIGKILL); | |
for (int i = 0; i < 100; i++) { | |
if (waitpid(-1, status, WNOHANG | __WALL) == pid) | |
return; | |
usleep(1000); | |
} | |
DIR* dir = opendir("/sys/fs/fuse/connections"); | |
if (dir) { | |
for (;;) { | |
struct dirent* ent = readdir(dir); | |
if (!ent) | |
break; | |
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) | |
continue; | |
char abort[300]; | |
snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort", | |
ent->d_name); | |
int fd = open(abort, O_WRONLY); | |
if (fd == -1) { | |
continue; | |
} | |
if (write(fd, abort, 1) < 0) { | |
} | |
close(fd); | |
} | |
closedir(dir); | |
} else { | |
} | |
while (waitpid(-1, status, __WALL) != pid) { | |
} | |
} | |
static void setup_test() { | |
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); | |
setpgrp(); | |
write_file("/proc/self/oom_score_adj", "1000"); | |
} | |
static void close_fds() { | |
for (int fd = 3; fd < MAX_FDS; fd++) | |
close(fd); | |
} | |
static void execute_one(void); | |
#define WAIT_FLAGS __WALL | |
static void loop(void) { | |
int iter = 0; | |
for (;; iter++) { | |
int pid = fork(); | |
if (pid < 0) | |
exit(1); | |
if (pid == 0) { | |
setup_test(); | |
execute_one(); | |
close_fds(); | |
exit(0); | |
} | |
int status = 0; | |
uint64_t start = current_time_ms(); | |
for (;;) { | |
if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid) | |
break; | |
sleep_ms(1); | |
if (current_time_ms() - start < 5000) | |
continue; | |
kill_and_wait(pid, &status); | |
break; | |
} | |
} | |
} | |
uint64_t r[4] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, | |
0x0}; | |
void execute_one(void) { | |
intptr_t res = 0; | |
res = syscall(__NR_socket, /*domain=*/0x11ul, /*type=*/3ul, /*proto=*/0x300); | |
if (res != -1) | |
r[0] = res; | |
*(uint32_t*)0x20006ffc = 0x200; | |
syscall(__NR_setsockopt, /*fd=*/r[0], /*level=*/0x107, /*optname=*/0xf, | |
/*optval=*/0x20006ffcul, /*optlen=*/0xe50fb6c50bc849c9ul); | |
res = syscall(__NR_socket, /*domain=*/0x10ul, /*type=*/3ul, /*proto=*/0); | |
if (res != -1) | |
r[1] = res; | |
*(uint64_t*)0x20001340 = 0; | |
*(uint32_t*)0x20001348 = 0; | |
*(uint64_t*)0x20001350 = 0x20000800; | |
*(uint64_t*)0x20000800 = 0; | |
*(uint64_t*)0x20000808 = 0; | |
*(uint64_t*)0x20000810 = 0; | |
*(uint64_t*)0x20000818 = 0; | |
*(uint64_t*)0x20000820 = 0; | |
*(uint64_t*)0x20000828 = 0; | |
*(uint64_t*)0x20000830 = 0x200001c0; | |
memcpy((void*)0x200001c0, | |
"\x8f\xc2\x86\x98\x2d\xf8\x34\x00\x25\x8d\x0b\xce\x45\x0d\xcb\x27\x3c" | |
"\x88\x0f\x76\x6d\x6d\x47\xbf\x05\xa0\x14\x6a\x7a\xb1\xcc\xa6\x71\x44" | |
"\x75\xe7\x55\xea\xe9\xcc\x4c\x43\x05", | |
43); | |
*(uint64_t*)0x20000838 = 0x2b; | |
*(uint64_t*)0x20000840 = 0; | |
*(uint64_t*)0x20000848 = 0; | |
*(uint64_t*)0x20000850 = 0; | |
*(uint64_t*)0x20000858 = 0; | |
*(uint64_t*)0x20000860 = 0; | |
*(uint64_t*)0x20000868 = 0; | |
*(uint64_t*)0x20001358 = 7; | |
*(uint64_t*)0x20001360 = 0; | |
*(uint64_t*)0x20001368 = 0; | |
*(uint32_t*)0x20001370 = 0; | |
*(uint32_t*)0x20001378 = 0; | |
*(uint64_t*)0x20001380 = 0; | |
*(uint32_t*)0x20001388 = 0; | |
*(uint64_t*)0x20001390 = 0; | |
*(uint64_t*)0x20001398 = 0; | |
*(uint64_t*)0x200013a0 = 0; | |
*(uint64_t*)0x200013a8 = 0; | |
*(uint32_t*)0x200013b0 = 0; | |
*(uint32_t*)0x200013b8 = 0; | |
*(uint64_t*)0x200013c0 = 0; | |
*(uint32_t*)0x200013c8 = 0; | |
*(uint64_t*)0x200013d0 = 0; | |
*(uint64_t*)0x200013d8 = 0; | |
*(uint64_t*)0x200013e0 = 0; | |
*(uint64_t*)0x200013e8 = 0; | |
*(uint32_t*)0x200013f0 = 0; | |
*(uint32_t*)0x200013f8 = 0; | |
syscall(__NR_sendmmsg, /*fd=*/r[0], /*mmsg=*/0x20001340ul, /*vlen=*/3ul, | |
/*f=*/0x40000ul); | |
res = syscall(__NR_socket, /*domain=*/0x10ul, /*type=*/0x803ul, /*proto=*/0); | |
if (res != -1) | |
r[2] = res; | |
memcpy((void*)0x20000700, "TIPCv2\000", 7); | |
syz_genetlink_get_family_id(/*name=*/0x20000700, /*fd=*/r[2]); | |
*(uint32_t*)0x20000200 = 0x14; | |
res = syscall(__NR_getsockname, /*fd=*/r[2], /*addr=*/0x20001480ul, | |
/*addrlen=*/0x20000200ul); | |
if (res != -1) | |
r[3] = *(uint32_t*)0x20001484; | |
*(uint64_t*)0x20000000 = 0; | |
*(uint32_t*)0x20000008 = 0; | |
*(uint64_t*)0x20000010 = 0x20000140; | |
*(uint64_t*)0x20000140 = 0x20000500; | |
memcpy((void*)0x20000500, | |
"\x3c\x00\x00\x00\x10\x00\x01\x44\x00\xee\xff\xff\xff\xff\x07\x1a\xf7" | |
"\x00\x00\x00", | |
20); | |
*(uint32_t*)0x20000514 = r[3]; | |
memcpy((void*)0x20000518, | |
"\x01\x00\x00\x00\x01\x00\x00\x00\x1c\x00\x12\x00\x0c\x00\x01\x00\x62" | |
"\x72\x69\x64\x67\x65", | |
22); | |
*(uint64_t*)0x20000148 = 0x3c; | |
*(uint64_t*)0x20000018 = 1; | |
*(uint64_t*)0x20000020 = 0; | |
*(uint64_t*)0x20000028 = 0; | |
*(uint32_t*)0x20000030 = 0; | |
syscall(__NR_sendmsg, /*fd=*/r[2], /*msg=*/0x20000000ul, /*f=*/0ul); | |
*(uint64_t*)0x200007c0 = 0; | |
*(uint32_t*)0x200007c8 = 0; | |
*(uint64_t*)0x200007d0 = 0x20000080; | |
*(uint64_t*)0x20000080 = 0x20000180; | |
memcpy((void*)0x20000180, | |
"\x60\x00\x00\x00\x24\x00\x0b\x0e\x00\x00\x00\x00\x00\x80\x00\x00\x00" | |
"\x00\x00\x00", | |
20); | |
*(uint32_t*)0x20000194 = r[3]; | |
memcpy( | |
(void*)0x20000198, | |
"\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x45\x08\x00\x01\x00\x74\x62" | |
"\x66\x00\x34\x00\x02\x00\x08\x00\x06\x00\xa4\x23\x00\x00\x28\x00\x01", | |
35); | |
*(uint64_t*)0x20000088 = 0x60; | |
*(uint64_t*)0x200007d8 = 1; | |
*(uint64_t*)0x200007e0 = 0; | |
*(uint64_t*)0x200007e8 = 0; | |
*(uint32_t*)0x200007f0 = 0; | |
syscall(__NR_sendmsg, /*fd=*/r[1], /*msg=*/0x200007c0ul, /*f=*/0ul); | |
*(uint16_t*)0x20000040 = 0x11; | |
*(uint16_t*)0x20000042 = htobe16(0); | |
*(uint32_t*)0x20000044 = r[3]; | |
*(uint16_t*)0x20000048 = 1; | |
*(uint8_t*)0x2000004a = 0; | |
*(uint8_t*)0x2000004b = 6; | |
memset((void*)0x2000004c, 170, 5); | |
*(uint8_t*)0x20000051 = 0; | |
memset((void*)0x20000052, 0, 2); | |
syscall(__NR_bind, /*fd=*/r[0], /*addr=*/0x20000040ul, /*addrlen=*/0x14ul); | |
memcpy((void*)0x20000280, | |
"\x41\x03\x09\x5c\xf2\x1d\x48\x04\x07\x02\x02\x00\xc5\x2c\xf7\xc2\x59" | |
"\x75\xe0\x05\xb0\x2f\x08\x00\xeb\x2b\x2f\xf0\xda\xc8\x89\x7c\x6b\x11" | |
"\x87\x77\xfa\xff\xff\xff\x30\x66\x09\x0c\xb6\x00\xc5\x47\x1d\x13\x0a" | |
"\x66\x32\x1a\x54\xe7\xdf\x30\x5f\x80\xa8\x81\x61\xb6\xfd\x8f\x24\x28" | |
"\x6a\x57\xc3\xfe\xff\xff", | |
74); | |
syscall(__NR_sendto, /*fd=*/r[0], /*buf=*/0x20000280ul, /*len=*/0x5c13ul, | |
/*f=*/0x806ul, /*addr=*/0ul, /*addrlen=*/0x2ful); | |
} | |
int main(void) { | |
syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, | |
/*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul); | |
syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul, /*prot=*/7ul, | |
/*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul); | |
syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul, /*prot=*/0ul, | |
/*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul); | |
do_sandbox_none(); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
r0 = socket$packet(0x11, 0x3, 0x300) | |
setsockopt$packet_int(r0, 0x107, 0xf, &(0x7f0000006ffc)=0x4000000000000200, 0xe50fb6c50bc849c9) | |
r1 = socket(0x10, 0x3, 0x0) | |
sendmmsg$inet(r0, &(0x7f0000001340)=[{{0x0, 0x0, &(0x7f0000000800)=[{0x0}, {0x0}, {0x0}, {&(0x7f00000001c0)="8fc286982df83400258d0bce450dcb273c880f766d6d47bf05a0146a7ab1cca6714475e755eae9cc4c4305", 0x2b}, {0x0}, {0x0}, {0x0}], 0x7}}, {{0x0, 0x0, 0x0}}, {{0x0, 0x0, 0x0}}], 0x3, 0x40000) | |
r2 = socket(0x10, 0x803, 0x0) | |
syz_genetlink_get_family_id$tipc2(&(0x7f0000000700), r2) | |
getsockname$packet(r2, &(0x7f0000001480)={0x11, 0x0, <r3=>0x0, 0x1, 0x0, 0x6, @broadcast}, &(0x7f0000000200)=0x14) | |
sendmsg$nl_route(r2, &(0x7f0000000000)={0x0, 0x0, &(0x7f0000000140)={&(0x7f0000000500)=ANY=[@ANYBLOB="3c0000001000014400eeffffffff071af7000000", @ANYRES32=r3, @ANYBLOB="01000000010000001c0012000c000100627269646765"], 0x3c}}, 0x0) | |
sendmsg$nl_route_sched(r1, &(0x7f00000007c0)={0x0, 0x0, &(0x7f0000000080)={&(0x7f0000000180)=ANY=[@ANYBLOB="6000000024000b0e000000000080000000000000", @ANYRES32=r3, @ANYBLOB="00000000ffffffff0000004508000100746266003400020008000600a4230000280001"], 0x60}}, 0x0) | |
bind$packet(r0, &(0x7f0000000040)={0x11, 0x0, r3, 0x1, 0x0, 0x6, @dev}, 0x14) | |
sendto$inet6(r0, &(0x7f0000000280)="4103095cf21d480407020200c52cf7c25975e005b02f0800eb2b2ff0dac8897c6b118777faffffff3066090cb600c5471d130a66321a54e7df305f80a88161b6fd8f24286a57c3feffff", 0x5c13, 0x806, 0x0, 0x2f) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment