1*ec80f488SAlexander Mikhalitsyn // SPDX-License-Identifier: GPL-2.0 OR MIT
2*ec80f488SAlexander Mikhalitsyn #define _GNU_SOURCE
3*ec80f488SAlexander Mikhalitsyn #include <error.h>
4*ec80f488SAlexander Mikhalitsyn #include <limits.h>
5*ec80f488SAlexander Mikhalitsyn #include <stddef.h>
6*ec80f488SAlexander Mikhalitsyn #include <stdio.h>
7*ec80f488SAlexander Mikhalitsyn #include <stdlib.h>
8*ec80f488SAlexander Mikhalitsyn #include <sys/socket.h>
9*ec80f488SAlexander Mikhalitsyn #include <linux/socket.h>
10*ec80f488SAlexander Mikhalitsyn #include <unistd.h>
11*ec80f488SAlexander Mikhalitsyn #include <string.h>
12*ec80f488SAlexander Mikhalitsyn #include <errno.h>
13*ec80f488SAlexander Mikhalitsyn #include <sys/un.h>
14*ec80f488SAlexander Mikhalitsyn #include <sys/signal.h>
15*ec80f488SAlexander Mikhalitsyn #include <sys/types.h>
16*ec80f488SAlexander Mikhalitsyn #include <sys/wait.h>
17*ec80f488SAlexander Mikhalitsyn
18*ec80f488SAlexander Mikhalitsyn #include "../../kselftest_harness.h"
19*ec80f488SAlexander Mikhalitsyn
20*ec80f488SAlexander Mikhalitsyn #define clean_errno() (errno == 0 ? "None" : strerror(errno))
21*ec80f488SAlexander Mikhalitsyn #define log_err(MSG, ...) \
22*ec80f488SAlexander Mikhalitsyn fprintf(stderr, "(%s:%d: errno: %s) " MSG "\n", __FILE__, __LINE__, \
23*ec80f488SAlexander Mikhalitsyn clean_errno(), ##__VA_ARGS__)
24*ec80f488SAlexander Mikhalitsyn
25*ec80f488SAlexander Mikhalitsyn #ifndef SCM_PIDFD
26*ec80f488SAlexander Mikhalitsyn #define SCM_PIDFD 0x04
27*ec80f488SAlexander Mikhalitsyn #endif
28*ec80f488SAlexander Mikhalitsyn
child_die()29*ec80f488SAlexander Mikhalitsyn static void child_die()
30*ec80f488SAlexander Mikhalitsyn {
31*ec80f488SAlexander Mikhalitsyn exit(1);
32*ec80f488SAlexander Mikhalitsyn }
33*ec80f488SAlexander Mikhalitsyn
safe_int(const char * numstr,int * converted)34*ec80f488SAlexander Mikhalitsyn static int safe_int(const char *numstr, int *converted)
35*ec80f488SAlexander Mikhalitsyn {
36*ec80f488SAlexander Mikhalitsyn char *err = NULL;
37*ec80f488SAlexander Mikhalitsyn long sli;
38*ec80f488SAlexander Mikhalitsyn
39*ec80f488SAlexander Mikhalitsyn errno = 0;
40*ec80f488SAlexander Mikhalitsyn sli = strtol(numstr, &err, 0);
41*ec80f488SAlexander Mikhalitsyn if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN))
42*ec80f488SAlexander Mikhalitsyn return -ERANGE;
43*ec80f488SAlexander Mikhalitsyn
44*ec80f488SAlexander Mikhalitsyn if (errno != 0 && sli == 0)
45*ec80f488SAlexander Mikhalitsyn return -EINVAL;
46*ec80f488SAlexander Mikhalitsyn
47*ec80f488SAlexander Mikhalitsyn if (err == numstr || *err != '\0')
48*ec80f488SAlexander Mikhalitsyn return -EINVAL;
49*ec80f488SAlexander Mikhalitsyn
50*ec80f488SAlexander Mikhalitsyn if (sli > INT_MAX || sli < INT_MIN)
51*ec80f488SAlexander Mikhalitsyn return -ERANGE;
52*ec80f488SAlexander Mikhalitsyn
53*ec80f488SAlexander Mikhalitsyn *converted = (int)sli;
54*ec80f488SAlexander Mikhalitsyn return 0;
55*ec80f488SAlexander Mikhalitsyn }
56*ec80f488SAlexander Mikhalitsyn
char_left_gc(const char * buffer,size_t len)57*ec80f488SAlexander Mikhalitsyn static int char_left_gc(const char *buffer, size_t len)
58*ec80f488SAlexander Mikhalitsyn {
59*ec80f488SAlexander Mikhalitsyn size_t i;
60*ec80f488SAlexander Mikhalitsyn
61*ec80f488SAlexander Mikhalitsyn for (i = 0; i < len; i++) {
62*ec80f488SAlexander Mikhalitsyn if (buffer[i] == ' ' || buffer[i] == '\t')
63*ec80f488SAlexander Mikhalitsyn continue;
64*ec80f488SAlexander Mikhalitsyn
65*ec80f488SAlexander Mikhalitsyn return i;
66*ec80f488SAlexander Mikhalitsyn }
67*ec80f488SAlexander Mikhalitsyn
68*ec80f488SAlexander Mikhalitsyn return 0;
69*ec80f488SAlexander Mikhalitsyn }
70*ec80f488SAlexander Mikhalitsyn
char_right_gc(const char * buffer,size_t len)71*ec80f488SAlexander Mikhalitsyn static int char_right_gc(const char *buffer, size_t len)
72*ec80f488SAlexander Mikhalitsyn {
73*ec80f488SAlexander Mikhalitsyn int i;
74*ec80f488SAlexander Mikhalitsyn
75*ec80f488SAlexander Mikhalitsyn for (i = len - 1; i >= 0; i--) {
76*ec80f488SAlexander Mikhalitsyn if (buffer[i] == ' ' || buffer[i] == '\t' ||
77*ec80f488SAlexander Mikhalitsyn buffer[i] == '\n' || buffer[i] == '\0')
78*ec80f488SAlexander Mikhalitsyn continue;
79*ec80f488SAlexander Mikhalitsyn
80*ec80f488SAlexander Mikhalitsyn return i + 1;
81*ec80f488SAlexander Mikhalitsyn }
82*ec80f488SAlexander Mikhalitsyn
83*ec80f488SAlexander Mikhalitsyn return 0;
84*ec80f488SAlexander Mikhalitsyn }
85*ec80f488SAlexander Mikhalitsyn
trim_whitespace_in_place(char * buffer)86*ec80f488SAlexander Mikhalitsyn static char *trim_whitespace_in_place(char *buffer)
87*ec80f488SAlexander Mikhalitsyn {
88*ec80f488SAlexander Mikhalitsyn buffer += char_left_gc(buffer, strlen(buffer));
89*ec80f488SAlexander Mikhalitsyn buffer[char_right_gc(buffer, strlen(buffer))] = '\0';
90*ec80f488SAlexander Mikhalitsyn return buffer;
91*ec80f488SAlexander Mikhalitsyn }
92*ec80f488SAlexander Mikhalitsyn
93*ec80f488SAlexander Mikhalitsyn /* borrowed (with all helpers) from pidfd/pidfd_open_test.c */
get_pid_from_fdinfo_file(int pidfd,const char * key,size_t keylen)94*ec80f488SAlexander Mikhalitsyn static pid_t get_pid_from_fdinfo_file(int pidfd, const char *key, size_t keylen)
95*ec80f488SAlexander Mikhalitsyn {
96*ec80f488SAlexander Mikhalitsyn int ret;
97*ec80f488SAlexander Mikhalitsyn char path[512];
98*ec80f488SAlexander Mikhalitsyn FILE *f;
99*ec80f488SAlexander Mikhalitsyn size_t n = 0;
100*ec80f488SAlexander Mikhalitsyn pid_t result = -1;
101*ec80f488SAlexander Mikhalitsyn char *line = NULL;
102*ec80f488SAlexander Mikhalitsyn
103*ec80f488SAlexander Mikhalitsyn snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", pidfd);
104*ec80f488SAlexander Mikhalitsyn
105*ec80f488SAlexander Mikhalitsyn f = fopen(path, "re");
106*ec80f488SAlexander Mikhalitsyn if (!f)
107*ec80f488SAlexander Mikhalitsyn return -1;
108*ec80f488SAlexander Mikhalitsyn
109*ec80f488SAlexander Mikhalitsyn while (getline(&line, &n, f) != -1) {
110*ec80f488SAlexander Mikhalitsyn char *numstr;
111*ec80f488SAlexander Mikhalitsyn
112*ec80f488SAlexander Mikhalitsyn if (strncmp(line, key, keylen))
113*ec80f488SAlexander Mikhalitsyn continue;
114*ec80f488SAlexander Mikhalitsyn
115*ec80f488SAlexander Mikhalitsyn numstr = trim_whitespace_in_place(line + 4);
116*ec80f488SAlexander Mikhalitsyn ret = safe_int(numstr, &result);
117*ec80f488SAlexander Mikhalitsyn if (ret < 0)
118*ec80f488SAlexander Mikhalitsyn goto out;
119*ec80f488SAlexander Mikhalitsyn
120*ec80f488SAlexander Mikhalitsyn break;
121*ec80f488SAlexander Mikhalitsyn }
122*ec80f488SAlexander Mikhalitsyn
123*ec80f488SAlexander Mikhalitsyn out:
124*ec80f488SAlexander Mikhalitsyn free(line);
125*ec80f488SAlexander Mikhalitsyn fclose(f);
126*ec80f488SAlexander Mikhalitsyn return result;
127*ec80f488SAlexander Mikhalitsyn }
128*ec80f488SAlexander Mikhalitsyn
cmsg_check(int fd)129*ec80f488SAlexander Mikhalitsyn static int cmsg_check(int fd)
130*ec80f488SAlexander Mikhalitsyn {
131*ec80f488SAlexander Mikhalitsyn struct msghdr msg = { 0 };
132*ec80f488SAlexander Mikhalitsyn struct cmsghdr *cmsg;
133*ec80f488SAlexander Mikhalitsyn struct iovec iov;
134*ec80f488SAlexander Mikhalitsyn struct ucred *ucred = NULL;
135*ec80f488SAlexander Mikhalitsyn int data = 0;
136*ec80f488SAlexander Mikhalitsyn char control[CMSG_SPACE(sizeof(struct ucred)) +
137*ec80f488SAlexander Mikhalitsyn CMSG_SPACE(sizeof(int))] = { 0 };
138*ec80f488SAlexander Mikhalitsyn int *pidfd = NULL;
139*ec80f488SAlexander Mikhalitsyn pid_t parent_pid;
140*ec80f488SAlexander Mikhalitsyn int err;
141*ec80f488SAlexander Mikhalitsyn
142*ec80f488SAlexander Mikhalitsyn iov.iov_base = &data;
143*ec80f488SAlexander Mikhalitsyn iov.iov_len = sizeof(data);
144*ec80f488SAlexander Mikhalitsyn
145*ec80f488SAlexander Mikhalitsyn msg.msg_iov = &iov;
146*ec80f488SAlexander Mikhalitsyn msg.msg_iovlen = 1;
147*ec80f488SAlexander Mikhalitsyn msg.msg_control = control;
148*ec80f488SAlexander Mikhalitsyn msg.msg_controllen = sizeof(control);
149*ec80f488SAlexander Mikhalitsyn
150*ec80f488SAlexander Mikhalitsyn err = recvmsg(fd, &msg, 0);
151*ec80f488SAlexander Mikhalitsyn if (err < 0) {
152*ec80f488SAlexander Mikhalitsyn log_err("recvmsg");
153*ec80f488SAlexander Mikhalitsyn return 1;
154*ec80f488SAlexander Mikhalitsyn }
155*ec80f488SAlexander Mikhalitsyn
156*ec80f488SAlexander Mikhalitsyn if (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) {
157*ec80f488SAlexander Mikhalitsyn log_err("recvmsg: truncated");
158*ec80f488SAlexander Mikhalitsyn return 1;
159*ec80f488SAlexander Mikhalitsyn }
160*ec80f488SAlexander Mikhalitsyn
161*ec80f488SAlexander Mikhalitsyn for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
162*ec80f488SAlexander Mikhalitsyn cmsg = CMSG_NXTHDR(&msg, cmsg)) {
163*ec80f488SAlexander Mikhalitsyn if (cmsg->cmsg_level == SOL_SOCKET &&
164*ec80f488SAlexander Mikhalitsyn cmsg->cmsg_type == SCM_PIDFD) {
165*ec80f488SAlexander Mikhalitsyn if (cmsg->cmsg_len < sizeof(*pidfd)) {
166*ec80f488SAlexander Mikhalitsyn log_err("CMSG parse: SCM_PIDFD wrong len");
167*ec80f488SAlexander Mikhalitsyn return 1;
168*ec80f488SAlexander Mikhalitsyn }
169*ec80f488SAlexander Mikhalitsyn
170*ec80f488SAlexander Mikhalitsyn pidfd = (void *)CMSG_DATA(cmsg);
171*ec80f488SAlexander Mikhalitsyn }
172*ec80f488SAlexander Mikhalitsyn
173*ec80f488SAlexander Mikhalitsyn if (cmsg->cmsg_level == SOL_SOCKET &&
174*ec80f488SAlexander Mikhalitsyn cmsg->cmsg_type == SCM_CREDENTIALS) {
175*ec80f488SAlexander Mikhalitsyn if (cmsg->cmsg_len < sizeof(*ucred)) {
176*ec80f488SAlexander Mikhalitsyn log_err("CMSG parse: SCM_CREDENTIALS wrong len");
177*ec80f488SAlexander Mikhalitsyn return 1;
178*ec80f488SAlexander Mikhalitsyn }
179*ec80f488SAlexander Mikhalitsyn
180*ec80f488SAlexander Mikhalitsyn ucred = (void *)CMSG_DATA(cmsg);
181*ec80f488SAlexander Mikhalitsyn }
182*ec80f488SAlexander Mikhalitsyn }
183*ec80f488SAlexander Mikhalitsyn
184*ec80f488SAlexander Mikhalitsyn /* send(pfd, "x", sizeof(char), 0) */
185*ec80f488SAlexander Mikhalitsyn if (data != 'x') {
186*ec80f488SAlexander Mikhalitsyn log_err("recvmsg: data corruption");
187*ec80f488SAlexander Mikhalitsyn return 1;
188*ec80f488SAlexander Mikhalitsyn }
189*ec80f488SAlexander Mikhalitsyn
190*ec80f488SAlexander Mikhalitsyn if (!pidfd) {
191*ec80f488SAlexander Mikhalitsyn log_err("CMSG parse: SCM_PIDFD not found");
192*ec80f488SAlexander Mikhalitsyn return 1;
193*ec80f488SAlexander Mikhalitsyn }
194*ec80f488SAlexander Mikhalitsyn
195*ec80f488SAlexander Mikhalitsyn if (!ucred) {
196*ec80f488SAlexander Mikhalitsyn log_err("CMSG parse: SCM_CREDENTIALS not found");
197*ec80f488SAlexander Mikhalitsyn return 1;
198*ec80f488SAlexander Mikhalitsyn }
199*ec80f488SAlexander Mikhalitsyn
200*ec80f488SAlexander Mikhalitsyn /* pidfd from SCM_PIDFD should point to the parent process PID */
201*ec80f488SAlexander Mikhalitsyn parent_pid =
202*ec80f488SAlexander Mikhalitsyn get_pid_from_fdinfo_file(*pidfd, "Pid:", sizeof("Pid:") - 1);
203*ec80f488SAlexander Mikhalitsyn if (parent_pid != getppid()) {
204*ec80f488SAlexander Mikhalitsyn log_err("wrong SCM_PIDFD %d != %d", parent_pid, getppid());
205*ec80f488SAlexander Mikhalitsyn return 1;
206*ec80f488SAlexander Mikhalitsyn }
207*ec80f488SAlexander Mikhalitsyn
208*ec80f488SAlexander Mikhalitsyn return 0;
209*ec80f488SAlexander Mikhalitsyn }
210*ec80f488SAlexander Mikhalitsyn
211*ec80f488SAlexander Mikhalitsyn struct sock_addr {
212*ec80f488SAlexander Mikhalitsyn char sock_name[32];
213*ec80f488SAlexander Mikhalitsyn struct sockaddr_un listen_addr;
214*ec80f488SAlexander Mikhalitsyn socklen_t addrlen;
215*ec80f488SAlexander Mikhalitsyn };
216*ec80f488SAlexander Mikhalitsyn
FIXTURE(scm_pidfd)217*ec80f488SAlexander Mikhalitsyn FIXTURE(scm_pidfd)
218*ec80f488SAlexander Mikhalitsyn {
219*ec80f488SAlexander Mikhalitsyn int server;
220*ec80f488SAlexander Mikhalitsyn pid_t client_pid;
221*ec80f488SAlexander Mikhalitsyn int startup_pipe[2];
222*ec80f488SAlexander Mikhalitsyn struct sock_addr server_addr;
223*ec80f488SAlexander Mikhalitsyn struct sock_addr *client_addr;
224*ec80f488SAlexander Mikhalitsyn };
225*ec80f488SAlexander Mikhalitsyn
FIXTURE_VARIANT(scm_pidfd)226*ec80f488SAlexander Mikhalitsyn FIXTURE_VARIANT(scm_pidfd)
227*ec80f488SAlexander Mikhalitsyn {
228*ec80f488SAlexander Mikhalitsyn int type;
229*ec80f488SAlexander Mikhalitsyn bool abstract;
230*ec80f488SAlexander Mikhalitsyn };
231*ec80f488SAlexander Mikhalitsyn
FIXTURE_VARIANT_ADD(scm_pidfd,stream_pathname)232*ec80f488SAlexander Mikhalitsyn FIXTURE_VARIANT_ADD(scm_pidfd, stream_pathname)
233*ec80f488SAlexander Mikhalitsyn {
234*ec80f488SAlexander Mikhalitsyn .type = SOCK_STREAM,
235*ec80f488SAlexander Mikhalitsyn .abstract = 0,
236*ec80f488SAlexander Mikhalitsyn };
237*ec80f488SAlexander Mikhalitsyn
FIXTURE_VARIANT_ADD(scm_pidfd,stream_abstract)238*ec80f488SAlexander Mikhalitsyn FIXTURE_VARIANT_ADD(scm_pidfd, stream_abstract)
239*ec80f488SAlexander Mikhalitsyn {
240*ec80f488SAlexander Mikhalitsyn .type = SOCK_STREAM,
241*ec80f488SAlexander Mikhalitsyn .abstract = 1,
242*ec80f488SAlexander Mikhalitsyn };
243*ec80f488SAlexander Mikhalitsyn
FIXTURE_VARIANT_ADD(scm_pidfd,dgram_pathname)244*ec80f488SAlexander Mikhalitsyn FIXTURE_VARIANT_ADD(scm_pidfd, dgram_pathname)
245*ec80f488SAlexander Mikhalitsyn {
246*ec80f488SAlexander Mikhalitsyn .type = SOCK_DGRAM,
247*ec80f488SAlexander Mikhalitsyn .abstract = 0,
248*ec80f488SAlexander Mikhalitsyn };
249*ec80f488SAlexander Mikhalitsyn
FIXTURE_VARIANT_ADD(scm_pidfd,dgram_abstract)250*ec80f488SAlexander Mikhalitsyn FIXTURE_VARIANT_ADD(scm_pidfd, dgram_abstract)
251*ec80f488SAlexander Mikhalitsyn {
252*ec80f488SAlexander Mikhalitsyn .type = SOCK_DGRAM,
253*ec80f488SAlexander Mikhalitsyn .abstract = 1,
254*ec80f488SAlexander Mikhalitsyn };
255*ec80f488SAlexander Mikhalitsyn
FIXTURE_SETUP(scm_pidfd)256*ec80f488SAlexander Mikhalitsyn FIXTURE_SETUP(scm_pidfd)
257*ec80f488SAlexander Mikhalitsyn {
258*ec80f488SAlexander Mikhalitsyn self->client_addr = mmap(NULL, sizeof(*self->client_addr), PROT_READ | PROT_WRITE,
259*ec80f488SAlexander Mikhalitsyn MAP_SHARED | MAP_ANONYMOUS, -1, 0);
260*ec80f488SAlexander Mikhalitsyn ASSERT_NE(MAP_FAILED, self->client_addr);
261*ec80f488SAlexander Mikhalitsyn }
262*ec80f488SAlexander Mikhalitsyn
FIXTURE_TEARDOWN(scm_pidfd)263*ec80f488SAlexander Mikhalitsyn FIXTURE_TEARDOWN(scm_pidfd)
264*ec80f488SAlexander Mikhalitsyn {
265*ec80f488SAlexander Mikhalitsyn close(self->server);
266*ec80f488SAlexander Mikhalitsyn
267*ec80f488SAlexander Mikhalitsyn kill(self->client_pid, SIGKILL);
268*ec80f488SAlexander Mikhalitsyn waitpid(self->client_pid, NULL, 0);
269*ec80f488SAlexander Mikhalitsyn
270*ec80f488SAlexander Mikhalitsyn if (!variant->abstract) {
271*ec80f488SAlexander Mikhalitsyn unlink(self->server_addr.sock_name);
272*ec80f488SAlexander Mikhalitsyn unlink(self->client_addr->sock_name);
273*ec80f488SAlexander Mikhalitsyn }
274*ec80f488SAlexander Mikhalitsyn }
275*ec80f488SAlexander Mikhalitsyn
fill_sockaddr(struct sock_addr * addr,bool abstract)276*ec80f488SAlexander Mikhalitsyn static void fill_sockaddr(struct sock_addr *addr, bool abstract)
277*ec80f488SAlexander Mikhalitsyn {
278*ec80f488SAlexander Mikhalitsyn char *sun_path_buf = (char *)&addr->listen_addr.sun_path;
279*ec80f488SAlexander Mikhalitsyn
280*ec80f488SAlexander Mikhalitsyn addr->listen_addr.sun_family = AF_UNIX;
281*ec80f488SAlexander Mikhalitsyn addr->addrlen = offsetof(struct sockaddr_un, sun_path);
282*ec80f488SAlexander Mikhalitsyn snprintf(addr->sock_name, sizeof(addr->sock_name), "scm_pidfd_%d", getpid());
283*ec80f488SAlexander Mikhalitsyn addr->addrlen += strlen(addr->sock_name);
284*ec80f488SAlexander Mikhalitsyn if (abstract) {
285*ec80f488SAlexander Mikhalitsyn *sun_path_buf = '\0';
286*ec80f488SAlexander Mikhalitsyn addr->addrlen++;
287*ec80f488SAlexander Mikhalitsyn sun_path_buf++;
288*ec80f488SAlexander Mikhalitsyn } else {
289*ec80f488SAlexander Mikhalitsyn unlink(addr->sock_name);
290*ec80f488SAlexander Mikhalitsyn }
291*ec80f488SAlexander Mikhalitsyn memcpy(sun_path_buf, addr->sock_name, strlen(addr->sock_name));
292*ec80f488SAlexander Mikhalitsyn }
293*ec80f488SAlexander Mikhalitsyn
client(FIXTURE_DATA (scm_pidfd)* self,const FIXTURE_VARIANT (scm_pidfd)* variant)294*ec80f488SAlexander Mikhalitsyn static void client(FIXTURE_DATA(scm_pidfd) *self,
295*ec80f488SAlexander Mikhalitsyn const FIXTURE_VARIANT(scm_pidfd) *variant)
296*ec80f488SAlexander Mikhalitsyn {
297*ec80f488SAlexander Mikhalitsyn int cfd;
298*ec80f488SAlexander Mikhalitsyn socklen_t len;
299*ec80f488SAlexander Mikhalitsyn struct ucred peer_cred;
300*ec80f488SAlexander Mikhalitsyn int peer_pidfd;
301*ec80f488SAlexander Mikhalitsyn pid_t peer_pid;
302*ec80f488SAlexander Mikhalitsyn int on = 0;
303*ec80f488SAlexander Mikhalitsyn
304*ec80f488SAlexander Mikhalitsyn cfd = socket(AF_UNIX, variant->type, 0);
305*ec80f488SAlexander Mikhalitsyn if (cfd < 0) {
306*ec80f488SAlexander Mikhalitsyn log_err("socket");
307*ec80f488SAlexander Mikhalitsyn child_die();
308*ec80f488SAlexander Mikhalitsyn }
309*ec80f488SAlexander Mikhalitsyn
310*ec80f488SAlexander Mikhalitsyn if (variant->type == SOCK_DGRAM) {
311*ec80f488SAlexander Mikhalitsyn fill_sockaddr(self->client_addr, variant->abstract);
312*ec80f488SAlexander Mikhalitsyn
313*ec80f488SAlexander Mikhalitsyn if (bind(cfd, (struct sockaddr *)&self->client_addr->listen_addr, self->client_addr->addrlen)) {
314*ec80f488SAlexander Mikhalitsyn log_err("bind");
315*ec80f488SAlexander Mikhalitsyn child_die();
316*ec80f488SAlexander Mikhalitsyn }
317*ec80f488SAlexander Mikhalitsyn }
318*ec80f488SAlexander Mikhalitsyn
319*ec80f488SAlexander Mikhalitsyn if (connect(cfd, (struct sockaddr *)&self->server_addr.listen_addr,
320*ec80f488SAlexander Mikhalitsyn self->server_addr.addrlen) != 0) {
321*ec80f488SAlexander Mikhalitsyn log_err("connect");
322*ec80f488SAlexander Mikhalitsyn child_die();
323*ec80f488SAlexander Mikhalitsyn }
324*ec80f488SAlexander Mikhalitsyn
325*ec80f488SAlexander Mikhalitsyn on = 1;
326*ec80f488SAlexander Mikhalitsyn if (setsockopt(cfd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
327*ec80f488SAlexander Mikhalitsyn log_err("Failed to set SO_PASSCRED");
328*ec80f488SAlexander Mikhalitsyn child_die();
329*ec80f488SAlexander Mikhalitsyn }
330*ec80f488SAlexander Mikhalitsyn
331*ec80f488SAlexander Mikhalitsyn if (setsockopt(cfd, SOL_SOCKET, SO_PASSPIDFD, &on, sizeof(on))) {
332*ec80f488SAlexander Mikhalitsyn log_err("Failed to set SO_PASSPIDFD");
333*ec80f488SAlexander Mikhalitsyn child_die();
334*ec80f488SAlexander Mikhalitsyn }
335*ec80f488SAlexander Mikhalitsyn
336*ec80f488SAlexander Mikhalitsyn close(self->startup_pipe[1]);
337*ec80f488SAlexander Mikhalitsyn
338*ec80f488SAlexander Mikhalitsyn if (cmsg_check(cfd)) {
339*ec80f488SAlexander Mikhalitsyn log_err("cmsg_check failed");
340*ec80f488SAlexander Mikhalitsyn child_die();
341*ec80f488SAlexander Mikhalitsyn }
342*ec80f488SAlexander Mikhalitsyn
343*ec80f488SAlexander Mikhalitsyn /* skip further for SOCK_DGRAM as it's not applicable */
344*ec80f488SAlexander Mikhalitsyn if (variant->type == SOCK_DGRAM)
345*ec80f488SAlexander Mikhalitsyn return;
346*ec80f488SAlexander Mikhalitsyn
347*ec80f488SAlexander Mikhalitsyn len = sizeof(peer_cred);
348*ec80f488SAlexander Mikhalitsyn if (getsockopt(cfd, SOL_SOCKET, SO_PEERCRED, &peer_cred, &len)) {
349*ec80f488SAlexander Mikhalitsyn log_err("Failed to get SO_PEERCRED");
350*ec80f488SAlexander Mikhalitsyn child_die();
351*ec80f488SAlexander Mikhalitsyn }
352*ec80f488SAlexander Mikhalitsyn
353*ec80f488SAlexander Mikhalitsyn len = sizeof(peer_pidfd);
354*ec80f488SAlexander Mikhalitsyn if (getsockopt(cfd, SOL_SOCKET, SO_PEERPIDFD, &peer_pidfd, &len)) {
355*ec80f488SAlexander Mikhalitsyn log_err("Failed to get SO_PEERPIDFD");
356*ec80f488SAlexander Mikhalitsyn child_die();
357*ec80f488SAlexander Mikhalitsyn }
358*ec80f488SAlexander Mikhalitsyn
359*ec80f488SAlexander Mikhalitsyn /* pid from SO_PEERCRED should point to the parent process PID */
360*ec80f488SAlexander Mikhalitsyn if (peer_cred.pid != getppid()) {
361*ec80f488SAlexander Mikhalitsyn log_err("peer_cred.pid != getppid(): %d != %d", peer_cred.pid, getppid());
362*ec80f488SAlexander Mikhalitsyn child_die();
363*ec80f488SAlexander Mikhalitsyn }
364*ec80f488SAlexander Mikhalitsyn
365*ec80f488SAlexander Mikhalitsyn peer_pid = get_pid_from_fdinfo_file(peer_pidfd,
366*ec80f488SAlexander Mikhalitsyn "Pid:", sizeof("Pid:") - 1);
367*ec80f488SAlexander Mikhalitsyn if (peer_pid != peer_cred.pid) {
368*ec80f488SAlexander Mikhalitsyn log_err("peer_pid != peer_cred.pid: %d != %d", peer_pid, peer_cred.pid);
369*ec80f488SAlexander Mikhalitsyn child_die();
370*ec80f488SAlexander Mikhalitsyn }
371*ec80f488SAlexander Mikhalitsyn }
372*ec80f488SAlexander Mikhalitsyn
TEST_F(scm_pidfd,test)373*ec80f488SAlexander Mikhalitsyn TEST_F(scm_pidfd, test)
374*ec80f488SAlexander Mikhalitsyn {
375*ec80f488SAlexander Mikhalitsyn int err;
376*ec80f488SAlexander Mikhalitsyn int pfd;
377*ec80f488SAlexander Mikhalitsyn int child_status = 0;
378*ec80f488SAlexander Mikhalitsyn
379*ec80f488SAlexander Mikhalitsyn self->server = socket(AF_UNIX, variant->type, 0);
380*ec80f488SAlexander Mikhalitsyn ASSERT_NE(-1, self->server);
381*ec80f488SAlexander Mikhalitsyn
382*ec80f488SAlexander Mikhalitsyn fill_sockaddr(&self->server_addr, variant->abstract);
383*ec80f488SAlexander Mikhalitsyn
384*ec80f488SAlexander Mikhalitsyn err = bind(self->server, (struct sockaddr *)&self->server_addr.listen_addr, self->server_addr.addrlen);
385*ec80f488SAlexander Mikhalitsyn ASSERT_EQ(0, err);
386*ec80f488SAlexander Mikhalitsyn
387*ec80f488SAlexander Mikhalitsyn if (variant->type == SOCK_STREAM) {
388*ec80f488SAlexander Mikhalitsyn err = listen(self->server, 1);
389*ec80f488SAlexander Mikhalitsyn ASSERT_EQ(0, err);
390*ec80f488SAlexander Mikhalitsyn }
391*ec80f488SAlexander Mikhalitsyn
392*ec80f488SAlexander Mikhalitsyn err = pipe(self->startup_pipe);
393*ec80f488SAlexander Mikhalitsyn ASSERT_NE(-1, err);
394*ec80f488SAlexander Mikhalitsyn
395*ec80f488SAlexander Mikhalitsyn self->client_pid = fork();
396*ec80f488SAlexander Mikhalitsyn ASSERT_NE(-1, self->client_pid);
397*ec80f488SAlexander Mikhalitsyn if (self->client_pid == 0) {
398*ec80f488SAlexander Mikhalitsyn close(self->server);
399*ec80f488SAlexander Mikhalitsyn close(self->startup_pipe[0]);
400*ec80f488SAlexander Mikhalitsyn client(self, variant);
401*ec80f488SAlexander Mikhalitsyn exit(0);
402*ec80f488SAlexander Mikhalitsyn }
403*ec80f488SAlexander Mikhalitsyn close(self->startup_pipe[1]);
404*ec80f488SAlexander Mikhalitsyn
405*ec80f488SAlexander Mikhalitsyn if (variant->type == SOCK_STREAM) {
406*ec80f488SAlexander Mikhalitsyn pfd = accept(self->server, NULL, NULL);
407*ec80f488SAlexander Mikhalitsyn ASSERT_NE(-1, pfd);
408*ec80f488SAlexander Mikhalitsyn } else {
409*ec80f488SAlexander Mikhalitsyn pfd = self->server;
410*ec80f488SAlexander Mikhalitsyn }
411*ec80f488SAlexander Mikhalitsyn
412*ec80f488SAlexander Mikhalitsyn /* wait until the child arrives at checkpoint */
413*ec80f488SAlexander Mikhalitsyn read(self->startup_pipe[0], &err, sizeof(int));
414*ec80f488SAlexander Mikhalitsyn close(self->startup_pipe[0]);
415*ec80f488SAlexander Mikhalitsyn
416*ec80f488SAlexander Mikhalitsyn if (variant->type == SOCK_DGRAM) {
417*ec80f488SAlexander Mikhalitsyn err = sendto(pfd, "x", sizeof(char), 0, (struct sockaddr *)&self->client_addr->listen_addr, self->client_addr->addrlen);
418*ec80f488SAlexander Mikhalitsyn ASSERT_NE(-1, err);
419*ec80f488SAlexander Mikhalitsyn } else {
420*ec80f488SAlexander Mikhalitsyn err = send(pfd, "x", sizeof(char), 0);
421*ec80f488SAlexander Mikhalitsyn ASSERT_NE(-1, err);
422*ec80f488SAlexander Mikhalitsyn }
423*ec80f488SAlexander Mikhalitsyn
424*ec80f488SAlexander Mikhalitsyn close(pfd);
425*ec80f488SAlexander Mikhalitsyn waitpid(self->client_pid, &child_status, 0);
426*ec80f488SAlexander Mikhalitsyn ASSERT_EQ(0, WIFEXITED(child_status) ? WEXITSTATUS(child_status) : 1);
427*ec80f488SAlexander Mikhalitsyn }
428*ec80f488SAlexander Mikhalitsyn
429*ec80f488SAlexander Mikhalitsyn TEST_HARNESS_MAIN
430