111 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#define _GNU_SOURCE4 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 20static 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 msg46TEST(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, sizeof(struct nlmsghdr));60 61 n = recv(netlink_sock, buf, sizeof(buf), MSG_DONTWAIT);62 ASSERT_GE(n, sizeof(struct nlmsghdr));63 64 close(netlink_sock);65}66 67TEST(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 81TEST(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 fire107 usleep(100 * 1000);108}109 110TEST_HARNESS_MAIN111