af_unix: Add test for sock_diag and UDIAG_SHOW_UID.
[platform/kernel/linux-starfive.git] / tools / testing / selftests / net / af_unix / diag_uid.c
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright Amazon.com Inc. or its affiliates. */
3
4 #define _GNU_SOURCE
5 #include <sched.h>
6
7 #include <unistd.h>
8 #include <linux/netlink.h>
9 #include <linux/rtnetlink.h>
10 #include <linux/sock_diag.h>
11 #include <linux/unix_diag.h>
12 #include <sys/socket.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 #include <sys/un.h>
16
17 #include "../../kselftest_harness.h"
18
19 FIXTURE(diag_uid)
20 {
21         int netlink_fd;
22         int unix_fd;
23         __u32 inode;
24         __u64 cookie;
25 };
26
27 FIXTURE_VARIANT(diag_uid)
28 {
29         int unshare;
30         int udiag_show;
31 };
32
33 FIXTURE_VARIANT_ADD(diag_uid, uid)
34 {
35         .unshare = 0,
36         .udiag_show = UDIAG_SHOW_UID
37 };
38
39 FIXTURE_VARIANT_ADD(diag_uid, uid_unshare)
40 {
41         .unshare = CLONE_NEWUSER,
42         .udiag_show = UDIAG_SHOW_UID
43 };
44
45 FIXTURE_SETUP(diag_uid)
46 {
47         struct stat file_stat;
48         socklen_t optlen;
49         int ret;
50
51         if (variant->unshare)
52                 ASSERT_EQ(unshare(variant->unshare), 0);
53
54         self->netlink_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG);
55         ASSERT_NE(self->netlink_fd, -1);
56
57         self->unix_fd = socket(AF_UNIX, SOCK_STREAM, 0);
58         ASSERT_NE(self->unix_fd, -1);
59
60         ret = fstat(self->unix_fd, &file_stat);
61         ASSERT_EQ(ret, 0);
62
63         self->inode = file_stat.st_ino;
64
65         optlen = sizeof(self->cookie);
66         ret = getsockopt(self->unix_fd, SOL_SOCKET, SO_COOKIE, &self->cookie, &optlen);
67         ASSERT_EQ(ret, 0);
68 }
69
70 FIXTURE_TEARDOWN(diag_uid)
71 {
72         close(self->netlink_fd);
73         close(self->unix_fd);
74 }
75
76 int send_request(struct __test_metadata *_metadata,
77                  FIXTURE_DATA(diag_uid) *self,
78                  const FIXTURE_VARIANT(diag_uid) *variant)
79 {
80         struct {
81                 struct nlmsghdr nlh;
82                 struct unix_diag_req udr;
83         } req = {
84                 .nlh = {
85                         .nlmsg_len = sizeof(req),
86                         .nlmsg_type = SOCK_DIAG_BY_FAMILY,
87                         .nlmsg_flags = NLM_F_REQUEST
88                 },
89                 .udr = {
90                         .sdiag_family = AF_UNIX,
91                         .udiag_ino = self->inode,
92                         .udiag_cookie = {
93                                 (__u32)self->cookie,
94                                 (__u32)(self->cookie >> 32)
95                         },
96                         .udiag_show = variant->udiag_show
97                 }
98         };
99         struct sockaddr_nl nladdr = {
100                 .nl_family = AF_NETLINK
101         };
102         struct iovec iov = {
103                 .iov_base = &req,
104                 .iov_len = sizeof(req)
105         };
106         struct msghdr msg = {
107                 .msg_name = &nladdr,
108                 .msg_namelen = sizeof(nladdr),
109                 .msg_iov = &iov,
110                 .msg_iovlen = 1
111         };
112
113         return sendmsg(self->netlink_fd, &msg, 0);
114 }
115
116 void render_response(struct __test_metadata *_metadata,
117                      struct unix_diag_req *udr, __u32 len)
118 {
119         unsigned int rta_len = len - NLMSG_LENGTH(sizeof(*udr));
120         struct rtattr *attr;
121         uid_t uid;
122
123         ASSERT_GT(len, sizeof(*udr));
124         ASSERT_EQ(udr->sdiag_family, AF_UNIX);
125
126         attr = (struct rtattr *)(udr + 1);
127         ASSERT_NE(RTA_OK(attr, rta_len), 0);
128         ASSERT_EQ(attr->rta_type, UNIX_DIAG_UID);
129
130         uid = *(uid_t *)RTA_DATA(attr);
131         ASSERT_EQ(uid, getuid());
132 }
133
134 void receive_response(struct __test_metadata *_metadata,
135                       FIXTURE_DATA(diag_uid) *self)
136 {
137         long buf[8192 / sizeof(long)];
138         struct sockaddr_nl nladdr = {
139                 .nl_family = AF_NETLINK
140         };
141         struct iovec iov = {
142                 .iov_base = buf,
143                 .iov_len = sizeof(buf)
144         };
145         struct msghdr msg = {
146                 .msg_name = &nladdr,
147                 .msg_namelen = sizeof(nladdr),
148                 .msg_iov = &iov,
149                 .msg_iovlen = 1
150         };
151         struct unix_diag_req *udr;
152         struct nlmsghdr *nlh;
153         int ret;
154
155         ret = recvmsg(self->netlink_fd, &msg, 0);
156         ASSERT_GT(ret, 0);
157
158         nlh = (struct nlmsghdr *)buf;
159         ASSERT_NE(NLMSG_OK(nlh, ret), 0);
160         ASSERT_EQ(nlh->nlmsg_type, SOCK_DIAG_BY_FAMILY);
161
162         render_response(_metadata, NLMSG_DATA(nlh), nlh->nlmsg_len);
163
164         nlh = NLMSG_NEXT(nlh, ret);
165         ASSERT_EQ(NLMSG_OK(nlh, ret), 0);
166 }
167
168 TEST_F(diag_uid, 1)
169 {
170         int ret;
171
172         ret = send_request(_metadata, self, variant);
173         ASSERT_GT(ret, 0);
174
175         receive_response(_metadata, self);
176 }
177
178 TEST_HARNESS_MAIN