1 // SPDX-License-Identifier: GPL-2.0 2 3 #define _GNU_SOURCE 4 5 #include <fcntl.h> 6 #include <stdio.h> 7 #include <string.h> 8 #include <sys/socket.h> 9 #include <sys/stat.h> 10 #include <sys/syscall.h> 11 #include <sys/types.h> 12 #include <unistd.h> 13 14 #include <linux/genetlink.h> 15 #include <linux/netlink.h> 16 #include <linux/mqueue.h> 17 18 #include "../kselftest_harness.h" 19 20 static const struct { 21 struct nlmsghdr nlhdr; 22 struct genlmsghdr genlhdr; 23 struct nlattr ahdr; 24 __u16 val; 25 __u16 pad; 26 } dump_policies = { 27 .nlhdr = { 28 .nlmsg_len = sizeof(dump_policies), 29 .nlmsg_type = GENL_ID_CTRL, 30 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP, 31 .nlmsg_seq = 1, 32 }, 33 .genlhdr = { 34 .cmd = CTRL_CMD_GETPOLICY, 35 .version = 2, 36 }, 37 .ahdr = { 38 .nla_len = 6, 39 .nla_type = CTRL_ATTR_FAMILY_ID, 40 }, 41 .val = GENL_ID_CTRL, 42 .pad = 0, 43 }; 44 45 // Sanity check for the test itself, make sure the dump doesn't fit in one msg 46 TEST(test_sanity) 47 { 48 int netlink_sock; 49 char buf[8192]; 50 ssize_t n; 51 52 netlink_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); 53 ASSERT_GE(netlink_sock, 0); 54 55 n = send(netlink_sock, &dump_policies, sizeof(dump_policies), 0); 56 ASSERT_EQ(n, sizeof(dump_policies)); 57 58 n = recv(netlink_sock, buf, sizeof(buf), MSG_DONTWAIT); 59 ASSERT_GE(n, (ssize_t)sizeof(struct nlmsghdr)); 60 61 n = recv(netlink_sock, buf, sizeof(buf), MSG_DONTWAIT); 62 ASSERT_GE(n, (ssize_t)sizeof(struct nlmsghdr)); 63 64 close(netlink_sock); 65 } 66 67 TEST(close_in_progress) 68 { 69 int netlink_sock; 70 ssize_t n; 71 72 netlink_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); 73 ASSERT_GE(netlink_sock, 0); 74 75 n = send(netlink_sock, &dump_policies, sizeof(dump_policies), 0); 76 ASSERT_EQ(n, sizeof(dump_policies)); 77 78 close(netlink_sock); 79 } 80 81 TEST(close_with_ref) 82 { 83 char cookie[NOTIFY_COOKIE_LEN] = {}; 84 int netlink_sock, mq_fd; 85 struct sigevent sigev; 86 ssize_t n; 87 88 netlink_sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC); 89 ASSERT_GE(netlink_sock, 0); 90 91 n = send(netlink_sock, &dump_policies, sizeof(dump_policies), 0); 92 ASSERT_EQ(n, sizeof(dump_policies)); 93 94 mq_fd = syscall(__NR_mq_open, "sed", O_CREAT | O_WRONLY, 0600, 0); 95 ASSERT_GE(mq_fd, 0); 96 97 memset(&sigev, 0, sizeof(sigev)); 98 sigev.sigev_notify = SIGEV_THREAD; 99 sigev.sigev_value.sival_ptr = cookie; 100 sigev.sigev_signo = netlink_sock; 101 102 syscall(__NR_mq_notify, mq_fd, &sigev); 103 104 close(netlink_sock); 105 106 // give mqueue time to fire 107 usleep(100 * 1000); 108 } 109 110 TEST_HARNESS_MAIN 111