Home | History | Annotate | Line # | Download | only in sys
t_dup.c revision 1.8.14.1
      1  1.8.14.1  pgoyette /* $NetBSD: t_dup.c,v 1.8.14.1 2017/03/20 06:57:59 pgoyette Exp $ */
      2       1.1    jruoho 
      3       1.1    jruoho /*-
      4       1.1    jruoho  * Copyright (c) 2011 The NetBSD Foundation, Inc.
      5       1.1    jruoho  * All rights reserved.
      6       1.1    jruoho  *
      7       1.1    jruoho  * This code is derived from software contributed to The NetBSD Foundation
      8       1.1    jruoho  * by Jukka Ruohonen.
      9       1.1    jruoho  *
     10       1.1    jruoho  * Redistribution and use in source and binary forms, with or without
     11       1.1    jruoho  * modification, are permitted provided that the following conditions
     12       1.1    jruoho  * are met:
     13       1.1    jruoho  * 1. Redistributions of source code must retain the above copyright
     14       1.1    jruoho  *    notice, this list of conditions and the following disclaimer.
     15       1.1    jruoho  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1    jruoho  *    notice, this list of conditions and the following disclaimer in the
     17       1.1    jruoho  *    documentation and/or other materials provided with the distribution.
     18       1.1    jruoho  *
     19       1.1    jruoho  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20       1.1    jruoho  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21       1.1    jruoho  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22       1.1    jruoho  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23       1.1    jruoho  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24       1.1    jruoho  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25       1.1    jruoho  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26       1.1    jruoho  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27       1.1    jruoho  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28       1.1    jruoho  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29       1.1    jruoho  * POSSIBILITY OF SUCH DAMAGE.
     30       1.1    jruoho  */
     31       1.1    jruoho #include <sys/cdefs.h>
     32  1.8.14.1  pgoyette __RCSID("$NetBSD: t_dup.c,v 1.8.14.1 2017/03/20 06:57:59 pgoyette Exp $");
     33       1.1    jruoho 
     34       1.1    jruoho #include <sys/resource.h>
     35       1.1    jruoho #include <sys/stat.h>
     36       1.2    jruoho #include <sys/wait.h>
     37       1.1    jruoho 
     38       1.2    jruoho #include <atf-c.h>
     39       1.1    jruoho #include <errno.h>
     40       1.1    jruoho #include <fcntl.h>
     41       1.3    jruoho #include <limits.h>
     42  1.8.14.1  pgoyette #include <stdbool.h>
     43       1.2    jruoho #include <stdio.h>
     44       1.1    jruoho #include <stdlib.h>
     45       1.1    jruoho #include <string.h>
     46       1.1    jruoho #include <unistd.h>
     47       1.2    jruoho #include <sysexits.h>
     48       1.1    jruoho 
     49       1.3    jruoho static char	path[] = "dup";
     50       1.3    jruoho static void	check_mode(bool, bool, bool);
     51       1.3    jruoho 
     52       1.3    jruoho static void
     53       1.3    jruoho check_mode(bool _dup, bool _dup2, bool _dup3)
     54       1.3    jruoho {
     55       1.3    jruoho 	int mode[3] = { O_RDONLY, O_WRONLY, O_RDWR   };
     56       1.3    jruoho 	int perm[5] = { 0700, 0400, 0600, 0444, 0666 };
     57       1.3    jruoho 	struct stat st, st1;
     58       1.3    jruoho 	int fd, fd1, fd2;
     59       1.3    jruoho 	size_t i, j;
     60       1.3    jruoho 
     61       1.3    jruoho 	/*
     62       1.3    jruoho 	 * Check that a duplicated descriptor
     63       1.3    jruoho 	 * retains the mode of the original file.
     64       1.3    jruoho 	 */
     65       1.3    jruoho 	for (i = 0; i < __arraycount(mode); i++) {
     66       1.3    jruoho 
     67       1.3    jruoho 		for (j = 0; j < __arraycount(perm); j++) {
     68       1.3    jruoho 
     69       1.3    jruoho 			fd1 = open(path, mode[i] | O_CREAT, perm[j]);
     70       1.3    jruoho 			fd2 = open("/etc/passwd", O_RDONLY);
     71       1.3    jruoho 
     72       1.3    jruoho 			ATF_REQUIRE(fd1 >= 0);
     73       1.3    jruoho 			ATF_REQUIRE(fd2 >= 0);
     74       1.3    jruoho 
     75       1.3    jruoho 			if (_dup != false)
     76       1.3    jruoho 				fd = dup(fd1);
     77       1.3    jruoho 			else if (_dup2 != false)
     78       1.3    jruoho 				fd = dup2(fd1, fd2);
     79       1.3    jruoho 			else if (_dup3 != false)
     80       1.3    jruoho 				fd = dup3(fd1, fd2, O_CLOEXEC);
     81       1.3    jruoho 			else {
     82       1.3    jruoho 				fd = -1;
     83       1.3    jruoho 			}
     84       1.3    jruoho 
     85       1.3    jruoho 			ATF_REQUIRE(fd >= 0);
     86       1.3    jruoho 
     87       1.3    jruoho 			(void)memset(&st, 0, sizeof(struct stat));
     88       1.3    jruoho 			(void)memset(&st1, 0, sizeof(struct stat));
     89       1.3    jruoho 
     90       1.3    jruoho 			ATF_REQUIRE(fstat(fd, &st) == 0);
     91       1.3    jruoho 			ATF_REQUIRE(fstat(fd1, &st1) == 0);
     92       1.3    jruoho 
     93       1.3    jruoho 			if (st.st_mode != st1.st_mode)
     94       1.3    jruoho 				atf_tc_fail("invalid mode");
     95       1.3    jruoho 
     96       1.3    jruoho 			(void)close(fd);
     97       1.3    jruoho 			(void)close(fd1);
     98       1.3    jruoho 			(void)close(fd2);
     99       1.3    jruoho 			(void)unlink(path);
    100       1.3    jruoho 		}
    101       1.3    jruoho 	}
    102       1.3    jruoho }
    103       1.3    jruoho 
    104       1.3    jruoho ATF_TC(dup2_basic);
    105       1.3    jruoho ATF_TC_HEAD(dup2_basic, tc)
    106       1.3    jruoho {
    107       1.3    jruoho 	atf_tc_set_md_var(tc, "descr", "A basic test of dup2(2)");
    108       1.3    jruoho }
    109       1.3    jruoho 
    110       1.3    jruoho ATF_TC_BODY(dup2_basic, tc)
    111       1.3    jruoho {
    112       1.3    jruoho 	int fd, fd1, fd2;
    113       1.3    jruoho 
    114       1.3    jruoho 	fd1 = open("/etc/passwd", O_RDONLY);
    115       1.3    jruoho 	fd2 = open("/etc/passwd", O_RDONLY);
    116       1.3    jruoho 
    117       1.3    jruoho 	ATF_REQUIRE(fd1 >= 0);
    118       1.3    jruoho 	ATF_REQUIRE(fd2 >= 0);
    119       1.3    jruoho 
    120       1.3    jruoho 	fd = dup2(fd1, fd2);
    121       1.3    jruoho 	ATF_REQUIRE(fd >= 0);
    122       1.3    jruoho 
    123       1.3    jruoho 	if (fd != fd2)
    124       1.3    jruoho 		atf_tc_fail("invalid descriptor");
    125       1.3    jruoho 
    126       1.3    jruoho 	(void)close(fd);
    127       1.3    jruoho 	(void)close(fd1);
    128       1.3    jruoho 
    129       1.3    jruoho 	ATF_REQUIRE(close(fd2) != 0);
    130       1.3    jruoho }
    131       1.3    jruoho 
    132       1.3    jruoho ATF_TC(dup2_err);
    133       1.3    jruoho ATF_TC_HEAD(dup2_err, tc)
    134       1.3    jruoho {
    135       1.3    jruoho 	atf_tc_set_md_var(tc, "descr", "Test error conditions of dup2(2)");
    136       1.3    jruoho }
    137       1.3    jruoho 
    138       1.3    jruoho ATF_TC_BODY(dup2_err, tc)
    139       1.3    jruoho {
    140       1.3    jruoho 	int fd;
    141       1.3    jruoho 
    142       1.3    jruoho 	fd = open("/etc/passwd", O_RDONLY);
    143       1.3    jruoho 	ATF_REQUIRE(fd >= 0);
    144       1.3    jruoho 
    145       1.3    jruoho 	errno = 0;
    146       1.3    jruoho 	ATF_REQUIRE_ERRNO(EBADF, dup2(-1, -1) == -1);
    147       1.3    jruoho 
    148       1.3    jruoho 	errno = 0;
    149       1.3    jruoho 	ATF_REQUIRE_ERRNO(EBADF, dup2(fd, -1) == -1);
    150       1.3    jruoho 
    151       1.3    jruoho 	errno = 0;
    152       1.3    jruoho 	ATF_REQUIRE_ERRNO(EBADF, dup2(-1, fd) == -1);
    153       1.3    jruoho 
    154       1.3    jruoho 	/*
    155       1.3    jruoho 	 * Note that this should not fail with EINVAL.
    156       1.3    jruoho 	 */
    157       1.3    jruoho 	ATF_REQUIRE(dup2(fd, fd) != -1);
    158       1.3    jruoho 
    159       1.3    jruoho 	(void)close(fd);
    160       1.3    jruoho }
    161       1.3    jruoho 
    162       1.5    jruoho ATF_TC(dup2_max);
    163       1.5    jruoho ATF_TC_HEAD(dup2_max, tc)
    164       1.5    jruoho {
    165       1.5    jruoho 	atf_tc_set_md_var(tc, "descr", "Test dup2(2) against limits");
    166       1.5    jruoho }
    167       1.5    jruoho 
    168       1.5    jruoho ATF_TC_BODY(dup2_max, tc)
    169       1.5    jruoho {
    170       1.5    jruoho 	struct rlimit res;
    171       1.5    jruoho 
    172       1.5    jruoho 	(void)memset(&res, 0, sizeof(struct rlimit));
    173       1.5    jruoho 	(void)getrlimit(RLIMIT_NOFILE, &res);
    174       1.5    jruoho 
    175       1.5    jruoho 	errno = 0;
    176       1.5    jruoho 	ATF_REQUIRE_ERRNO(EBADF, dup2(STDERR_FILENO, res.rlim_cur + 1) == -1);
    177       1.5    jruoho }
    178       1.5    jruoho 
    179       1.3    jruoho ATF_TC_WITH_CLEANUP(dup2_mode);
    180       1.3    jruoho ATF_TC_HEAD(dup2_mode, tc)
    181       1.3    jruoho {
    182       1.3    jruoho 	atf_tc_set_md_var(tc, "descr", "A basic test of dup2(2)");
    183       1.3    jruoho }
    184       1.3    jruoho 
    185       1.3    jruoho ATF_TC_BODY(dup2_mode, tc)
    186       1.3    jruoho {
    187       1.3    jruoho 	check_mode(false, true, false);
    188       1.3    jruoho }
    189       1.3    jruoho 
    190       1.3    jruoho ATF_TC_CLEANUP(dup2_mode, tc)
    191       1.3    jruoho {
    192       1.3    jruoho 	(void)unlink(path);
    193       1.3    jruoho }
    194       1.3    jruoho 
    195       1.3    jruoho 
    196       1.3    jruoho ATF_TC(dup3_err);
    197       1.3    jruoho ATF_TC_HEAD(dup3_err, tc)
    198       1.3    jruoho {
    199       1.8    jruoho 	atf_tc_set_md_var(tc, "descr",
    200       1.8    jruoho 	    "Test error conditions of dup3(2) (PR lib/45148)");
    201       1.3    jruoho }
    202       1.3    jruoho 
    203       1.3    jruoho ATF_TC_BODY(dup3_err, tc)
    204       1.3    jruoho {
    205       1.3    jruoho 	int fd;
    206       1.3    jruoho 
    207       1.3    jruoho 	fd = open("/etc/passwd", O_RDONLY);
    208       1.3    jruoho 	ATF_REQUIRE(fd >= 0);
    209       1.3    jruoho 
    210       1.3    jruoho 	errno = 0;
    211       1.3    jruoho 	ATF_REQUIRE(dup3(fd, fd, O_CLOEXEC) != -1);
    212       1.3    jruoho 
    213       1.3    jruoho 	errno = 0;
    214       1.3    jruoho 	ATF_REQUIRE_ERRNO(EBADF, dup3(-1, -1, O_CLOEXEC) == -1);
    215       1.3    jruoho 
    216       1.3    jruoho 	errno = 0;
    217       1.3    jruoho 	ATF_REQUIRE_ERRNO(EBADF, dup3(fd, -1, O_CLOEXEC) == -1);
    218       1.3    jruoho 
    219       1.3    jruoho 	errno = 0;
    220       1.3    jruoho 	ATF_REQUIRE_ERRNO(EBADF, dup3(-1, fd, O_CLOEXEC) == -1);
    221       1.3    jruoho 
    222       1.3    jruoho 	errno = 0;
    223       1.4    jruoho 	ATF_REQUIRE_ERRNO(EINVAL, dup3(fd, 1, O_NOFOLLOW) == -1);
    224       1.3    jruoho 
    225       1.3    jruoho 	(void)close(fd);
    226       1.3    jruoho }
    227       1.3    jruoho 
    228       1.5    jruoho ATF_TC(dup3_max);
    229       1.5    jruoho ATF_TC_HEAD(dup3_max, tc)
    230       1.5    jruoho {
    231       1.5    jruoho 	atf_tc_set_md_var(tc, "descr", "Test dup3(2) against limits");
    232       1.5    jruoho }
    233       1.5    jruoho 
    234       1.5    jruoho ATF_TC_BODY(dup3_max, tc)
    235       1.5    jruoho {
    236       1.5    jruoho 	struct rlimit res;
    237       1.5    jruoho 
    238       1.5    jruoho 	(void)memset(&res, 0, sizeof(struct rlimit));
    239       1.5    jruoho 	(void)getrlimit(RLIMIT_NOFILE, &res);
    240       1.5    jruoho 
    241       1.5    jruoho 	errno = 0;
    242       1.5    jruoho 	ATF_REQUIRE_ERRNO(EBADF, dup3(STDERR_FILENO,
    243       1.5    jruoho 		res.rlim_cur + 1, O_CLOEXEC) == -1);
    244       1.5    jruoho }
    245       1.5    jruoho 
    246       1.3    jruoho ATF_TC_WITH_CLEANUP(dup3_mode);
    247       1.3    jruoho ATF_TC_HEAD(dup3_mode, tc)
    248       1.3    jruoho {
    249       1.3    jruoho 	atf_tc_set_md_var(tc, "descr", "A basic test of dup3(2)");
    250       1.3    jruoho }
    251       1.3    jruoho 
    252       1.3    jruoho ATF_TC_BODY(dup3_mode, tc)
    253       1.3    jruoho {
    254       1.3    jruoho 	check_mode(false, false, true);
    255       1.3    jruoho }
    256       1.3    jruoho 
    257       1.3    jruoho ATF_TC_CLEANUP(dup3_mode, tc)
    258       1.3    jruoho {
    259       1.3    jruoho 	(void)unlink(path);
    260       1.3    jruoho }
    261       1.1    jruoho 
    262       1.1    jruoho ATF_TC(dup_err);
    263       1.1    jruoho ATF_TC_HEAD(dup_err, tc)
    264       1.1    jruoho {
    265       1.1    jruoho 	atf_tc_set_md_var(tc, "descr", "Test error conditions of dup(2)");
    266       1.1    jruoho }
    267       1.1    jruoho 
    268       1.1    jruoho ATF_TC_BODY(dup_err, tc)
    269       1.1    jruoho {
    270       1.3    jruoho 
    271       1.3    jruoho 	errno = 0;
    272       1.3    jruoho 	ATF_REQUIRE_ERRNO(EBADF, dup(-1) == -1);
    273       1.1    jruoho }
    274       1.1    jruoho 
    275       1.1    jruoho ATF_TC_WITH_CLEANUP(dup_max);
    276       1.1    jruoho ATF_TC_HEAD(dup_max, tc)
    277       1.1    jruoho {
    278       1.1    jruoho 	atf_tc_set_md_var(tc, "descr", "Test dup(2) against limits");
    279       1.1    jruoho }
    280       1.1    jruoho 
    281       1.1    jruoho ATF_TC_BODY(dup_max, tc)
    282       1.1    jruoho {
    283       1.1    jruoho 	struct rlimit res;
    284       1.2    jruoho 	int *buf, fd, sta;
    285       1.2    jruoho 	size_t i, n;
    286       1.2    jruoho 	pid_t pid;
    287       1.2    jruoho 
    288       1.2    jruoho 	pid = fork();
    289       1.2    jruoho 	ATF_REQUIRE(pid >= 0);
    290       1.2    jruoho 
    291       1.2    jruoho 	if (pid == 0) {
    292       1.2    jruoho 
    293       1.2    jruoho 		/*
    294       1.2    jruoho 		 * Open a temporary file until the
    295       1.2    jruoho 		 * maximum number of open files is
    296       1.3    jruoho 		 * reached. Ater that dup(2) family
    297       1.3    jruoho 		 * should fail with EMFILE.
    298       1.2    jruoho 		 */
    299       1.2    jruoho 		(void)closefrom(0);
    300       1.2    jruoho 		(void)memset(&res, 0, sizeof(struct rlimit));
    301       1.1    jruoho 
    302       1.6     njoly 		n = 10;
    303       1.6     njoly 		res.rlim_cur = res.rlim_max = n;
    304       1.6     njoly 		if (setrlimit(RLIMIT_NOFILE, &res) != 0)
    305       1.2    jruoho 			_exit(EX_OSERR);
    306       1.2    jruoho 
    307       1.2    jruoho 		buf = calloc(n, sizeof(int));
    308       1.1    jruoho 
    309       1.2    jruoho 		if (buf == NULL)
    310       1.2    jruoho 			_exit(EX_OSERR);
    311       1.1    jruoho 
    312       1.2    jruoho 		buf[0] = mkstemp(path);
    313       1.1    jruoho 
    314       1.2    jruoho 		if (buf[0] < 0)
    315       1.2    jruoho 			_exit(EX_OSERR);
    316       1.1    jruoho 
    317       1.2    jruoho 		for (i = 1; i < n; i++) {
    318       1.1    jruoho 
    319       1.2    jruoho 			buf[i] = open(path, O_RDONLY);
    320       1.1    jruoho 
    321       1.2    jruoho 			if (buf[i] < 0)
    322       1.2    jruoho 				_exit(EX_OSERR);
    323       1.2    jruoho 		}
    324       1.1    jruoho 
    325       1.2    jruoho 		errno = 0;
    326       1.2    jruoho 		fd = dup(buf[0]);
    327       1.1    jruoho 
    328       1.2    jruoho 		if (fd != -1 || errno != EMFILE)
    329       1.2    jruoho 			_exit(EX_DATAERR);
    330       1.1    jruoho 
    331       1.2    jruoho 		_exit(EXIT_SUCCESS);
    332       1.1    jruoho 	}
    333       1.1    jruoho 
    334       1.2    jruoho 	(void)wait(&sta);
    335       1.2    jruoho 
    336       1.2    jruoho 	if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) {
    337       1.1    jruoho 
    338       1.2    jruoho 		if (WEXITSTATUS(sta) == EX_OSERR)
    339       1.3    jruoho 			atf_tc_fail("system call error");
    340       1.1    jruoho 
    341       1.2    jruoho 		if (WEXITSTATUS(sta) == EX_DATAERR)
    342       1.2    jruoho 			atf_tc_fail("dup(2) dupped more than RLIMIT_NOFILE");
    343       1.3    jruoho 
    344       1.3    jruoho 		atf_tc_fail("unknown error");
    345       1.2    jruoho 	}
    346       1.3    jruoho 
    347       1.3    jruoho 	(void)unlink(path);
    348       1.1    jruoho }
    349       1.1    jruoho 
    350       1.1    jruoho ATF_TC_CLEANUP(dup_max, tc)
    351       1.1    jruoho {
    352       1.1    jruoho 	(void)unlink(path);
    353       1.1    jruoho }
    354       1.1    jruoho 
    355       1.1    jruoho ATF_TC_WITH_CLEANUP(dup_mode);
    356       1.1    jruoho ATF_TC_HEAD(dup_mode, tc)
    357       1.1    jruoho {
    358       1.1    jruoho 	atf_tc_set_md_var(tc, "descr", "A basic test of dup(2)");
    359       1.1    jruoho }
    360       1.1    jruoho 
    361       1.1    jruoho ATF_TC_BODY(dup_mode, tc)
    362       1.1    jruoho {
    363       1.3    jruoho 	check_mode(true, false, false);
    364       1.1    jruoho }
    365       1.1    jruoho 
    366       1.1    jruoho ATF_TC_CLEANUP(dup_mode, tc)
    367       1.1    jruoho {
    368       1.1    jruoho 	(void)unlink(path);
    369       1.1    jruoho }
    370       1.1    jruoho 
    371       1.1    jruoho ATF_TP_ADD_TCS(tp)
    372       1.1    jruoho {
    373       1.1    jruoho 
    374       1.3    jruoho 	ATF_TP_ADD_TC(tp, dup2_basic);
    375       1.3    jruoho 	ATF_TP_ADD_TC(tp, dup2_err);
    376       1.5    jruoho 	ATF_TP_ADD_TC(tp, dup2_max);
    377       1.3    jruoho 	ATF_TP_ADD_TC(tp, dup2_mode);
    378       1.3    jruoho 	ATF_TP_ADD_TC(tp, dup3_err);
    379       1.5    jruoho 	ATF_TP_ADD_TC(tp, dup3_max);
    380       1.3    jruoho 	ATF_TP_ADD_TC(tp, dup3_mode);
    381       1.1    jruoho 	ATF_TP_ADD_TC(tp, dup_err);
    382       1.1    jruoho 	ATF_TP_ADD_TC(tp, dup_max);
    383       1.1    jruoho 	ATF_TP_ADD_TC(tp, dup_mode);
    384       1.1    jruoho 
    385       1.1    jruoho 	return atf_no_error();
    386       1.1    jruoho }
    387