Skip to content

Commit d5accb8

Browse files
Adapt existing tests for O_CLOEXEC to O_CLOFORK
1 parent 199decc commit d5accb8

File tree

3 files changed

+241
-1
lines changed

3 files changed

+241
-1
lines changed

tests/sys/file/closefrom_test.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,5 +356,38 @@ main(void)
356356
fail_err("close_range");
357357
ok("close_range(..., CLOSE_RANGE_CLOEXEC)");
358358

359+
/* test CLOSE_RANGE_CLOFORK */
360+
for (i = 0; i < 8; i++)
361+
(void)devnull();
362+
fd = highest_fd();
363+
start = fd - 8;
364+
if (close_range(start + 1, start + 4, CLOSE_RANGE_CLOFORK) < 0)
365+
fail_err("close_range(..., CLOSE_RANGE_CLOFORK)");
366+
flags = fcntl(start, F_GETFD);
367+
if (flags < 0)
368+
fail_err("fcntl(.., F_GETFD)");
369+
if ((flags & FD_CLOFORK) != 0)
370+
fail("close_range", "CLOSE_RANGE_CLOFORK set close-on-exec "
371+
"when it should not have on fd %d", start);
372+
for (i = start + 1; i <= start + 4; i++) {
373+
flags = fcntl(i, F_GETFD);
374+
if (flags < 0)
375+
fail_err("fcntl(.., F_GETFD)");
376+
if ((flags & FD_CLOFORK) == 0)
377+
fail("close_range", "CLOSE_RANGE_CLOFORK did not set "
378+
"close-on-exec on fd %d", i);
379+
}
380+
for (; i < start + 8; i++) {
381+
flags = fcntl(i, F_GETFD);
382+
if (flags < 0)
383+
fail_err("fcntl(.., F_GETFD)");
384+
if ((flags & FD_CLOFORK) != 0)
385+
fail("close_range", "CLOSE_RANGE_CLOFORK set close-on-exec "
386+
"when it should not have on fd %d", i);
387+
}
388+
if (close_range(start, start + 8, 0) < 0)
389+
fail_err("close_range");
390+
ok("close_range(..., CLOSE_RANGE_CLOFORK)");
391+
359392
return (0);
360393
}

tests/sys/file/dup_test.c

Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
* Test #31: check if dup3(0) fails if oldfd == newfd.
4747
* Test #32: check if dup3(O_CLOEXEC) to a fd > current maximum number of
4848
* open files limit work.
49+
* Tests #33-50 : Same as #15-32 with O_CLOFORK instead of O_CLOEXEC
4950
*/
5051

5152
#include <sys/types.h>
@@ -60,6 +61,8 @@
6061

6162
static int getafile(void);
6263

64+
static int test = 0;
65+
6366
static int
6467
getafile(void)
6568
{
@@ -78,7 +81,7 @@ int
7881
main(int __unused argc, char __unused *argv[])
7982
{
8083
struct rlimit rlp;
81-
int orgfd, fd1, fd2, test = 0;
84+
int orgfd, fd1, fd2;
8285

8386
orgfd = getafile();
8487

@@ -380,5 +383,139 @@ main(int __unused argc, char __unused *argv[])
380383
printf("ok %d - dup3(O_CLOEXEC) didn't bypass NOFILE limit\n",
381384
test);
382385

386+
/* Does fcntl(F_DUPFD_CLOFORK) work? */
387+
if ((fd2 = fcntl(fd1, F_DUPFD_CLOFORK, 10)) < 0)
388+
err(1, "fcntl(F_DUPFD_CLOFORK)");
389+
if (fd2 < 10)
390+
printf("not ok %d - fcntl(F_DUPFD_CLOFORK) returned wrong fd %d\n",
391+
++test, fd2);
392+
else
393+
printf("ok %d - fcntl(F_DUPFD_CLOFORK) works\n", ++test);
394+
395+
/* Was close-on-fork cleared? */
396+
++test;
397+
if (fcntl(fd2, F_GETFD) != FD_CLOFORK)
398+
printf(
399+
"not ok %d - fcntl(F_DUPFD_CLOFORK) didn't set close-on-fork\n",
400+
test);
401+
else
402+
printf("ok %d - fcntl(F_DUPFD_CLOFORK) set close-on-fork\n",
403+
test);
404+
405+
/* If fcntl(F_DUP2FD_CLOFORK) ever work? */
406+
if ((fd2 = fcntl(fd1, F_DUP2FD_CLOFORK, fd1 + 1)) < 0)
407+
err(1, "fcntl(F_DUP2FD_CLOFORK)");
408+
printf("ok %d - fcntl(F_DUP2FD_CLOFORK) works\n", ++test);
409+
410+
/* Do we get the right fd? */
411+
++test;
412+
if (fd2 != fd1 + 1)
413+
printf(
414+
"no ok %d - fcntl(F_DUP2FD_CLOFORK) didn't give us the right fd\n",
415+
test);
416+
else
417+
printf("ok %d - fcntl(F_DUP2FD_CLOFORK) returned a correct fd\n",
418+
test);
419+
420+
/* Was close-on-fork set? */
421+
++test;
422+
if (fcntl(fd2, F_GETFD) != FD_CLOFORK)
423+
printf(
424+
"not ok %d - fcntl(F_DUP2FD_CLOFORK) didn't set close-on-fork\n",
425+
test);
426+
else
427+
printf("ok %d - fcntl(F_DUP2FD_CLOFORK) set close-on-fork\n",
428+
test);
429+
430+
/*
431+
* It is unclear what F_DUP2FD_CLOFORK should do when duplicating a
432+
* file descriptor onto itself.
433+
*/
434+
435+
++test;
436+
if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
437+
err(1, "getrlimit");
438+
if ((fd2 = fcntl(fd1, F_DUP2FD_CLOFORK, rlp.rlim_cur + 1)) >= 0)
439+
printf("not ok %d - fcntl(F_DUP2FD_CLOFORK) bypassed NOFILE limit\n",
440+
test);
441+
else
442+
printf("ok %d - fcntl(F_DUP2FD_CLOFORK) didn't bypass NOFILE limit\n",
443+
test);
444+
445+
/* Does dup3(O_CLOFORK) ever work? */
446+
if ((fd2 = dup3(fd1, fd1 + 1, O_CLOFORK)) < 0)
447+
err(1, "dup3(O_CLOFORK)");
448+
printf("ok %d - dup3(O_CLOFORK) works\n", ++test);
449+
450+
/* Do we get the right fd? */
451+
++test;
452+
if (fd2 != fd1 + 1)
453+
printf(
454+
"no ok %d - dup3(O_CLOFORK) didn't give us the right fd\n",
455+
test);
456+
else
457+
printf("ok %d - dup3(O_CLOFORK) returned a correct fd\n",
458+
test);
459+
460+
/* Was close-on-fork set? */
461+
++test;
462+
if (fcntl(fd2, F_GETFD) != FD_CLOFORK)
463+
printf(
464+
"not ok %d - dup3(O_CLOFORK) didn't set close-on-fork\n",
465+
test);
466+
else
467+
printf("ok %d - dup3(O_CLOFORK) set close-on-fork\n",
468+
test);
469+
470+
/* Does dup3(0) ever work? */
471+
if ((fd2 = dup3(fd1, fd1 + 1, 0)) < 0)
472+
err(1, "dup3(0)");
473+
printf("ok %d - dup3(0) works\n", ++test);
474+
475+
/* Do we get the right fd? */
476+
++test;
477+
if (fd2 != fd1 + 1)
478+
printf(
479+
"no ok %d - dup3(0) didn't give us the right fd\n",
480+
test);
481+
else
482+
printf("ok %d - dup3(0) returned a correct fd\n",
483+
test);
484+
485+
/* Was close-on-fork cleared? */
486+
++test;
487+
if (fcntl(fd2, F_GETFD) != 0)
488+
printf(
489+
"not ok %d - dup3(0) didn't clear close-on-fork\n",
490+
test);
491+
else
492+
printf("ok %d - dup3(0) cleared close-on-fork\n",
493+
test);
494+
495+
/* dup3() does not allow duplicating to the same fd */
496+
++test;
497+
if (dup3(fd1, fd1, O_CLOFORK) != -1)
498+
printf(
499+
"not ok %d - dup3(fd1, fd1, O_CLOFORK) succeeded\n", test);
500+
else
501+
printf("ok %d - dup3(fd1, fd1, O_CLOFORK) failed\n", test);
502+
503+
++test;
504+
if (dup3(fd1, fd1, 0) != -1)
505+
printf(
506+
"not ok %d - dup3(fd1, fd1, 0) succeeded\n", test);
507+
else
508+
printf("ok %d - dup3(fd1, fd1, 0) failed\n", test);
509+
510+
++test;
511+
if (getrlimit(RLIMIT_NOFILE, &rlp) < 0)
512+
err(1, "getrlimit");
513+
if ((fd2 = dup3(fd1, rlp.rlim_cur + 1, O_CLOFORK)) >= 0)
514+
printf("not ok %d - dup3(O_CLOFORK) bypassed NOFILE limit\n",
515+
test);
516+
else
517+
printf("ok %d - dup3(O_CLOFORK) didn't bypass NOFILE limit\n",
518+
test);
519+
383520
return (0);
384521
}

tests/sys/kern/unix_passfd_test.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,30 @@ ATF_TC_BODY(simple_send_fd_msg_cmsg_cloexec, tc)
375375
closesocketpair(fd);
376376
}
377377

378+
/*
379+
* Like simple_send_fd but also sets MSG_CMSG_CLOFORK and checks that the
380+
* received file descriptor has the FD_CLOFORK flag set.
381+
*/
382+
ATF_TC_WITHOUT_HEAD(simple_send_fd_msg_cmsg_clofork);
383+
ATF_TC_BODY(simple_send_fd_msg_cmsg_clofork, tc)
384+
{
385+
struct stat getfd_stat, putfd_stat;
386+
int fd[2], getfd, putfd;
387+
388+
domainsocketpair(fd);
389+
tempfile(&putfd);
390+
dofstat(putfd, &putfd_stat);
391+
sendfd(fd[0], putfd);
392+
recvfd(fd[1], &getfd, MSG_CMSG_CLOFORK);
393+
dofstat(getfd, &getfd_stat);
394+
samefile(&putfd_stat, &getfd_stat);
395+
ATF_REQUIRE_EQ_MSG(fcntl(getfd, F_GETFD) & FD_CLOFORK, FD_CLOFORK,
396+
"FD_CLOFORK not set on the received file descriptor");
397+
close(putfd);
398+
close(getfd);
399+
closesocketpair(fd);
400+
}
401+
378402
/*
379403
* Same as simple_send_fd, only close the file reference after sending, so that
380404
* the only reference is the descriptor in the UNIX domain socket buffer.
@@ -544,6 +568,51 @@ ATF_TC_BODY(send_overflow, tc)
544568
closesocketpair(fd);
545569
}
546570

571+
/*
572+
* Make sure that we do not receive descriptors with MSG_PEEK.
573+
*/
574+
ATF_TC_WITHOUT_HEAD(peek);
575+
ATF_TC_BODY(peek, tc)
576+
{
577+
int fd[2], getfd, putfd, nfds;
578+
579+
domainsocketpair(fd);
580+
tempfile(&putfd);
581+
nfds = getnfds();
582+
sendfd(fd[0], putfd);
583+
ATF_REQUIRE(getnfds() == nfds);
584+
585+
/* First make MSG_PEEK recvmsg(2)... */
586+
char cbuf[CMSG_SPACE(sizeof(int))];
587+
char buf[1];
588+
struct iovec iov = {
589+
.iov_base = buf,
590+
.iov_len = sizeof(buf)
591+
};
592+
struct msghdr msghdr = {
593+
.msg_iov = &iov,
594+
.msg_iovlen = 1,
595+
.msg_control = cbuf,
596+
.msg_controllen = sizeof(cbuf),
597+
};
598+
ATF_REQUIRE(1 == recvmsg(fd[1], &msghdr, MSG_PEEK));
599+
for (struct cmsghdr *cmsghdr = CMSG_FIRSTHDR(&msghdr);
600+
cmsghdr != NULL; cmsghdr = CMSG_NXTHDR(&msghdr, cmsghdr)) {
601+
/* Usually this is some garbage. */
602+
printf("level %d type %d len %u\n",
603+
cmsghdr->cmsg_level, cmsghdr->cmsg_type, cmsghdr->cmsg_len);
604+
}
605+
606+
/* ... and make sure we did not receive any descriptors! */
607+
ATF_REQUIRE(getnfds() == nfds);
608+
609+
/* Now really receive a descriptor. */
610+
recvfd(fd[1], &getfd, 0);
611+
ATF_REQUIRE(getnfds() == nfds + 1);
612+
close(putfd);
613+
close(getfd);
614+
closesocketpair(fd);
615+
}
547616

548617
/*
549618
* Send two files. Then receive them. Make sure they are returned in the
@@ -992,6 +1061,7 @@ ATF_TP_ADD_TCS(tp)
9921061

9931062
ATF_TP_ADD_TC(tp, simple_send_fd);
9941063
ATF_TP_ADD_TC(tp, simple_send_fd_msg_cmsg_cloexec);
1064+
ATF_TP_ADD_TC(tp, simple_send_fd_msg_cmsg_clofork);
9951065
ATF_TP_ADD_TC(tp, send_and_close);
9961066
ATF_TP_ADD_TC(tp, send_and_cancel);
9971067
ATF_TP_ADD_TC(tp, send_and_shutdown);

0 commit comments

Comments
 (0)