xref: /linux/tools/testing/selftests/net/af_unix/scm_pidfd.c (revision a6656aefd328d544420ecec121fc898b7f067827)
1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 #define _GNU_SOURCE
3 #include <error.h>
4 #include <limits.h>
5 #include <stddef.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <sys/socket.h>
9 #include <linux/socket.h>
10 #include <unistd.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <pthread.h>
14 #include <sys/un.h>
15 #include <sys/signal.h>
16 #include <sys/types.h>
17 #include <sys/wait.h>
18 
19 #include "../../pidfd/pidfd.h"
20 #include "kselftest_harness.h"
21 
22 #define clean_errno() (errno == 0 ? "None" : strerror(errno))
23 #define log_err(MSG, ...)                                                   \
24 	fprintf(stderr, "(%s:%d: errno: %s) " MSG "\n", __FILE__, __LINE__, \
25 		clean_errno(), ##__VA_ARGS__)
26 
27 #ifndef SCM_PIDFD
28 #define SCM_PIDFD 0x04
29 #endif
30 
31 #ifndef SCM_PIDFD_THREAD
32 #define SCM_PIDFD_THREAD 0x05
33 #endif
34 
35 #ifndef SO_PASSPIDFD_THREAD
36 #define SO_PASSPIDFD_THREAD 86
37 #endif
38 
39 #ifndef SO_PEERPIDFD_THREAD
40 #define SO_PEERPIDFD_THREAD 87
41 #endif
42 
43 #define CHILD_EXIT_CODE_OK 123
44 
child_die()45 static void child_die()
46 {
47 	exit(1);
48 }
49 
safe_int(const char * numstr,int * converted)50 static int safe_int(const char *numstr, int *converted)
51 {
52 	char *err = NULL;
53 	long sli;
54 
55 	errno = 0;
56 	sli = strtol(numstr, &err, 0);
57 	if (errno == ERANGE && (sli == LONG_MAX || sli == LONG_MIN))
58 		return -ERANGE;
59 
60 	if (errno != 0 && sli == 0)
61 		return -EINVAL;
62 
63 	if (err == numstr || *err != '\0')
64 		return -EINVAL;
65 
66 	if (sli > INT_MAX || sli < INT_MIN)
67 		return -ERANGE;
68 
69 	*converted = (int)sli;
70 	return 0;
71 }
72 
char_left_gc(const char * buffer,size_t len)73 static int char_left_gc(const char *buffer, size_t len)
74 {
75 	size_t i;
76 
77 	for (i = 0; i < len; i++) {
78 		if (buffer[i] == ' ' || buffer[i] == '\t')
79 			continue;
80 
81 		return i;
82 	}
83 
84 	return 0;
85 }
86 
char_right_gc(const char * buffer,size_t len)87 static int char_right_gc(const char *buffer, size_t len)
88 {
89 	int i;
90 
91 	for (i = len - 1; i >= 0; i--) {
92 		if (buffer[i] == ' ' || buffer[i] == '\t' ||
93 		    buffer[i] == '\n' || buffer[i] == '\0')
94 			continue;
95 
96 		return i + 1;
97 	}
98 
99 	return 0;
100 }
101 
trim_whitespace_in_place(char * buffer)102 static char *trim_whitespace_in_place(char *buffer)
103 {
104 	buffer += char_left_gc(buffer, strlen(buffer));
105 	buffer[char_right_gc(buffer, strlen(buffer))] = '\0';
106 	return buffer;
107 }
108 
109 /* borrowed (with all helpers) from pidfd/pidfd_open_test.c */
get_pid_from_fdinfo_file(int pidfd,const char * key,size_t keylen)110 static pid_t get_pid_from_fdinfo_file(int pidfd, const char *key, size_t keylen)
111 {
112 	int ret;
113 	char path[512];
114 	FILE *f;
115 	size_t n = 0;
116 	pid_t result = -1;
117 	char *line = NULL;
118 
119 	snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", pidfd);
120 
121 	f = fopen(path, "re");
122 	if (!f)
123 		return -1;
124 
125 	while (getline(&line, &n, f) != -1) {
126 		char *numstr;
127 
128 		if (strncmp(line, key, keylen))
129 			continue;
130 
131 		numstr = trim_whitespace_in_place(line + 4);
132 		ret = safe_int(numstr, &result);
133 		if (ret < 0)
134 			goto out;
135 
136 		break;
137 	}
138 
139 out:
140 	free(line);
141 	fclose(f);
142 	return result;
143 }
144 
145 struct cmsg_data {
146 	struct ucred *ucred;
147 	int *pidfd;
148 };
149 
parse_cmsg(struct msghdr * msg,struct cmsg_data * res)150 static int parse_cmsg(struct msghdr *msg, struct cmsg_data *res)
151 {
152 	struct cmsghdr *cmsg;
153 
154 	if (msg->msg_flags & (MSG_TRUNC | MSG_CTRUNC)) {
155 		log_err("recvmsg: truncated");
156 		return 1;
157 	}
158 
159 	for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
160 	     cmsg = CMSG_NXTHDR(msg, cmsg)) {
161 		if (cmsg->cmsg_level == SOL_SOCKET &&
162 		    cmsg->cmsg_type == SCM_PIDFD) {
163 			if (cmsg->cmsg_len < sizeof(*res->pidfd)) {
164 				log_err("CMSG parse: SCM_PIDFD wrong len");
165 				return 1;
166 			}
167 
168 			res->pidfd = (void *)CMSG_DATA(cmsg);
169 		}
170 
171 		if (cmsg->cmsg_level == SOL_SOCKET &&
172 		    cmsg->cmsg_type == SCM_CREDENTIALS) {
173 			if (cmsg->cmsg_len < sizeof(*res->ucred)) {
174 				log_err("CMSG parse: SCM_CREDENTIALS wrong len");
175 				return 1;
176 			}
177 
178 			res->ucred = (void *)CMSG_DATA(cmsg);
179 		}
180 	}
181 
182 	if (!res->pidfd) {
183 		log_err("CMSG parse: SCM_PIDFD not found");
184 		return 1;
185 	}
186 
187 	if (!res->ucred) {
188 		log_err("CMSG parse: SCM_CREDENTIALS not found");
189 		return 1;
190 	}
191 
192 	return 0;
193 }
194 
cmsg_check(int fd)195 static int cmsg_check(int fd)
196 {
197 	struct msghdr msg = { 0 };
198 	struct cmsg_data res;
199 	struct iovec iov;
200 	int data = 0;
201 	char control[CMSG_SPACE(sizeof(struct ucred)) +
202 		     CMSG_SPACE(sizeof(int))] = { 0 };
203 	pid_t parent_pid;
204 	int err;
205 
206 	iov.iov_base = &data;
207 	iov.iov_len = sizeof(data);
208 
209 	msg.msg_iov = &iov;
210 	msg.msg_iovlen = 1;
211 	msg.msg_control = control;
212 	msg.msg_controllen = sizeof(control);
213 
214 	err = recvmsg(fd, &msg, 0);
215 	if (err < 0) {
216 		log_err("recvmsg");
217 		return 1;
218 	}
219 
220 	if (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) {
221 		log_err("recvmsg: truncated");
222 		return 1;
223 	}
224 
225 	/* send(pfd, "x", sizeof(char), 0) */
226 	if (data != 'x') {
227 		log_err("recvmsg: data corruption");
228 		return 1;
229 	}
230 
231 	if (parse_cmsg(&msg, &res)) {
232 		log_err("CMSG parse: parse_cmsg() failed");
233 		return 1;
234 	}
235 
236 	/* pidfd from SCM_PIDFD should point to the parent process PID */
237 	parent_pid =
238 		get_pid_from_fdinfo_file(*res.pidfd, "Pid:", sizeof("Pid:") - 1);
239 	if (parent_pid != getppid()) {
240 		log_err("wrong SCM_PIDFD %d != %d", parent_pid, getppid());
241 		close(*res.pidfd);
242 		return 1;
243 	}
244 
245 	close(*res.pidfd);
246 	return 0;
247 }
248 
cmsg_check_dead(int fd,int expected_pid)249 static int cmsg_check_dead(int fd, int expected_pid)
250 {
251 	int err;
252 	struct msghdr msg = { 0 };
253 	struct cmsg_data res;
254 	struct iovec iov;
255 	int data = 0;
256 	char control[CMSG_SPACE(sizeof(struct ucred)) +
257 		     CMSG_SPACE(sizeof(int))] = { 0 };
258 	struct pidfd_info info = {
259 		.mask = PIDFD_INFO_EXIT,
260 	};
261 
262 	iov.iov_base = &data;
263 	iov.iov_len = sizeof(data);
264 
265 	msg.msg_iov = &iov;
266 	msg.msg_iovlen = 1;
267 	msg.msg_control = control;
268 	msg.msg_controllen = sizeof(control);
269 
270 	err = recvmsg(fd, &msg, 0);
271 	if (err < 0) {
272 		log_err("recvmsg");
273 		return 1;
274 	}
275 
276 	if (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) {
277 		log_err("recvmsg: truncated");
278 		return 1;
279 	}
280 
281 	/* send(cfd, "y", sizeof(char), 0) */
282 	if (data != 'y') {
283 		log_err("recvmsg: data corruption");
284 		return 1;
285 	}
286 
287 	if (parse_cmsg(&msg, &res)) {
288 		log_err("CMSG parse: parse_cmsg() failed");
289 		return 1;
290 	}
291 
292 	/*
293 	 * pidfd from SCM_PIDFD should point to the client_pid.
294 	 * Let's read exit information and check if it's what
295 	 * we expect to see.
296 	 */
297 	if (ioctl(*res.pidfd, PIDFD_GET_INFO, &info)) {
298 		log_err("%s: ioctl(PIDFD_GET_INFO) failed", __func__);
299 		close(*res.pidfd);
300 		return 1;
301 	}
302 
303 	if (!(info.mask & PIDFD_INFO_EXIT)) {
304 		log_err("%s: No exit information from ioctl(PIDFD_GET_INFO)", __func__);
305 		close(*res.pidfd);
306 		return 1;
307 	}
308 
309 	err = WIFEXITED(info.exit_code) ? WEXITSTATUS(info.exit_code) : 1;
310 	if (err != CHILD_EXIT_CODE_OK) {
311 		log_err("%s: wrong exit_code %d != %d", __func__, err, CHILD_EXIT_CODE_OK);
312 		close(*res.pidfd);
313 		return 1;
314 	}
315 
316 	close(*res.pidfd);
317 	return 0;
318 }
319 
320 struct sock_addr {
321 	char sock_name[32];
322 	struct sockaddr_un listen_addr;
323 	socklen_t addrlen;
324 };
325 
FIXTURE(scm_pidfd)326 FIXTURE(scm_pidfd)
327 {
328 	int server;
329 	pid_t client_pid;
330 	int startup_pipe[2];
331 	struct sock_addr server_addr;
332 	struct sock_addr *client_addr;
333 };
334 
FIXTURE_VARIANT(scm_pidfd)335 FIXTURE_VARIANT(scm_pidfd)
336 {
337 	int type;
338 	bool abstract;
339 };
340 
FIXTURE_VARIANT_ADD(scm_pidfd,stream_pathname)341 FIXTURE_VARIANT_ADD(scm_pidfd, stream_pathname)
342 {
343 	.type = SOCK_STREAM,
344 	.abstract = 0,
345 };
346 
FIXTURE_VARIANT_ADD(scm_pidfd,stream_abstract)347 FIXTURE_VARIANT_ADD(scm_pidfd, stream_abstract)
348 {
349 	.type = SOCK_STREAM,
350 	.abstract = 1,
351 };
352 
FIXTURE_VARIANT_ADD(scm_pidfd,dgram_pathname)353 FIXTURE_VARIANT_ADD(scm_pidfd, dgram_pathname)
354 {
355 	.type = SOCK_DGRAM,
356 	.abstract = 0,
357 };
358 
FIXTURE_VARIANT_ADD(scm_pidfd,dgram_abstract)359 FIXTURE_VARIANT_ADD(scm_pidfd, dgram_abstract)
360 {
361 	.type = SOCK_DGRAM,
362 	.abstract = 1,
363 };
364 
FIXTURE_SETUP(scm_pidfd)365 FIXTURE_SETUP(scm_pidfd)
366 {
367 	self->client_addr = mmap(NULL, sizeof(*self->client_addr), PROT_READ | PROT_WRITE,
368 				 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
369 	ASSERT_NE(MAP_FAILED, self->client_addr);
370 }
371 
FIXTURE_TEARDOWN(scm_pidfd)372 FIXTURE_TEARDOWN(scm_pidfd)
373 {
374 	close(self->server);
375 
376 	kill(self->client_pid, SIGKILL);
377 	waitpid(self->client_pid, NULL, 0);
378 
379 	if (!variant->abstract) {
380 		unlink(self->server_addr.sock_name);
381 		unlink(self->client_addr->sock_name);
382 	}
383 }
384 
fill_sockaddr(struct sock_addr * addr,bool abstract)385 static void fill_sockaddr(struct sock_addr *addr, bool abstract)
386 {
387 	char *sun_path_buf = (char *)&addr->listen_addr.sun_path;
388 
389 	addr->listen_addr.sun_family = AF_UNIX;
390 	addr->addrlen = offsetof(struct sockaddr_un, sun_path);
391 	snprintf(addr->sock_name, sizeof(addr->sock_name), "scm_pidfd_%d", getpid());
392 	addr->addrlen += strlen(addr->sock_name);
393 	if (abstract) {
394 		*sun_path_buf = '\0';
395 		addr->addrlen++;
396 		sun_path_buf++;
397 	} else {
398 		unlink(addr->sock_name);
399 	}
400 	memcpy(sun_path_buf, addr->sock_name, strlen(addr->sock_name));
401 }
402 
sk_enable_cred_pass(int sk)403 static int sk_enable_cred_pass(int sk)
404 {
405 	int on = 0;
406 
407 	on = 1;
408 	if (setsockopt(sk, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on))) {
409 		log_err("Failed to set SO_PASSCRED");
410 		return 1;
411 	}
412 
413 	if (setsockopt(sk, SOL_SOCKET, SO_PASSPIDFD, &on, sizeof(on))) {
414 		log_err("Failed to set SO_PASSPIDFD");
415 		return 1;
416 	}
417 
418 	return 0;
419 }
420 
client(FIXTURE_DATA (scm_pidfd)* self,const FIXTURE_VARIANT (scm_pidfd)* variant)421 static void client(FIXTURE_DATA(scm_pidfd) *self,
422 		   const FIXTURE_VARIANT(scm_pidfd) *variant)
423 {
424 	int cfd;
425 	socklen_t len;
426 	struct ucred peer_cred;
427 	int peer_pidfd;
428 	pid_t peer_pid;
429 
430 	cfd = socket(AF_UNIX, variant->type, 0);
431 	if (cfd < 0) {
432 		log_err("socket");
433 		child_die();
434 	}
435 
436 	if (variant->type == SOCK_DGRAM) {
437 		fill_sockaddr(self->client_addr, variant->abstract);
438 
439 		if (bind(cfd, (struct sockaddr *)&self->client_addr->listen_addr, self->client_addr->addrlen)) {
440 			log_err("bind");
441 			child_die();
442 		}
443 	}
444 
445 	if (connect(cfd, (struct sockaddr *)&self->server_addr.listen_addr,
446 		    self->server_addr.addrlen) != 0) {
447 		log_err("connect");
448 		child_die();
449 	}
450 
451 	if (sk_enable_cred_pass(cfd)) {
452 		log_err("sk_enable_cred_pass() failed");
453 		child_die();
454 	}
455 
456 	close(self->startup_pipe[1]);
457 
458 	if (cmsg_check(cfd)) {
459 		log_err("cmsg_check failed");
460 		child_die();
461 	}
462 
463 	/* send something to the parent so it can receive SCM_PIDFD too and validate it */
464 	if (send(cfd, "y", sizeof(char), 0) == -1) {
465 		log_err("Failed to send(cfd, \"y\", sizeof(char), 0)");
466 		child_die();
467 	}
468 
469 	/* skip further for SOCK_DGRAM as it's not applicable */
470 	if (variant->type == SOCK_DGRAM)
471 		return;
472 
473 	len = sizeof(peer_cred);
474 	if (getsockopt(cfd, SOL_SOCKET, SO_PEERCRED, &peer_cred, &len)) {
475 		log_err("Failed to get SO_PEERCRED");
476 		child_die();
477 	}
478 
479 	len = sizeof(peer_pidfd);
480 	if (getsockopt(cfd, SOL_SOCKET, SO_PEERPIDFD, &peer_pidfd, &len)) {
481 		log_err("Failed to get SO_PEERPIDFD");
482 		child_die();
483 	}
484 
485 	/* pid from SO_PEERCRED should point to the parent process PID */
486 	if (peer_cred.pid != getppid()) {
487 		log_err("peer_cred.pid != getppid(): %d != %d", peer_cred.pid, getppid());
488 		child_die();
489 	}
490 
491 	peer_pid = get_pid_from_fdinfo_file(peer_pidfd,
492 					    "Pid:", sizeof("Pid:") - 1);
493 	if (peer_pid != peer_cred.pid) {
494 		log_err("peer_pid != peer_cred.pid: %d != %d", peer_pid, peer_cred.pid);
495 		child_die();
496 	}
497 }
498 
TEST_F(scm_pidfd,test)499 TEST_F(scm_pidfd, test)
500 {
501 	int err;
502 	int pfd;
503 	int child_status = 0;
504 
505 	self->server = socket(AF_UNIX, variant->type, 0);
506 	ASSERT_NE(-1, self->server);
507 
508 	fill_sockaddr(&self->server_addr, variant->abstract);
509 
510 	err = bind(self->server, (struct sockaddr *)&self->server_addr.listen_addr, self->server_addr.addrlen);
511 	ASSERT_EQ(0, err);
512 
513 	if (variant->type == SOCK_STREAM) {
514 		err = listen(self->server, 1);
515 		ASSERT_EQ(0, err);
516 	}
517 
518 	err = pipe(self->startup_pipe);
519 	ASSERT_NE(-1, err);
520 
521 	self->client_pid = fork();
522 	ASSERT_NE(-1, self->client_pid);
523 	if (self->client_pid == 0) {
524 		close(self->server);
525 		close(self->startup_pipe[0]);
526 		client(self, variant);
527 
528 		/*
529 		 * It's a bit unusual, but in case of success we return non-zero
530 		 * exit code (CHILD_EXIT_CODE_OK) and then we expect to read it
531 		 * from ioctl(PIDFD_GET_INFO) in cmsg_check_dead().
532 		 */
533 		exit(CHILD_EXIT_CODE_OK);
534 	}
535 	close(self->startup_pipe[1]);
536 
537 	if (variant->type == SOCK_STREAM) {
538 		pfd = accept(self->server, NULL, NULL);
539 		ASSERT_NE(-1, pfd);
540 	} else {
541 		pfd = self->server;
542 	}
543 
544 	/* wait until the child arrives at checkpoint */
545 	read(self->startup_pipe[0], &err, sizeof(int));
546 	close(self->startup_pipe[0]);
547 
548 	if (variant->type == SOCK_DGRAM) {
549 		err = sendto(pfd, "x", sizeof(char), 0, (struct sockaddr *)&self->client_addr->listen_addr, self->client_addr->addrlen);
550 		ASSERT_NE(-1, err);
551 	} else {
552 		err = send(pfd, "x", sizeof(char), 0);
553 		ASSERT_NE(-1, err);
554 	}
555 
556 	waitpid(self->client_pid, &child_status, 0);
557 	/* see comment before exit(CHILD_EXIT_CODE_OK) */
558 	ASSERT_EQ(CHILD_EXIT_CODE_OK, WIFEXITED(child_status) ? WEXITSTATUS(child_status) : 1);
559 
560 	err = sk_enable_cred_pass(pfd);
561 	ASSERT_EQ(0, err);
562 
563 	err = cmsg_check_dead(pfd, self->client_pid);
564 	ASSERT_EQ(0, err);
565 
566 	close(pfd);
567 }
568 
569 struct thread_ids {
570 	pid_t pid;
571 	pid_t tid;
572 };
573 
574 #define MAX_WRITERS 2
575 
576 /* Used by writers to signal they've written, so we can sequence multiple writers */
577 static int seq_pipe[2];
578 
send_ids_thread(void * arg)579 static void *send_ids_thread(void *arg)
580 {
581 	int fd = *(int *)arg;
582 	struct thread_ids ids = {
583 		.pid = getpid(),
584 		.tid = gettid(),
585 	};
586 	char sync;
587 
588 	if (send(fd, &ids, sizeof(ids), 0) != sizeof(ids))
589 		return (void *)1;
590 
591 	/* let the client start the next writer, so the queue order is known */
592 	if (write(seq_pipe[1], "1", 1) != 1)
593 		return (void *)1;
594 
595 	/* stay alive until the receiver has looked at our pidfd */
596 	if (read(fd, &sync, 1) != 1)
597 		return (void *)1;
598 
599 	return NULL;
600 }
601 
send_ids_creds_thread(void * arg)602 static void *send_ids_creds_thread(void *arg)
603 {
604 	int fd = *(int *)arg;
605 	struct thread_ids ids = {
606 		.pid = getpid(),
607 		.tid = gettid(),
608 	};
609 	struct ucred ucred = {
610 		.pid = getpid(),
611 		.uid = getuid(),
612 		.gid = getgid(),
613 	};
614 	char control[CMSG_SPACE(sizeof(ucred))] = { 0 };
615 	struct iovec iov;
616 	struct msghdr msg = { 0 };
617 	struct cmsghdr *cmsg;
618 	char sync;
619 
620 	iov.iov_base = &ids;
621 	iov.iov_len = sizeof(ids);
622 
623 	msg.msg_iov = &iov;
624 	msg.msg_iovlen = 1;
625 	msg.msg_control = control;
626 	msg.msg_controllen = sizeof(control);
627 
628 	cmsg = CMSG_FIRSTHDR(&msg);
629 	cmsg->cmsg_level = SOL_SOCKET;
630 	cmsg->cmsg_type = SCM_CREDENTIALS;
631 	cmsg->cmsg_len = CMSG_LEN(sizeof(ucred));
632 	memcpy(CMSG_DATA(cmsg), &ucred, sizeof(ucred));
633 
634 	if (sendmsg(fd, &msg, 0) != sizeof(ids))
635 		return (void *)1;
636 
637 	/* signal we've written our info */
638 	if (write(seq_pipe[1], "1", 1) != 1)
639 		return (void *)1;
640 
641 	/* stay alive until the receiver has looked at our pidfd */
642 	if (read(fd, &sync, 1) != 1)
643 		return (void *)1;
644 
645 	return NULL;
646 }
647 
648 /*
649  * Runs @nwriters copies of @sender, each in its own non-leader thread, one
650  * at a time so the queue order is known, then tells the parent on @ackfd
651  * that everything is queued.
652  */
thread_client(int fd,int syncfd,int ackfd,void * (* sender)(void *),int nwriters)653 static void thread_client(int fd, int syncfd, int ackfd,
654 			  void *(*sender)(void *), int nwriters)
655 {
656 	pthread_t writers[MAX_WRITERS];
657 	void *ret;
658 	char sync;
659 	int i;
660 
661 	/* wait until the receiver enabled the options it wants */
662 	if (read(syncfd, &sync, 1) != 1)
663 		child_die();
664 
665 	for (i = 0; i < nwriters; i++) {
666 		if (pthread_create(&writers[i], NULL, sender, &fd))
667 			child_die();
668 
669 		if (read(seq_pipe[0], &sync, 1) != 1)
670 			child_die();
671 	}
672 
673 	if (write(ackfd, "1", 1) != 1)
674 		child_die();
675 
676 	for (i = 0; i < nwriters; i++)
677 		if (pthread_join(writers[i], &ret) || ret)
678 			child_die();
679 
680 	exit(0);
681 }
682 
683 struct pidfd_msg {
684 	ssize_t len;
685 	struct thread_ids ids;
686 	struct pidfd_info tgid_info;
687 	struct pidfd_info thread_info;
688 	int tgid_flags;
689 	int thread_flags;
690 	bool have_tgid;
691 	bool have_thread;
692 };
693 
get_pidfd_info(int pidfd,struct pidfd_info * info)694 static int get_pidfd_info(int pidfd, struct pidfd_info *info)
695 {
696 	info->mask = PIDFD_INFO_PID;
697 	if (ioctl(pidfd, PIDFD_GET_INFO, info)) {
698 		log_err("ioctl(PIDFD_GET_INFO)");
699 		return -1;
700 	}
701 
702 	return 0;
703 }
704 
705 /* One recvmsg(), reporting how many bytes came back and what the pidfd
706  * cmsgs that came with them say.
707  */
read_pidfd_msg(int fd,struct pidfd_msg * out)708 static int read_pidfd_msg(int fd, struct pidfd_msg *out)
709 {
710 	char control[CMSG_SPACE(sizeof(int)) * 2] = { 0 };
711 	int tgid_pidfd = -1, thread_pidfd = -1;
712 	struct thread_ids buf[2] = { 0 };
713 	struct msghdr msg = { 0 };
714 	struct cmsghdr *cmsg;
715 	struct iovec iov;
716 
717 	iov.iov_base = buf;
718 	iov.iov_len = sizeof(buf);
719 	msg.msg_iov = &iov;
720 	msg.msg_iovlen = 1;
721 	msg.msg_control = control;
722 	msg.msg_controllen = sizeof(control);
723 
724 	out->len = recvmsg(fd, &msg, 0);
725 	if (out->len < 0) {
726 		log_err("recvmsg");
727 		return -1;
728 	}
729 
730 	if (msg.msg_flags & MSG_CTRUNC) {
731 		log_err("recvmsg: control truncated");
732 		return -1;
733 	}
734 
735 	out->ids = buf[0];
736 
737 	for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
738 	     cmsg = CMSG_NXTHDR(&msg, cmsg)) {
739 		if (cmsg->cmsg_level != SOL_SOCKET)
740 			continue;
741 
742 		if (cmsg->cmsg_type == SCM_PIDFD)
743 			memcpy(&tgid_pidfd, CMSG_DATA(cmsg), sizeof(tgid_pidfd));
744 		else if (cmsg->cmsg_type == SCM_PIDFD_THREAD)
745 			memcpy(&thread_pidfd, CMSG_DATA(cmsg), sizeof(thread_pidfd));
746 	}
747 
748 	out->have_tgid = tgid_pidfd >= 0;
749 	out->have_thread = thread_pidfd >= 0;
750 
751 	if (out->have_tgid) {
752 		if (get_pidfd_info(tgid_pidfd, &out->tgid_info))
753 			return -1;
754 		out->tgid_flags = fcntl(tgid_pidfd, F_GETFL);
755 		close(tgid_pidfd);
756 	}
757 
758 	if (out->have_thread) {
759 		if (get_pidfd_info(thread_pidfd, &out->thread_info))
760 			return -1;
761 		out->thread_flags = fcntl(thread_pidfd, F_GETFL);
762 		close(thread_pidfd);
763 	}
764 
765 	return 0;
766 }
767 
768 /*
769  * Runs @nwriters threads of one child process against a SOCK_STREAM pair,
770  * all of them queued before the parent reads. SO_PASSPIDFD is set when
771  * @want_tgid is given, SO_PASSPIDFD_THREAD when @want_thread is. @nread
772  * reads are returned in @out.
773  */
pidfd_flow(void * (* sender)(void *),int nwriters,bool want_tgid,bool want_thread,struct pidfd_msg * out,int nread)774 static int pidfd_flow(void *(*sender)(void *), int nwriters, bool want_tgid,
775 		      bool want_thread, struct pidfd_msg *out, int nread)
776 {
777 	int child_status = 0;
778 	int syncpipe[2];
779 	int ackpipe[2];
780 	int sk[2];
781 	int on = 1;
782 	char sync;
783 	pid_t child;
784 	int i;
785 
786 	if (nwriters > MAX_WRITERS)
787 		return -1;
788 
789 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sk))
790 		return -1;
791 	if (pipe(syncpipe) || pipe(ackpipe) || pipe(seq_pipe))
792 		return -1;
793 
794 	child = fork();
795 	if (child < 0)
796 		return -1;
797 
798 	if (child == 0) {
799 		close(sk[0]);
800 		close(syncpipe[1]);
801 		close(ackpipe[0]);
802 		thread_client(sk[1], syncpipe[0], ackpipe[1], sender, nwriters);
803 	}
804 	close(sk[1]);
805 	close(syncpipe[0]);
806 	close(ackpipe[1]);
807 	close(seq_pipe[0]);
808 	close(seq_pipe[1]);
809 
810 	if (want_tgid &&
811 	    setsockopt(sk[0], SOL_SOCKET, SO_PASSPIDFD, &on, sizeof(on))) {
812 		log_err("Failed to set SO_PASSPIDFD");
813 		return -1;
814 	}
815 
816 	if (want_thread &&
817 	    setsockopt(sk[0], SOL_SOCKET, SO_PASSPIDFD_THREAD, &on, sizeof(on))) {
818 		log_err("Failed to set SO_PASSPIDFD_THREAD");
819 		return -1;
820 	}
821 
822 	/* let the child know the options are set, it can write now */
823 	if (write(syncpipe[1], "1", 1) != 1)
824 		return -1;
825 	close(syncpipe[1]);
826 
827 	/* wait until every writer has queued its message */
828 	if (read(ackpipe[0], &sync, 1) != 1)
829 		return -1;
830 	close(ackpipe[0]);
831 
832 	for (i = 0; i < nread; i++)
833 		if (read_pidfd_msg(sk[0], &out[i]))
834 			return -1;
835 
836 	/* release the writers */
837 	for (i = 0; i < nwriters; i++)
838 		if (write(sk[0], "x", 1) != 1)
839 			return -1;
840 	close(sk[0]);
841 
842 	waitpid(child, &child_status, 0);
843 	if (!WIFEXITED(child_status) || WEXITSTATUS(child_status))
844 		return -1;
845 
846 	return 0;
847 }
848 
sockopt_set(int fd,int optname,int val)849 static int sockopt_set(int fd, int optname, int val)
850 {
851 	return setsockopt(fd, SOL_SOCKET, optname, &val, sizeof(val));
852 }
853 
sockopt_get(int fd,int optname)854 static int sockopt_get(int fd, int optname)
855 {
856 	socklen_t len = sizeof(int);
857 	int val = -1;
858 
859 	if (getsockopt(fd, SOL_SOCKET, optname, &val, &len))
860 		return -1;
861 
862 	return val;
863 }
864 
TEST(scm_pidfd_setsockopt_values)865 TEST(scm_pidfd_setsockopt_values)
866 {
867 	int sk[2];
868 
869 	ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sk));
870 
871 	/* Verify that the options are truly set independently */
872 	ASSERT_EQ(0, sockopt_set(sk[0], SO_PASSPIDFD_THREAD, 1));
873 	ASSERT_EQ(1, sockopt_get(sk[0], SO_PASSPIDFD_THREAD));
874 	ASSERT_EQ(0, sockopt_get(sk[0], SO_PASSPIDFD));
875 
876 	ASSERT_EQ(0, sockopt_set(sk[0], SO_PASSPIDFD, 1));
877 	ASSERT_EQ(1, sockopt_get(sk[0], SO_PASSPIDFD));
878 	ASSERT_EQ(1, sockopt_get(sk[0], SO_PASSPIDFD_THREAD));
879 
880 	/* Verify that the options are truly cleared independently */
881 	ASSERT_EQ(0, sockopt_set(sk[0], SO_PASSPIDFD, 0));
882 	ASSERT_EQ(0, sockopt_get(sk[0], SO_PASSPIDFD));
883 	ASSERT_EQ(1, sockopt_get(sk[0], SO_PASSPIDFD_THREAD));
884 
885 	ASSERT_EQ(0, sockopt_set(sk[0], SO_PASSPIDFD_THREAD, 0));
886 	ASSERT_EQ(0, sockopt_get(sk[0], SO_PASSPIDFD_THREAD));
887 	ASSERT_EQ(0, sockopt_get(sk[0], SO_PASSPIDFD));
888 
889 	close(sk[0]);
890 	close(sk[1]);
891 }
892 
893 /* A receiver that only asked about the process cannot tell the two
894  * threads apart, so their writes are glued into one read.
895  */
TEST(scm_pidfd_stream_glues_threads)896 TEST(scm_pidfd_stream_glues_threads)
897 {
898 	struct pidfd_msg msg[1] = { 0 };
899 
900 	ASSERT_EQ(0, pidfd_flow(send_ids_thread, 2, true, false, msg, 1));
901 	EXPECT_EQ(sizeof(struct thread_ids) * 2, msg[0].len);
902 
903 	EXPECT_TRUE(msg[0].have_tgid);
904 	EXPECT_FALSE(msg[0].have_thread);
905 	EXPECT_EQ(msg[0].ids.pid, msg[0].tgid_info.pid);
906 	EXPECT_EQ(msg[0].ids.pid, msg[0].tgid_info.tgid);
907 }
908 
909 /* A receiver asking for both thread and process pidfd should get a unique
910  * msg for each thread writing
911  */
TEST(scm_pidfd_thread_stream_splits_on_threads)912 TEST(scm_pidfd_thread_stream_splits_on_threads)
913 {
914 	struct pidfd_msg msg[2] = { 0 };
915 	int i;
916 
917 	ASSERT_EQ(0, pidfd_flow(send_ids_thread, 2, true, true, msg, 2));
918 
919 	for (i = 0; i < 2; i++) {
920 		EXPECT_EQ(sizeof(struct thread_ids), msg[i].len);
921 		EXPECT_TRUE(msg[i].have_tgid);
922 		EXPECT_TRUE(msg[i].have_thread);
923 
924 		/* Make sure the info makes sense for the pidfd type */
925 		EXPECT_EQ(msg[i].ids.pid, msg[i].tgid_info.pid);
926 		EXPECT_EQ(msg[i].ids.pid, msg[i].tgid_info.tgid);
927 		EXPECT_EQ(msg[i].ids.tid, msg[i].thread_info.pid);
928 		EXPECT_EQ(msg[i].ids.pid, msg[i].thread_info.tgid);
929 		EXPECT_NE(msg[i].ids.pid, msg[i].ids.tid);
930 	}
931 
932 	/* Make sure we really got unique threads per message */
933 	EXPECT_NE(msg[0].ids.tid, msg[1].ids.tid);
934 	EXPECT_EQ(msg[0].ids.pid, msg[1].ids.pid);
935 	EXPECT_EQ(msg[0].tgid_info.pid, msg[1].tgid_info.pid);
936 	EXPECT_NE(msg[0].thread_info.pid, msg[1].thread_info.pid);
937 }
938 
939 /* Sends from the thread-group leader */
leader_flow(bool want_thread,struct pidfd_msg * out)940 static int leader_flow(bool want_thread, struct pidfd_msg *out)
941 {
942 	struct thread_ids ids = {
943 		.pid = getpid(),
944 		.tid = gettid(),
945 	};
946 	int sk[2];
947 	int on = 1;
948 	int ret;
949 
950 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sk))
951 		return -1;
952 
953 	if (setsockopt(sk[0], SOL_SOCKET, SO_PASSPIDFD, &on, sizeof(on))) {
954 		log_err("Failed to set SO_PASSPIDFD");
955 		return -1;
956 	}
957 
958 	if (want_thread &&
959 	    setsockopt(sk[0], SOL_SOCKET, SO_PASSPIDFD_THREAD, &on, sizeof(on))) {
960 		log_err("Failed to set SO_PASSPIDFD_THREAD");
961 		return -1;
962 	}
963 
964 	if (send(sk[1], &ids, sizeof(ids), 0) != sizeof(ids)) {
965 		log_err("send");
966 		return -1;
967 	}
968 
969 	ret = read_pidfd_msg(sk[0], out);
970 
971 	close(sk[0]);
972 	close(sk[1]);
973 
974 	return ret;
975 }
976 
TEST(scm_pidfd_leader_sender)977 TEST(scm_pidfd_leader_sender)
978 {
979 	struct pidfd_msg msg = { 0 };
980 
981 	ASSERT_EQ(getpid(), gettid());
982 
983 	ASSERT_EQ(0, leader_flow(false, &msg));
984 	ASSERT_TRUE(msg.have_tgid);
985 	EXPECT_FALSE(msg.have_thread);
986 
987 	EXPECT_EQ(getpid(), msg.tgid_info.pid);
988 	EXPECT_EQ(getpid(), msg.tgid_info.tgid);
989 	EXPECT_FALSE(msg.tgid_flags & O_EXCL);
990 }
991 
TEST(scm_pidfd_thread_leader_sender)992 TEST(scm_pidfd_thread_leader_sender)
993 {
994 	struct pidfd_msg msg = { 0 };
995 
996 	ASSERT_EQ(getpid(), gettid());
997 
998 	ASSERT_EQ(0, leader_flow(true, &msg));
999 	ASSERT_TRUE(msg.have_tgid);
1000 	ASSERT_TRUE(msg.have_thread);
1001 
1002 	EXPECT_EQ(getpid(), msg.tgid_info.pid);
1003 	EXPECT_EQ(getpid(), msg.tgid_info.tgid);
1004 	EXPECT_EQ(getpid(), msg.thread_info.pid);
1005 	EXPECT_EQ(getpid(), msg.thread_info.tgid);
1006 
1007 	EXPECT_FALSE(msg.tgid_flags & O_EXCL);
1008 	EXPECT_TRUE(msg.thread_flags & O_EXCL);
1009 }
1010 
TEST(scm_pidfd_thread_and_group)1011 TEST(scm_pidfd_thread_and_group)
1012 {
1013 	struct pidfd_msg msg = { 0 };
1014 
1015 	ASSERT_EQ(0, pidfd_flow(send_ids_thread, 1, true, true, &msg, 1));
1016 	ASSERT_NE(msg.ids.pid, msg.ids.tid);
1017 	ASSERT_TRUE(msg.have_tgid);
1018 	ASSERT_TRUE(msg.have_thread);
1019 
1020 	EXPECT_EQ(msg.ids.pid, msg.tgid_info.pid);
1021 	EXPECT_EQ(msg.ids.pid, msg.tgid_info.tgid);
1022 
1023 	EXPECT_EQ(msg.ids.tid, msg.thread_info.pid);
1024 	EXPECT_EQ(msg.ids.pid, msg.thread_info.tgid);
1025 }
1026 
TEST(scm_pidfd_thread)1027 TEST(scm_pidfd_thread)
1028 {
1029 	struct pidfd_msg msg = { 0 };
1030 
1031 	ASSERT_EQ(0, pidfd_flow(send_ids_thread, 1, false, true, &msg, 1));
1032 	ASSERT_NE(msg.ids.pid, msg.ids.tid);
1033 	ASSERT_TRUE(msg.have_thread);
1034 	EXPECT_FALSE(msg.have_tgid);
1035 	EXPECT_EQ(msg.ids.tid, msg.thread_info.pid);
1036 	EXPECT_EQ(msg.ids.pid, msg.thread_info.tgid);
1037 }
1038 
TEST(scm_pidfd_thread_group)1039 TEST(scm_pidfd_thread_group)
1040 {
1041 	struct pidfd_msg msg = { 0 };
1042 
1043 	ASSERT_EQ(0, pidfd_flow(send_ids_thread, 1, true, false, &msg, 1));
1044 	ASSERT_NE(msg.ids.pid, msg.ids.tid);
1045 	ASSERT_TRUE(msg.have_tgid);
1046 	EXPECT_FALSE(msg.have_thread);
1047 	EXPECT_EQ(msg.ids.pid, msg.tgid_info.pid);
1048 	EXPECT_EQ(msg.ids.pid, msg.tgid_info.tgid);
1049 }
1050 
TEST(scm_pidfd_thread_creds)1051 TEST(scm_pidfd_thread_creds)
1052 {
1053 	struct pidfd_msg msg = { 0 };
1054 
1055 	ASSERT_EQ(0, pidfd_flow(send_ids_creds_thread, 1, true, true, &msg, 1));
1056 	ASSERT_NE(msg.ids.pid, msg.ids.tid);
1057 	ASSERT_TRUE(msg.have_tgid);
1058 	ASSERT_TRUE(msg.have_thread);
1059 	EXPECT_EQ(msg.ids.pid, msg.tgid_info.pid);
1060 	EXPECT_EQ(msg.ids.pid, msg.tgid_info.tgid);
1061 	EXPECT_EQ(msg.ids.tid, msg.thread_info.pid);
1062 	EXPECT_EQ(msg.ids.pid, msg.thread_info.tgid);
1063 }
1064 
peer_connect_thread(void * arg)1065 static void *peer_connect_thread(void *arg)
1066 {
1067 	struct sock_addr *sa = arg;
1068 	struct thread_ids ids = {
1069 		.pid = getpid(),
1070 		.tid = gettid(),
1071 	};
1072 	int fd;
1073 	char sync;
1074 
1075 	fd = socket(AF_UNIX, SOCK_STREAM, 0);
1076 	if (fd < 0)
1077 		return (void *)1;
1078 
1079 	if (connect(fd, (struct sockaddr *)&sa->listen_addr, sa->addrlen))
1080 		return (void *)1;
1081 
1082 	if (send(fd, &ids, sizeof(ids), 0) != sizeof(ids))
1083 		return (void *)1;
1084 
1085 	/* stay alive until the server has looked at our pidfd */
1086 	if (read(fd, &sync, 1) != 1)
1087 		return (void *)1;
1088 
1089 	close(fd);
1090 	return NULL;
1091 }
1092 
peer_pidfd_info(int fd,int optname,struct pidfd_info * info)1093 static int peer_pidfd_info(int fd, int optname, struct pidfd_info *info)
1094 {
1095 	int pidfd;
1096 	socklen_t len = sizeof(pidfd);
1097 
1098 	if (getsockopt(fd, SOL_SOCKET, optname, &pidfd, &len)) {
1099 		log_err("getsockopt(SO_PEERPIDFD*)");
1100 		return -1;
1101 	}
1102 
1103 	info->mask = PIDFD_INFO_PID;
1104 	if (ioctl(pidfd, PIDFD_GET_INFO, info)) {
1105 		log_err("ioctl(PIDFD_GET_INFO)");
1106 		close(pidfd);
1107 		return -1;
1108 	}
1109 
1110 	close(pidfd);
1111 	return 0;
1112 }
1113 
1114 /* SO_PEERPIDFD_THREAD returns a pidfd for the peer's connecting thread. */
TEST(so_peerpidfd_thread)1115 TEST(so_peerpidfd_thread)
1116 {
1117 	struct sock_addr sa;
1118 	struct thread_ids ids;
1119 	struct pidfd_info info;
1120 	pthread_t thread;
1121 	void *tret;
1122 	int server, cfd;
1123 
1124 	server = socket(AF_UNIX, SOCK_STREAM, 0);
1125 	ASSERT_LE(0, server);
1126 
1127 	fill_sockaddr(&sa, true);
1128 	ASSERT_EQ(0, bind(server, (struct sockaddr *)&sa.listen_addr, sa.addrlen));
1129 	ASSERT_EQ(0, listen(server, 1));
1130 
1131 	ASSERT_EQ(0, pthread_create(&thread, NULL, peer_connect_thread, &sa));
1132 
1133 	cfd = accept(server, NULL, NULL);
1134 	ASSERT_LE(0, cfd);
1135 
1136 	ASSERT_EQ(sizeof(ids), recv(cfd, &ids, sizeof(ids), MSG_WAITALL));
1137 	ASSERT_NE(ids.pid, ids.tid);
1138 
1139 	/* SO_PEERPIDFD refers to the peer's thread-group. */
1140 	ASSERT_EQ(0, peer_pidfd_info(cfd, SO_PEERPIDFD, &info));
1141 	EXPECT_EQ(ids.pid, info.pid);
1142 	EXPECT_EQ(ids.pid, info.tgid);
1143 
1144 	/* SO_PEERPIDFD_THREAD refers to the connecting thread. */
1145 	ASSERT_EQ(0, peer_pidfd_info(cfd, SO_PEERPIDFD_THREAD, &info));
1146 	EXPECT_EQ(ids.tid, info.pid);
1147 	EXPECT_EQ(ids.pid, info.tgid);
1148 
1149 	/* release the connecting thread */
1150 	ASSERT_EQ(1, write(cfd, "x", 1));
1151 	ASSERT_EQ(0, pthread_join(thread, &tret));
1152 	ASSERT_EQ(NULL, tret);
1153 
1154 	close(cfd);
1155 	close(server);
1156 }
1157 
1158 TEST_HARNESS_MAIN
1159