Add the syscall tests back. Couple of files and tests were also renamed for

consistency. All of these now mimic the libc structure.
This commit is contained in:
jruoho 2011-07-07 06:57:53 +00:00
parent dc1519dda0
commit 068fb4f133
32 changed files with 6909 additions and 1 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.3 2011/01/13 03:09:54 pgoyette Exp $
# $NetBSD: Makefile,v 1.4 2011/07/07 06:57:53 jruoho Exp $
MKMAN= no
@ -6,10 +6,46 @@ MKMAN= no
TESTSDIR= ${TESTSBASE}/lib/libc/sys
TESTS_C+= t_access
TESTS_C+= t_cerror
TESTS_C+= t_chroot
TESTS_C+= t_clone
TESTS_C+= t_context
TESTS_C+= t_dup
TESTS_C+= t_fsync
TESTS_C+= t_getgroups
TESTS_C+= t_getitimer
TESTS_C+= t_getlogin
TESTS_C+= t_getpid
TESTS_C+= t_getrusage
TESTS_C+= t_getsid
TESTS_C+= t_gettimeofday
TESTS_C+= t_issetugid
TESTS_C+= t_kill
TESTS_C+= t_link
TESTS_C+= t_mincore
TESTS_C+= t_mkfifo
TESTS_C+= t_mknod
TESTS_C+= t_mmap
TESTS_C+= t_mprotect
TESTS_C+= t_msync
TESTS_C+= t_nanosleep
TESTS_C+= t_poll
TESTS_C+= t_revoke
TESTS_C+= t_select
TESTS_C+= t_setrlimit
TESTS_C+= t_setuid
TESTS_C+= t_sigqueue
TESTS_C+= t_stat
TESTS_C+= t_timer_create
TESTS_C+= t_truncate
TESTS_C+= t_umask
TESTS_C+= t_unlink
LDADD.t_getpid+= -lpthread
LDADD.t_timer+= -lpthread
WARNS= 4
.include <bsd.test.mk>

View File

@ -0,0 +1,210 @@
/* $NetBSD: t_access.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_access.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <atf-c.h>
static const char path[] = "access";
static const int mode[4] = { R_OK, W_OK, X_OK, F_OK };
ATF_TC_WITH_CLEANUP(access_access);
ATF_TC_HEAD(access_access, tc)
{
atf_tc_set_md_var(tc, "descr", "Test access(2) for EACCES");
atf_tc_set_md_var(tc, "require.user", "unprivileged");
}
ATF_TC_BODY(access_access, tc)
{
const int perm[3] = { 0200, 0400, 0000 };
size_t i;
int fd;
fd = open(path, O_RDONLY | O_CREAT);
if (fd < 0)
return;
for (i = 0; i < __arraycount(mode) - 1; i++) {
ATF_REQUIRE(fchmod(fd, perm[i]) == 0);
errno = 0;
ATF_REQUIRE(access(path, mode[i]) != 0);
ATF_REQUIRE(errno == EACCES);
}
ATF_REQUIRE(close(fd) == 0);
}
ATF_TC_CLEANUP(access_access, tc)
{
(void)unlink(path);
}
ATF_TC(access_fault);
ATF_TC_HEAD(access_fault, tc)
{
atf_tc_set_md_var(tc, "descr", "Test access(2) for EFAULT");
}
ATF_TC_BODY(access_fault, tc)
{
size_t i;
for (i = 0; i < __arraycount(mode); i++) {
errno = 0;
ATF_REQUIRE(access(NULL, mode[i]) != 0);
ATF_REQUIRE(errno == EFAULT);
errno = 0;
ATF_REQUIRE(access((char *)-1, mode[i]) != 0);
ATF_REQUIRE(errno == EFAULT);
}
}
ATF_TC(access_inval);
ATF_TC_HEAD(access_inval, tc)
{
atf_tc_set_md_var(tc, "descr", "Test access(2) for EINVAL");
}
ATF_TC_BODY(access_inval, tc)
{
errno = 0;
ATF_REQUIRE(access("/usr", -1) != 0);
ATF_REQUIRE(errno == EINVAL);
}
ATF_TC(access_notdir);
ATF_TC_HEAD(access_notdir, tc)
{
atf_tc_set_md_var(tc, "descr", "Test access(2) for ENOTDIR");
}
ATF_TC_BODY(access_notdir, tc)
{
size_t i;
for (i = 0; i < __arraycount(mode); i++) {
errno = 0;
/*
* IEEE Std 1003.1-2008 about ENOTDIR:
*
* "A component of the path prefix is not a directory,
* or the path argument contains at least one non-<slash>
* character and ends with one or more trailing <slash>
* characters and the last pathname component names an
* existing file that is neither a directory nor a symbolic
* link to a directory."
*/
ATF_REQUIRE(access("/etc/passwd//", mode[i]) != 0);
ATF_REQUIRE(errno == ENOTDIR);
}
}
ATF_TC(access_notexist);
ATF_TC_HEAD(access_notexist, tc)
{
atf_tc_set_md_var(tc, "descr", "Test access(2) for ENOENT");
}
ATF_TC_BODY(access_notexist, tc)
{
size_t i;
for (i = 0; i < __arraycount(mode); i++) {
errno = 0;
ATF_REQUIRE(access("", mode[i]) != 0);
ATF_REQUIRE(errno == ENOENT);
}
}
ATF_TC(access_toolong);
ATF_TC_HEAD(access_toolong, tc)
{
atf_tc_set_md_var(tc, "descr", "Test access(2) for ENAMETOOLONG");
}
ATF_TC_BODY(access_toolong, tc)
{
char *buf;
size_t i;
buf = malloc(PATH_MAX);
if (buf == NULL)
return;
for (i = 0; i < PATH_MAX; i++)
buf[i] = 'x';
for (i = 0; i < __arraycount(mode); i++) {
errno = 0;
ATF_REQUIRE(access(buf, mode[i]) != 0);
ATF_REQUIRE(errno == ENAMETOOLONG);
}
free(buf);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, access_access);
ATF_TP_ADD_TC(tp, access_fault);
ATF_TP_ADD_TC(tp, access_inval);
ATF_TP_ADD_TC(tp, access_notdir);
ATF_TP_ADD_TC(tp, access_notexist);
ATF_TP_ADD_TC(tp, access_toolong);
return atf_no_error();
}

View File

@ -0,0 +1,313 @@
/* $NetBSD: t_chroot.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_chroot.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
#include <sys/wait.h>
#include <atf-c.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
ATF_TC(chroot_basic);
ATF_TC_HEAD(chroot_basic, tc)
{
atf_tc_set_md_var(tc, "descr", "A basic test of chroot(2)");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(chroot_basic, tc)
{
char buf[PATH_MAX];
int fd, sta;
pid_t pid;
(void)memset(buf, '\0', sizeof(buf));
(void)getcwd(buf, sizeof(buf));
(void)strlcat(buf, "/dir", sizeof(buf));
ATF_REQUIRE(mkdir(buf, 0500) == 0);
ATF_REQUIRE(chdir(buf) == 0);
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
if (chroot(buf) != 0)
_exit(EXIT_FAILURE);
errno = 0;
if (chroot("/root") != -1)
_exit(EXIT_FAILURE);
if (errno != ENOENT)
_exit(EXIT_FAILURE);
fd = open("file", O_RDONLY | O_CREAT, 0600);
if (fd < 0)
_exit(EXIT_FAILURE);
if (close(fd) != 0)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("chroot(2) failed");
(void)chdir("/");
(void)strlcat(buf, "/file", sizeof(buf));
fd = open(buf, O_RDONLY);
if (fd < 0)
atf_tc_fail("chroot(2) did not change the root directory");
ATF_REQUIRE(close(fd) == 0);
ATF_REQUIRE(unlink(buf) == 0);
}
ATF_TC(chroot_err);
ATF_TC_HEAD(chroot_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test error conditions of chroot(2)");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(chroot_err, tc)
{
char buf[PATH_MAX + 1];
(void)memset(buf, 'x', sizeof(buf));
errno = 0;
ATF_REQUIRE_ERRNO(ENAMETOOLONG, chroot(buf) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, chroot((void *)-1) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENOENT, chroot("/a/b/c/d/e/f/g/h/i/j") == -1);
}
ATF_TC(chroot_perm);
ATF_TC_HEAD(chroot_perm, tc)
{
atf_tc_set_md_var(tc, "descr", "Test permissions with chroot(2)");
atf_tc_set_md_var(tc, "require.user", "unprivileged");
}
ATF_TC_BODY(chroot_perm, tc)
{
static char buf[LINE_MAX];
pid_t pid;
int sta;
(void)memset(buf, '\0', sizeof(buf));
ATF_REQUIRE(getcwd(buf, sizeof(buf)) != NULL);
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
errno = 0;
if (chroot(buf) != -1)
_exit(EXIT_FAILURE);
if (errno != EPERM)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("chroot(2) succeeded as unprivileged user");
}
ATF_TC(fchroot_basic);
ATF_TC_HEAD(fchroot_basic, tc)
{
atf_tc_set_md_var(tc, "descr", "A basic test of fchroot(2)");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(fchroot_basic, tc)
{
char buf[PATH_MAX];
int fd, sta;
pid_t pid;
(void)memset(buf, '\0', sizeof(buf));
(void)getcwd(buf, sizeof(buf));
(void)strlcat(buf, "/dir", sizeof(buf));
ATF_REQUIRE(mkdir(buf, 0500) == 0);
ATF_REQUIRE(chdir(buf) == 0);
fd = open(buf, O_RDONLY);
ATF_REQUIRE(fd >= 0);
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
if (fchroot(fd) != 0)
_exit(EXIT_FAILURE);
if (close(fd) != 0)
_exit(EXIT_FAILURE);
fd = open("file", O_RDONLY | O_CREAT, 0600);
if (fd < 0)
_exit(EXIT_FAILURE);
if (close(fd) != 0)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("fchroot(2) failed");
(void)chdir("/");
(void)strlcat(buf, "/file", sizeof(buf));
fd = open(buf, O_RDONLY);
if (fd < 0)
atf_tc_fail("fchroot(2) did not change the root directory");
ATF_REQUIRE(close(fd) == 0);
ATF_REQUIRE(unlink(buf) == 0);
}
ATF_TC(fchroot_err);
ATF_TC_HEAD(fchroot_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test error conditions of fchroot(2)");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(fchroot_err, tc)
{
int fd;
fd = open("/etc/passwd", O_RDONLY);
ATF_REQUIRE(fd >= 0);
errno = 0;
ATF_REQUIRE_ERRNO(EBADF, fchroot(-1) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENOTDIR, fchroot(fd) == -1);
ATF_REQUIRE(close(fd) == 0);
}
ATF_TC(fchroot_perm);
ATF_TC_HEAD(fchroot_perm, tc)
{
atf_tc_set_md_var(tc, "descr", "Test permissions with fchroot(2)");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(fchroot_perm, tc)
{
static char buf[LINE_MAX];
struct passwd *pw;
int fd, sta;
pid_t pid;
(void)memset(buf, '\0', sizeof(buf));
ATF_REQUIRE(getcwd(buf, sizeof(buf)) != NULL);
pw = getpwnam("nobody");
fd = open(buf, O_RDONLY);
ATF_REQUIRE(fd >= 0);
ATF_REQUIRE(pw != NULL);
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
(void)setuid(pw->pw_uid);
errno = 0;
if (fchroot(fd) != -1)
_exit(EXIT_FAILURE);
if (errno != EPERM)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("fchroot(2) succeeded as unprivileged user");
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, chroot_basic);
ATF_TP_ADD_TC(tp, chroot_err);
ATF_TP_ADD_TC(tp, chroot_perm);
ATF_TP_ADD_TC(tp, fchroot_basic);
ATF_TP_ADD_TC(tp, fchroot_err);
ATF_TP_ADD_TC(tp, fchroot_perm);
return atf_no_error();
}

184
tests/lib/libc/sys/t_dup.c Normal file
View File

@ -0,0 +1,184 @@
/* $NetBSD: t_dup.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_dup.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
#include <sys/resource.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <atf-c.h>
static char path[] = "dup";
ATF_TC(dup_err);
ATF_TC_HEAD(dup_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test error conditions of dup(2)");
}
ATF_TC_BODY(dup_err, tc)
{
ATF_REQUIRE(dup(-1) != 0);
}
ATF_TC_WITH_CLEANUP(dup_max);
ATF_TC_HEAD(dup_max, tc)
{
atf_tc_set_md_var(tc, "descr", "Test dup(2) against limits");
}
ATF_TC_BODY(dup_max, tc)
{
int current, fd, *buf, serrno;
struct rlimit res;
long i, maxfd;
/*
* Open a temporary file until the
* maximum number of open files is
* reached. Ater that dup(2) should
* fail with EMFILE.
*/
(void)memset(&res, 0, sizeof(struct rlimit));
ATF_REQUIRE(getrlimit(RLIMIT_NOFILE, &res) == 0);
ATF_REQUIRE(res.rlim_cur > 0);
ATF_REQUIRE(res.rlim_max > 0);
maxfd = res.rlim_cur;
buf = calloc(maxfd, sizeof(int));
if (buf == NULL)
return;
buf[0] = mkstemp(path);
ATF_REQUIRE(buf[0] != -1);
current = fcntl(0, F_MAXFD);
ATF_REQUIRE(current != -1);
fd = -1;
serrno = EMFILE;
for (i = current; i <= maxfd; i++) {
buf[i] = open(path, O_RDONLY);
if (buf[i] < 0)
goto out;
}
errno = 0;
fd = dup(buf[0]);
serrno = errno;
out:
for (i = 0; i <= maxfd; i++)
(void)close(buf[i]);
free(buf);
if (fd != -1 || serrno != EMFILE)
atf_tc_fail("dup(2) dupped more than RLIMIT_NOFILE");
}
ATF_TC_CLEANUP(dup_max, tc)
{
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(dup_mode);
ATF_TC_HEAD(dup_mode, tc)
{
atf_tc_set_md_var(tc, "descr", "A basic test of dup(2)");
}
ATF_TC_BODY(dup_mode, tc)
{
int mode[3] = { O_RDONLY, O_WRONLY, O_RDWR };
int perm[5] = { 0700, 0400, 0600, 0444, 0666 };
struct stat st1, st2;
int fd1, fd2;
size_t i, j;
/*
* Check that a duplicated descriptor
* retains the mode of the original file.
*/
for (i = 0; i < __arraycount(mode); i++) {
for (j = 0; j < __arraycount(perm); j++) {
fd1 = open(path, mode[i] | O_CREAT, perm[j]);
if (fd1 < 0)
return;
fd2 = dup(fd1);
ATF_REQUIRE(fd2 >= 0);
(void)memset(&st1, 0, sizeof(struct stat));
(void)memset(&st2, 0, sizeof(struct stat));
ATF_REQUIRE(fstat(fd1, &st1) == 0);
ATF_REQUIRE(fstat(fd2, &st2) == 0);
if (st1.st_mode != st2.st_mode)
atf_tc_fail("invalid mode");
ATF_REQUIRE(close(fd1) == 0);
ATF_REQUIRE(close(fd2) == 0);
ATF_REQUIRE(unlink(path) == 0);
}
}
}
ATF_TC_CLEANUP(dup_mode, tc)
{
(void)unlink(path);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, dup_err);
ATF_TP_ADD_TC(tp, dup_max);
ATF_TP_ADD_TC(tp, dup_mode);
return atf_no_error();
}

View File

@ -0,0 +1,119 @@
/* $NetBSD: t_fsync.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_fsync.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <atf-c.h>
ATF_TC(fsync_err);
ATF_TC_HEAD(fsync_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test error conditions of fsync(2)");
}
ATF_TC_BODY(fsync_err, tc)
{
int i, fd[2];
/*
* The fsync(2) call should fail with EBADF
* when the 'fd' is not a valid descriptor.
*/
for (i = 1; i < 1024; i = i + 128) {
errno = 0;
ATF_REQUIRE(fsync(-i) == -1);
ATF_REQUIRE(errno == EBADF);
}
/*
* On the other hand, EINVAL should follow
* if the operation is not possible with
* the file descriptor (cf. PR kern/30).
*/
ATF_REQUIRE(pipe(fd) == 0);
errno = 0;
ATF_REQUIRE(fsync(fd[0]) == -1);
ATF_REQUIRE(errno == EINVAL);
errno = 0;
ATF_REQUIRE(fsync(fd[1]) == -1);
ATF_REQUIRE(errno == EINVAL);
ATF_REQUIRE(close(fd[0]) == 0);
ATF_REQUIRE(close(fd[1]) == 0);
}
ATF_TC(fsync_sync);
ATF_TC_HEAD(fsync_sync, tc)
{
atf_tc_set_md_var(tc, "descr", "A basic test of fsync(2)");
}
ATF_TC_BODY(fsync_sync, tc)
{
char buf[128];
int fd, i;
for (i = 0; i < 10; i++) {
(void)snprintf(buf, sizeof(buf), "t_fsync-%d", i);
fd = mkstemp(buf);
ATF_REQUIRE(fd != -1);
ATF_REQUIRE(write(fd, "0", 1) == 1);
ATF_REQUIRE(fsync(fd) == 0);
ATF_REQUIRE(unlink(buf) == 0);
ATF_REQUIRE(close(fd) == 0);
}
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, fsync_err);
ATF_TP_ADD_TC(tp, fsync_sync);
return atf_no_error();
}

View File

@ -0,0 +1,171 @@
/* $NetBSD: t_getgroups.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_getgroups.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
#include <sys/wait.h>
#include <atf-c.h>
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
ATF_TC(getgroups_err);
ATF_TC_HEAD(getgroups_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test errors in getgroups(2)");
}
ATF_TC_BODY(getgroups_err, tc)
{
gid_t gidset[NGROUPS_MAX];
errno = 0;
ATF_REQUIRE(getgroups(10, (gid_t *)-1) == -1);
ATF_REQUIRE(errno == EFAULT);
errno = 0;
ATF_REQUIRE(getgroups(-1, gidset) == -1);
ATF_REQUIRE(errno == EINVAL);
}
ATF_TC(getgroups_getgid);
ATF_TC_HEAD(getgroups_getgid, tc)
{
atf_tc_set_md_var(tc, "descr", "Test getgid(2) from getgroups(2)");
}
ATF_TC_BODY(getgroups_getgid, tc)
{
gid_t gidset[NGROUPS_MAX];
gid_t gid = getgid();
int i, n;
/*
* Check that getgid(2) is found from
* the GIDs returned by getgroups(2).
*/
n = getgroups(NGROUPS_MAX, gidset);
for (i = 0; i < n; i++) {
if (gidset[i] == gid)
return;
}
atf_tc_fail("getgid(2) not found from getgroups(2)");
}
ATF_TC(getgroups_setgid);
ATF_TC_HEAD(getgroups_setgid, tc)
{
atf_tc_set_md_var(tc, "descr", "Test setgid(2) from getgroups(2)");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(getgroups_setgid, tc)
{
gid_t gidset[NGROUPS_MAX];
int i, n, rv, sta;
pid_t pid;
/*
* Check that we can setgid(2)
* to the returned group IDs.
*/
n = getgroups(NGROUPS_MAX, gidset);
ATF_REQUIRE(n >= 0);
for (i = 0; i < n; i++) {
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
rv = setgid(gidset[i]);
if (rv != 0)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("getgroups(2) is inconsistent");
}
}
ATF_TC(getgroups_zero);
ATF_TC_HEAD(getgroups_zero, tc)
{
atf_tc_set_md_var(tc, "descr", "Test getgroups(2) with zero param");
}
ATF_TC_BODY(getgroups_zero, tc)
{
const gid_t val = 123456789;
gid_t gidset[NGROUPS_MAX];
size_t i;
/*
* If the first parameter is zero, the number
* of groups should be returned but the supplied
* buffer should remain intact.
*/
for (i = 0; i < __arraycount(gidset); i++)
gidset[i] = val;
ATF_REQUIRE(getgroups(0, gidset) >= 0);
for (i = 0; i < __arraycount(gidset); i++) {
if (gidset[i] != val)
atf_tc_fail("getgroups(2) modified the buffer");
}
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, getgroups_err);
ATF_TP_ADD_TC(tp, getgroups_getgid);
ATF_TP_ADD_TC(tp, getgroups_setgid);
ATF_TP_ADD_TC(tp, getgroups_zero);
return atf_no_error();
}

View File

@ -0,0 +1,215 @@
/* $NetBSD: t_getitimer.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_getitimer.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
#include <sys/time.h>
#include <atf-c.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
static bool fail;
static void sighandler(int);
static void
sighandler(int signo)
{
if (signo == SIGALRM || signo == SIGVTALRM)
fail = false;
}
ATF_TC(getitimer_empty);
ATF_TC_HEAD(getitimer_empty, tc)
{
atf_tc_set_md_var(tc, "descr", "getitimer(2) before setitimer(2)");
}
ATF_TC_BODY(getitimer_empty, tc)
{
struct itimerval it;
/*
* Verify that the passed structure remains
* empty after calling getitimer(2) but before
* actually arming the timer with setitimer(2).
*/
(void)memset(&it, 0, sizeof(struct itimerval));
ATF_REQUIRE(getitimer(ITIMER_REAL, &it) == 0);
if (it.it_value.tv_sec != 0 || it.it_value.tv_usec != 0)
goto fail;
ATF_REQUIRE(getitimer(ITIMER_VIRTUAL, &it) == 0);
if (it.it_value.tv_sec != 0 || it.it_value.tv_usec != 0)
goto fail;
ATF_REQUIRE(getitimer(ITIMER_PROF, &it) == 0);
if (it.it_value.tv_sec != 0 || it.it_value.tv_usec != 0)
goto fail;
return;
fail:
atf_tc_fail("getitimer(2) modfied the timer before it was armed");
}
ATF_TC(getitimer_err);
ATF_TC_HEAD(getitimer_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test errors from getitimer(2)");
}
ATF_TC_BODY(getitimer_err, tc)
{
struct itimerval it;
errno = 0;
ATF_REQUIRE_ERRNO(EINVAL, getitimer(-1, &it) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EINVAL, getitimer(INT_MAX, &it) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, getitimer(ITIMER_REAL, (void *)-1) == -1);
}
ATF_TC(setitimer_basic);
ATF_TC_HEAD(setitimer_basic, tc)
{
atf_tc_set_md_var(tc, "descr", "A basic test of setitimer(2)");
}
ATF_TC_BODY(setitimer_basic, tc)
{
struct itimerval it;
it.it_value.tv_sec = 0;
it.it_value.tv_usec = 100;
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 0;
fail = true;
ATF_REQUIRE(signal(SIGALRM, sighandler) != SIG_ERR);
ATF_REQUIRE(setitimer(ITIMER_REAL, &it, NULL) == 0);
/*
* Although the interaction between
* setitimer(2) and sleep(3) can be
* unspecified, it is assumed that one
* second suspension will be enough for
* the timer to fire.
*/
(void)sleep(1);
if (fail != false)
atf_tc_fail("timer did not fire");
}
ATF_TC(setitimer_err);
ATF_TC_HEAD(setitimer_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test errors from setitimer(2)");
}
ATF_TC_BODY(setitimer_err, tc)
{
struct itimerval it, ot;
errno = 0;
ATF_REQUIRE_ERRNO(EINVAL, setitimer(-1, &it, &ot) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EINVAL, setitimer(INT_MAX, &it, &ot) == -1);
/*
* This fails incorrectly with EPERM.
*/
atf_tc_expect_fail("PR standards/44927");
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, setitimer(ITIMER_REAL,(void*)-1, &ot) == -1);
}
ATF_TC(setitimer_old);
ATF_TC_HEAD(setitimer_old, tc)
{
atf_tc_set_md_var(tc, "descr", "Test old values from setitimer(2)");
}
ATF_TC_BODY(setitimer_old, tc)
{
struct itimerval it, ot;
/*
* Make two calls; the second one
* should store the old values.
*/
it.it_value.tv_sec = 4;
it.it_value.tv_usec = 3;
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 0;
ATF_REQUIRE(setitimer(ITIMER_REAL, &it, &ot) == 0);
it.it_value.tv_sec = 2;
it.it_value.tv_usec = 1;
it.it_interval.tv_sec = 0;
it.it_interval.tv_usec = 0;
ATF_REQUIRE(setitimer(ITIMER_REAL, &it, &ot) == 0);
if (ot.it_value.tv_sec != 4 || ot.it_value.tv_usec != 3)
atf_tc_fail("setitimer(2) did not store old values");
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, getitimer_empty);
ATF_TP_ADD_TC(tp, getitimer_err);
ATF_TP_ADD_TC(tp, setitimer_basic);
ATF_TP_ADD_TC(tp, setitimer_err);
ATF_TP_ADD_TC(tp, setitimer_old);
return atf_no_error();
}

View File

@ -0,0 +1,237 @@
/* $NetBSD: t_getlogin.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_getlogin.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
#include <sys/param.h>
#include <sys/wait.h>
#include <atf-c.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
ATF_TC(getlogin_r_err);
ATF_TC_HEAD(getlogin_r_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test errors from getlogin_r(2)");
}
ATF_TC_BODY(getlogin_r_err, tc)
{
char small[0];
ATF_REQUIRE(getlogin_r(small, sizeof(small)) == ERANGE);
}
ATF_TC(getlogin_same);
ATF_TC_HEAD(getlogin_same, tc)
{
atf_tc_set_md_var(tc, "descr", "getlogin(2) vs. getlogin_r(2)");
}
ATF_TC_BODY(getlogin_same, tc)
{
char buf[MAXLOGNAME];
char *str;
str = getlogin();
if (str == NULL)
return;
ATF_REQUIRE(getlogin_r(buf, sizeof(buf)) == 0);
if (strcmp(str, buf) != 0)
atf_tc_fail("getlogin(2) and getlogin_r(2) differ");
}
ATF_TC(setlogin_basic);
ATF_TC_HEAD(setlogin_basic, tc)
{
atf_tc_set_md_var(tc, "descr", "Test that setlogin(2) works");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(setlogin_basic, tc)
{
char *name;
pid_t pid;
int sta;
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
(void)setsid();
if (setlogin("foobar") != 0)
_exit(EXIT_FAILURE);
name = getlogin();
if (name == NULL)
_exit(EXIT_FAILURE);
if (strcmp(name, "foobar") != 0)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("setlogin(2) failed to set login name");
}
ATF_TC(setlogin_err);
ATF_TC_HEAD(setlogin_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test errors from setlogin(2)");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(setlogin_err, tc)
{
char buf[MAXLOGNAME + 1];
char *name;
pid_t pid;
int sta;
pid = fork();
ATF_REQUIRE(pid >= 0);
(void)memset(buf, 'x', sizeof(buf));
if (pid == 0) {
(void)setsid();
errno = 0;
if (setlogin(buf) != -1)
_exit(EINVAL);
if (errno != EINVAL)
_exit(EINVAL);
errno = 0;
if (setlogin((void *)-1) != -1)
_exit(EFAULT);
if (errno != EFAULT)
_exit(EFAULT);
name = getlogin();
if (name == NULL)
_exit(EXIT_FAILURE);
if (strcmp(name, "foobar") == 0)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) {
if (WEXITSTATUS(sta) == EFAULT)
atf_tc_fail("expected EFAULT, but the call succeeded");
if (WEXITSTATUS(sta) == EINVAL)
atf_tc_fail("expected EINVAL, but the call succeeded");
atf_tc_fail("setlogin(2) failed, but login name was set");
}
}
ATF_TC(setlogin_perm);
ATF_TC_HEAD(setlogin_perm, tc)
{
atf_tc_set_md_var(tc, "descr", "Test setlogin(2) as normal user");
atf_tc_set_md_var(tc, "require.user", "unprivileged");
}
ATF_TC_BODY(setlogin_perm, tc)
{
char *name;
pid_t pid;
int sta;
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
(void)setsid();
errno = 0;
if (setlogin("foobar") != -1)
_exit(EXIT_FAILURE);
if (errno != EPERM)
_exit(EXIT_FAILURE);
name = getlogin();
if (name == NULL)
_exit(EXIT_FAILURE);
if (strcmp(name, "foobar") == 0)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("login name was set as an unprivileged user");
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, getlogin_r_err);
ATF_TP_ADD_TC(tp, getlogin_same);
ATF_TP_ADD_TC(tp, setlogin_basic);
ATF_TP_ADD_TC(tp, setlogin_err);
ATF_TP_ADD_TC(tp, setlogin_perm);
return atf_no_error();
}

View File

@ -0,0 +1,134 @@
/* $NetBSD: t_getpid.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_getpid.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
#include <sys/wait.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <atf-c.h>
static int maxiter = 10;
static void *threadfunc(void *);
static void *
threadfunc(void *arg)
{
*(pid_t *)arg = getpid();
return NULL;
}
ATF_TC(getpid_process);
ATF_TC_HEAD(getpid_process, tc)
{
atf_tc_set_md_var(tc, "descr", "Test getpid(2) with processes");
}
ATF_TC_BODY(getpid_process, tc)
{
pid_t ppid, fpid, cpid, tpid, wpid;
int i, sta;
for (i = 0; i < maxiter; i++) {
tpid = getpid();
fpid = fork();
ATF_REQUIRE(fpid >= 0);
if (fpid == 0) {
cpid = getpid();
ppid = getppid();
if (tpid != ppid)
_exit(EXIT_FAILURE);
if (cpid == ppid)
_exit(EXIT_FAILURE);
if (tpid == fpid)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
wpid = wait(&sta);
if (wpid != fpid)
atf_tc_fail("PID mismatch");
ATF_REQUIRE(WIFEXITED(sta) != 0);
if (WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("PID mismatch");
}
}
ATF_TC(getpid_thread);
ATF_TC_HEAD(getpid_thread, tc)
{
atf_tc_set_md_var(tc, "descr", "Test getpid(2) with threads");
}
ATF_TC_BODY(getpid_thread, tc)
{
pid_t pid, tpid;
pthread_t tid;
int i, rv;
for (i = 0; i < maxiter; i++) {
pid = getpid();
rv = pthread_create(&tid, NULL, threadfunc, &tpid);
ATF_REQUIRE(rv == 0);
rv = pthread_join(tid, NULL);
ATF_REQUIRE(rv == 0);
if (pid != tpid)
atf_tc_fail("Unequal PIDs");
}
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, getpid_process);
ATF_TP_ADD_TC(tp, getpid_thread);
return atf_no_error();
}

View File

@ -0,0 +1,192 @@
/* $NetBSD: t_getrusage.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_getrusage.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
#include <sys/resource.h>
#include <sys/time.h>
#include <atf-c.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <string.h>
static void work(void);
static void sighandler(int);
static const size_t maxiter = 2000;
static void
sighandler(int signo)
{
/* Nothing. */
}
static void
work(void)
{
size_t n = UINT16_MAX * 10;
while (n > 0) {
asm volatile("nop"); /* Do something. */
n--;
}
}
ATF_TC(getrusage_err);
ATF_TC_HEAD(getrusage_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test error conditions");
}
ATF_TC_BODY(getrusage_err, tc)
{
struct rusage ru;
errno = 0;
ATF_REQUIRE(getrusage(INT_MAX, &ru) != 0);
ATF_REQUIRE(errno == EINVAL);
errno = 0;
ATF_REQUIRE(getrusage(RUSAGE_SELF, (void *)0) != 0);
ATF_REQUIRE(errno == EFAULT);
}
ATF_TC(getrusage_sig);
ATF_TC_HEAD(getrusage_sig, tc)
{
atf_tc_set_md_var(tc, "descr", "Test signal count with getrusage(2)");
}
ATF_TC_BODY(getrusage_sig, tc)
{
struct rusage ru;
const long n = 5;
int i;
/*
* Test that signals are recorded.
*/
ATF_REQUIRE(signal(SIGUSR1, sighandler) != SIG_ERR);
for (i = 0; i < n; i++)
ATF_REQUIRE(raise(SIGUSR1) == 0);
(void)memset(&ru, 0, sizeof(struct rusage));
ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru) == 0);
if (n != ru.ru_nsignals)
atf_tc_fail("getrusage(2) did not record signals");
}
ATF_TC(getrusage_utime_back);
ATF_TC_HEAD(getrusage_utime_back, tc)
{
atf_tc_set_md_var(tc, "descr", "Test bogus values from getrusage(2)");
}
ATF_TC_BODY(getrusage_utime_back, tc)
{
struct rusage ru1, ru2;
size_t i;
/*
* Test that two consecutive calls are sane.
*/
atf_tc_expect_fail("PR kern/30115");
for (i = 0; i < maxiter; i++) {
(void)memset(&ru1, 0, sizeof(struct rusage));
(void)memset(&ru2, 0, sizeof(struct rusage));
work();
ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru1) == 0);
work();
ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru2) == 0);
if (timercmp(&ru2.ru_utime, &ru1.ru_utime, <) != 0)
atf_tc_fail("user time went backwards");
}
atf_tc_fail("anticipated error did not occur");
}
ATF_TC(getrusage_utime_zero);
ATF_TC_HEAD(getrusage_utime_zero, tc)
{
atf_tc_set_md_var(tc, "descr", "Test zero utime from getrusage(2)");
}
ATF_TC_BODY(getrusage_utime_zero, tc)
{
struct rusage ru;
size_t i;
/*
* Test that getrusage(2) does not return
* zero user time for the calling process.
*
* See also (duplicate) PR port-amd64/41734.
*/
atf_tc_expect_fail("PR kern/30115");
for (i = 0; i < maxiter; i++) {
work();
(void)memset(&ru, 0, sizeof(struct rusage));
ATF_REQUIRE(getrusage(RUSAGE_SELF, &ru) == 0);
if (ru.ru_utime.tv_sec == 0 && ru.ru_utime.tv_usec == 0)
atf_tc_fail("zero user time from getrusage(2)");
}
atf_tc_fail("anticipated error did not occur");
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, getrusage_err);
ATF_TP_ADD_TC(tp, getrusage_sig);
ATF_TP_ADD_TC(tp, getrusage_utime_back);
ATF_TP_ADD_TC(tp, getrusage_utime_zero);
return atf_no_error();
}

View File

@ -0,0 +1,119 @@
/* $NetBSD: t_getsid.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_getsid.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
#include <sys/wait.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <atf-c.h>
ATF_TC(getsid_current);
ATF_TC_HEAD(getsid_current, tc)
{
atf_tc_set_md_var(tc, "descr", "Test getsid(0)");
}
ATF_TC_BODY(getsid_current, tc)
{
pid_t sid;
sid = getsid(0);
ATF_REQUIRE(sid != -1);
if (sid != getsid(getpid()))
atf_tc_fail("getsid(0) did not match the calling process");
}
ATF_TC(getsid_err);
ATF_TC_HEAD(getsid_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test error conditions in getsid(2)");
}
ATF_TC_BODY(getsid_err, tc)
{
errno = 0;
ATF_REQUIRE(getsid(-1) == -1);
ATF_REQUIRE(errno == ESRCH);
}
ATF_TC(getsid_process);
ATF_TC_HEAD(getsid_process, tc)
{
atf_tc_set_md_var(tc, "descr", "Test getsid(2) with processes");
}
ATF_TC_BODY(getsid_process, tc)
{
pid_t csid, pid, ppid, sid;
int sta;
sid = getsid(0);
pid = fork();
ATF_REQUIRE(pid >= 0);
ATF_REQUIRE(sid != -1);
if (pid == 0) {
csid = getsid(0);
ppid = getppid();
if (sid != csid)
_exit(EXIT_FAILURE);
if (getsid(ppid) != csid)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("invalid session ID");
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, getsid_current);
ATF_TP_ADD_TC(tp, getsid_err);
ATF_TP_ADD_TC(tp, getsid_process);
return atf_no_error();
}

View File

@ -0,0 +1,86 @@
/* $NetBSD: t_gettimeofday.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_gettimeofday.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
#include <sys/time.h>
#include <atf-c.h>
#include <errno.h>
#include <string.h>
ATF_TC(gettimeofday_err);
ATF_TC_HEAD(gettimeofday_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test errors from gettimeofday(2)");
}
ATF_TC_BODY(gettimeofday_err, tc)
{
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, gettimeofday((void *)-1, NULL) != 0);
}
ATF_TC(gettimeofday_mono);
ATF_TC_HEAD(gettimeofday_mono, tc)
{
atf_tc_set_md_var(tc, "descr", "Test monotonicity of gettimeofday(2)");
}
ATF_TC_BODY(gettimeofday_mono, tc)
{
static const size_t maxiter = 100;
struct timeval tv1, tv2;
size_t i;
for (i = 0; i < maxiter; i++) {
(void)memset(&tv1, 0, sizeof(struct timeval));
(void)memset(&tv2, 0, sizeof(struct timeval));
ATF_REQUIRE(gettimeofday(&tv1, NULL) == 0);
ATF_REQUIRE(gettimeofday(&tv2, NULL) == 0);
if (timercmp(&tv2, &tv1, <) != 0)
atf_tc_fail("time went backwards");
}
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, gettimeofday_err);
ATF_TP_ADD_TC(tp, gettimeofday_mono);
return atf_no_error();
}

View File

@ -0,0 +1,148 @@
/* $NetBSD: t_issetugid.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_issetugid.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
#include <sys/wait.h>
#include <atf-c.h>
#include <errno.h>
#include <pwd.h>
#include <stdlib.h>
#include <unistd.h>
static bool check(int (*fuid)(uid_t), int (*fgid)(gid_t));
static bool
check(int (*fuid)(uid_t), int (*fgid)(gid_t))
{
struct passwd *pw;
pid_t pid;
int sta;
pw = getpwnam("nobody");
if (pw == NULL)
return false;
pid = fork();
if (pid < 0)
return false;
if (pid == 0) {
if (fuid != NULL && (*fuid)(pw->pw_uid) != 0)
_exit(EXIT_FAILURE);
if (fgid != NULL && (*fgid)(pw->pw_gid) != 0)
_exit(EXIT_FAILURE);
if (issetugid() != 1)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
return false;
return true;
}
ATF_TC(issetugid_egid);
ATF_TC_HEAD(issetugid_egid, tc)
{
atf_tc_set_md_var(tc, "descr", "A test of issetugid(2), eff. GID");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(issetugid_egid, tc)
{
if (check(NULL, setegid) != true)
atf_tc_fail("issetugid(2) failed with effective GID");
}
ATF_TC(issetugid_euid);
ATF_TC_HEAD(issetugid_euid, tc)
{
atf_tc_set_md_var(tc, "descr", "A test of issetugid(2), eff. UID");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(issetugid_euid, tc)
{
if (check(seteuid, NULL) != true)
atf_tc_fail("issetugid(2) failed with effective UID");
}
ATF_TC(issetugid_rgid);
ATF_TC_HEAD(issetugid_rgid, tc)
{
atf_tc_set_md_var(tc, "descr", "A test of issetugid(2), real GID");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(issetugid_rgid, tc)
{
if (check(NULL, setgid) != true)
atf_tc_fail("issetugid(2) failed with real GID");
}
ATF_TC(issetugid_ruid);
ATF_TC_HEAD(issetugid_ruid, tc)
{
atf_tc_set_md_var(tc, "descr", "A test of issetugid(2), real UID");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(issetugid_ruid, tc)
{
if (check(setuid, NULL) != true)
atf_tc_fail("issetugid(2) failed with real UID");
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, issetugid_egid);
ATF_TP_ADD_TC(tp, issetugid_euid);
ATF_TP_ADD_TC(tp, issetugid_rgid);
ATF_TP_ADD_TC(tp, issetugid_ruid);
return atf_no_error();
}

312
tests/lib/libc/sys/t_kill.c Normal file
View File

@ -0,0 +1,312 @@
/* $NetBSD: t_kill.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_kill.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
#include <sys/wait.h>
#include <errno.h>
#include <limits.h>
#include <pwd.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <atf-c.h>
ATF_TC(kill_basic);
ATF_TC_HEAD(kill_basic, tc)
{
atf_tc_set_md_var(tc, "descr", "Test that kill(2) works");
}
ATF_TC_BODY(kill_basic, tc)
{
const int sig[] = { SIGHUP, SIGINT, SIGKILL, SIGTERM };
pid_t pid;
size_t i;
int sta;
for (i = 0; i < __arraycount(sig); i++) {
pid = fork();
ATF_REQUIRE(pid >= 0);
switch (pid) {
case 0:
pause();
break;
default:
ATF_REQUIRE(kill(pid, sig[i]) == 0);
}
(void)wait(&sta);
if (WIFSIGNALED(sta) == 0 || WTERMSIG(sta) != sig[i])
atf_tc_fail("kill(2) failed to kill child");
}
}
ATF_TC(kill_err);
ATF_TC_HEAD(kill_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test error conditions of kill(2)");
}
ATF_TC_BODY(kill_err, tc)
{
int rv, sta;
pid_t pid;
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
errno = 0;
rv = kill(getpid(), -1);
if (rv == 0 || errno != EINVAL)
_exit(EINVAL);
errno = 0;
rv = kill(INT_MAX, SIGUSR1);
if (rv == 0 || errno != ESRCH)
_exit(ESRCH);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) {
if (WEXITSTATUS(sta) == EINVAL)
atf_tc_fail("expected EINVAL, but kill(2) succeeded");
if (WEXITSTATUS(sta) == ESRCH)
atf_tc_fail("expected ESRCH, but kill(2) succeeded");
atf_tc_fail("unknown error from kill(2)");
}
}
ATF_TC(kill_perm);
ATF_TC_HEAD(kill_perm, tc)
{
atf_tc_set_md_var(tc, "descr", "Test kill(2) permissions");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(kill_perm, tc)
{
struct passwd *pw;
pid_t cpid, ppid;
uid_t cuid = 0;
uid_t puid = 0;
int sta;
/*
* Test that kill(2) fails when called
* for a PID owned by another user.
*/
pw = getpwnam("operator");
if (pw != NULL)
cuid = pw->pw_uid;
pw = getpwnam("nobody");
if (pw != NULL)
puid = pw->pw_uid;
if (cuid == 0 || puid == 0 || cuid == puid)
atf_tc_fail("getpwnam(3) failed");
ppid = fork();
if (ppid < 0)
_exit(EXIT_FAILURE);
if (ppid == 0) {
cpid = fork();
if (cpid < 0)
_exit(EXIT_FAILURE);
if (cpid == 0) {
if (setuid(cuid) < 0)
_exit(EXIT_FAILURE);
else {
(void)sleep(1);
}
_exit(EXIT_SUCCESS);
}
/*
* Try to kill the child after having
* set the real and effective UID.
*/
if (setuid(puid) != 0)
_exit(EXIT_FAILURE);
errno = 0;
if (kill(cpid, SIGKILL) == 0)
_exit(EPERM);
if (errno != EPERM)
_exit(EPERM);
(void)waitpid(cpid, &sta, 0);
_exit(EXIT_SUCCESS);
}
(void)waitpid(ppid, &sta, 0);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) == EPERM)
atf_tc_fail("killed a process of another user");
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("unknown error from kill(2)");
}
ATF_TC(kill_pgrp_neg);
ATF_TC_HEAD(kill_pgrp_neg, tc)
{
atf_tc_set_md_var(tc, "descr", "Test kill(2) with process group, #2");
}
ATF_TC_BODY(kill_pgrp_neg, tc)
{
const int maxiter = 3;
pid_t cpid, ppid;
int i, sta;
ppid = fork();
ATF_REQUIRE(ppid >= 0);
if (ppid == 0) {
ATF_REQUIRE(setpgid(0, 0) == 0);
for (i = 0; i < maxiter; i++) {
cpid = fork();
ATF_REQUIRE(cpid >= 0);
if (cpid == 0)
pause();
}
/*
* Test the variant of killpg(3); if the process number
* is negative but not -1, the signal should be sent to
* all processes whose process group ID is equal to the
* absolute value of the process number.
*/
ATF_REQUIRE(kill(-getpgrp(), SIGKILL) == 0);
(void)sleep(1);
_exit(EXIT_SUCCESS);
}
(void)waitpid(ppid, &sta, 0);
if (WIFSIGNALED(sta) == 0 || WTERMSIG(sta) != SIGKILL)
atf_tc_fail("failed to kill(2) a process group");
}
ATF_TC(kill_pgrp_zero);
ATF_TC_HEAD(kill_pgrp_zero, tc)
{
atf_tc_set_md_var(tc, "descr", "Test kill(2) with process group, #1");
}
ATF_TC_BODY(kill_pgrp_zero, tc)
{
const int maxiter = 3;
pid_t cpid, ppid;
int i, sta;
ppid = fork();
ATF_REQUIRE(ppid >= 0);
if (ppid == 0) {
ATF_REQUIRE(setpgid(0, 0) == 0);
for (i = 0; i < maxiter; i++) {
cpid = fork();
ATF_REQUIRE(cpid >= 0);
if (cpid == 0)
pause();
}
/*
* If the supplied process number is zero,
* the signal should be sent to all processes
* under the current process group.
*/
ATF_REQUIRE(kill(0, SIGKILL) == 0);
(void)sleep(1);
_exit(EXIT_SUCCESS);
}
(void)waitpid(ppid, &sta, 0);
if (WIFSIGNALED(sta) == 0 || WTERMSIG(sta) != SIGKILL)
atf_tc_fail("failed to kill(2) a process group");
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, kill_basic);
ATF_TP_ADD_TC(tp, kill_err);
ATF_TP_ADD_TC(tp, kill_perm);
ATF_TP_ADD_TC(tp, kill_pgrp_neg);
ATF_TP_ADD_TC(tp, kill_pgrp_zero);
return atf_no_error();
}

225
tests/lib/libc/sys/t_link.c Normal file
View File

@ -0,0 +1,225 @@
/* $NetBSD: t_link.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_link.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
#include <sys/param.h>
#include <sys/stat.h>
#include <atf-c.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static const char *getpath(void);
static char path[] = "link";
static const char *pathl;
static const char *
getpath(void)
{
static char buf[LINE_MAX];
(void)memset(buf, '\0', sizeof(buf));
if (getcwd(buf, sizeof(buf)) == NULL)
return NULL;
(void)strlcat(buf, path, sizeof(buf));
(void)strlcat(buf, ".link", sizeof(buf));
return buf;
}
ATF_TC_WITH_CLEANUP(link_count);
ATF_TC_HEAD(link_count, tc)
{
atf_tc_set_md_var(tc, "descr", "link(2) counts are incremented?");
}
ATF_TC_BODY(link_count, tc)
{
struct stat sa, sb;
int fd;
(void)memset(&sa, 0, sizeof(struct stat));
(void)memset(&sb, 0, sizeof(struct stat));
pathl = getpath();
fd = open(path, O_RDWR | O_CREAT, 0600);
ATF_REQUIRE(fd >= 0);
ATF_REQUIRE(pathl != NULL);
ATF_REQUIRE(stat(path, &sa) == 0);
ATF_REQUIRE(link(path, pathl) == 0);
ATF_REQUIRE(stat(path, &sb) == 0);
if (sa.st_nlink != sb.st_nlink - 1)
atf_tc_fail("incorrect link(2) count");
ATF_REQUIRE(close(fd) == 0);
ATF_REQUIRE(unlink(path) == 0);
ATF_REQUIRE(unlink(pathl) == 0);
}
ATF_TC_CLEANUP(link_count, tc)
{
(void)unlink(path);
(void)unlink(pathl);
}
ATF_TC_WITH_CLEANUP(link_err);
ATF_TC_HEAD(link_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test error conditions of link(2)");
}
ATF_TC_BODY(link_err, tc)
{
char buf[MAXPATHLEN + 1];
int fd;
(void)memset(buf, 'x', sizeof(buf));
pathl = getpath();
fd = open(path, O_RDWR | O_CREAT, 0600);
ATF_REQUIRE(fd >= 0);
ATF_REQUIRE(pathl != NULL);
errno = 0;
ATF_REQUIRE(link(path, pathl) == 0);
ATF_REQUIRE_ERRNO(EEXIST, link(path, pathl) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENAMETOOLONG, link(buf, "xxx") == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENOENT, link(path, "/d/c/b/a") == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENOENT, link("/a/b/c/d", path) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENOENT, link("/a/b/c/d", "/d/c/b/a") == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, link(path, (const char *)-1) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, link((const char *)-1, "xxx") == -1);
ATF_REQUIRE(close(fd) == 0);
ATF_REQUIRE(unlink(path) == 0);
ATF_REQUIRE(unlink(pathl) == 0);
}
ATF_TC_CLEANUP(link_err, tc)
{
(void)unlink(path);
(void)unlink(pathl);
}
ATF_TC(link_perm);
ATF_TC_HEAD(link_perm, tc)
{
atf_tc_set_md_var(tc, "descr", "Test permissions with link(2)");
atf_tc_set_md_var(tc, "require.user", "unprivileged");
}
ATF_TC_BODY(link_perm, tc)
{
errno =0;
ATF_REQUIRE_ERRNO(EACCES, link("/root", "/root.link") == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EACCES,
link("/root/.profile", "/root/.profile.link") == -1);
}
ATF_TC_WITH_CLEANUP(link_stat);
ATF_TC_HEAD(link_stat, tc)
{
atf_tc_set_md_var(tc, "descr", "Check stat(2) of a linked file");
}
ATF_TC_BODY(link_stat, tc)
{
struct stat sa, sb;
int fd;
(void)memset(&sa, 0, sizeof(struct stat));
(void)memset(&sb, 0, sizeof(struct stat));
pathl = getpath();
fd = open(path, O_RDWR | O_CREAT, 0600);
ATF_REQUIRE(fd >= 0);
ATF_REQUIRE(pathl != NULL);
ATF_REQUIRE(link(path, pathl) == 0);
ATF_REQUIRE(stat(path, &sa) == 0);
ATF_REQUIRE(lstat(pathl, &sb) == 0);
if (sa.st_uid != sb.st_uid)
atf_tc_fail("unequal UIDs");
if (sa.st_mode != sb.st_mode)
atf_tc_fail("unequal modes");
if (sa.st_ino != sb.st_ino)
atf_tc_fail("unequal inodes");
ATF_REQUIRE(close(fd) == 0);
ATF_REQUIRE(unlink(path) == 0);
ATF_REQUIRE(unlink(pathl) == 0);
}
ATF_TC_CLEANUP(link_stat, tc)
{
(void)unlink(path);
(void)unlink(pathl);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, link_count);
ATF_TP_ADD_TC(tp, link_err);
ATF_TP_ADD_TC(tp, link_perm);
ATF_TP_ADD_TC(tp, link_stat);
return atf_no_error();
}

View File

@ -0,0 +1,189 @@
/* $NetBSD: t_mincore.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_mincore.c,v 1.1 2011/07/07 06:57:53 jruoho Exp $");
#include <sys/mman.h>
#include <atf-c.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
static long page = 0;
static const char path[] = "mincore";
ATF_TC(mincore_err);
ATF_TC_HEAD(mincore_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test errors from mincore(2)");
}
ATF_TC_BODY(mincore_err, tc)
{
char *map, *vec;
map = mmap(NULL, page, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
vec = malloc(page);
ATF_REQUIRE(vec != NULL);
ATF_REQUIRE(map != MAP_FAILED);
errno = 0;
ATF_REQUIRE_ERRNO(EINVAL, mincore(map, 0, vec) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENOMEM, mincore(0, page, vec) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, mincore(map, page, (void *)-1) == -1);
free(vec);
ATF_REQUIRE(munmap(map, page) == 0);
}
ATF_TC_WITH_CLEANUP(mincore_incore);
ATF_TC_HEAD(mincore_incore, tc)
{
atf_tc_set_md_var(tc, "descr", "Test that mincore(2) works");
}
ATF_TC_BODY(mincore_incore, tc)
{
char *buf, *vec, *map = MAP_FAILED;
const char *str = NULL;
const size_t n = 3;
ssize_t tot;
int fd, rv;
size_t i, j;
/*
* Create a temporary file, write
* few pages to it, and map the file.
*/
buf = calloc(n, page);
vec = calloc(n, page);
if (buf == NULL || vec == NULL)
return;
for (i = 0; i < (size_t)page * n; i++)
buf[i] = 'x';
fd = open(path, O_RDWR | O_CREAT, 0600);
if (fd < 0) {
str = "failed to open";
goto out;
}
tot = 0;
while (tot < page * (long)n) {
rv = write(fd, buf, sizeof(buf));
if (rv < 0) {
str = "failed to write";
goto out;
}
tot += rv;
}
map = mmap(NULL, page * n, PROT_READ | PROT_WRITE,
MAP_FILE | MAP_PRIVATE, fd, 0);
if (map == MAP_FAILED) {
str = "failed to map";
goto out;
}
/*
* Lock the mapping such that only
* in-core page status is returned.
*/
if (mlock(map, page * n) != 0) {
str = "failed to lock";
goto out;
}
if (mincore(map, page * n, vec) != 0) {
str = "mincore failed";
goto out;
}
/*
* Check that the in-core pages
* match the locked pages.
*/
for (i = j = 0; i < (size_t)page * n; i++) {
if (vec[i] != 0)
j++;
}
if (j != n)
str = "mismatch of in-core pages";
out:
free(buf);
free(vec);
(void)close(fd);
(void)unlink(path);
if (map != MAP_FAILED) {
(void)munlock(map, page);
(void)munmap(map, page);
}
if (str != NULL)
atf_tc_fail("%s", str);
}
ATF_TC_CLEANUP(mincore_incore, tc)
{
(void)unlink(path);
}
ATF_TP_ADD_TCS(tp)
{
page = sysconf(_SC_PAGESIZE);
ATF_REQUIRE(page >= 0);
ATF_TP_ADD_TC(tp, mincore_err);
ATF_TP_ADD_TC(tp, mincore_incore);
return atf_no_error();
}

View File

@ -0,0 +1,280 @@
/* $NetBSD: t_mkfifo.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_mkfifo.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
#include <sys/stat.h>
#include <sys/wait.h>
#include <atf-c.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
static const char path[] = "fifo";
static void support(void);
static void
support(void)
{
errno = 0;
if (mkfifo(path, 0600) == 0) {
ATF_REQUIRE(unlink(path) == 0);
return;
}
if (errno == EOPNOTSUPP)
atf_tc_skip("the kernel does not support FIFOs");
else {
atf_tc_fail("mkfifo(2) failed");
}
}
ATF_TC_WITH_CLEANUP(mkfifo_block);
ATF_TC_HEAD(mkfifo_block, tc)
{
atf_tc_set_md_var(tc, "descr", "Test that FIFOs block");
}
ATF_TC_BODY(mkfifo_block, tc)
{
int fd[2], sta;
pid_t pid;
support();
fd[0] = fd[1] = -1;
ATF_REQUIRE(mkfifo(path, 0600) == 0);
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
/*
* If we open the FIFO as read-only (write-only),
* the call should block until another process
* opens the FIFO for writing (reading).
*/
fd[0] = open(path, O_RDONLY);
(void)pause();
_exit(EXIT_SUCCESS); /* NOTREACHED */
}
(void)sleep(1);
fd[1] = open(path, O_WRONLY);
ATF_REQUIRE(kill(pid, SIGKILL) == 0);
(void)wait(&sta);
if (WIFSIGNALED(sta) == 0 || WTERMSIG(sta) != SIGKILL)
atf_tc_fail("FIFO did not block");
(void)close(fd[0]);
(void)unlink(path);
}
ATF_TC_CLEANUP(mkfifo_block, tc)
{
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(mkfifo_err);
ATF_TC_HEAD(mkfifo_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test erros from mkfifo(2)");
}
ATF_TC_BODY(mkfifo_err, tc)
{
char buf[PATH_MAX + 1];
support();
(void)memset(buf, 'x', sizeof(buf));
ATF_REQUIRE(mkfifo(path, 0600) == 0);
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, mkfifo((char *)-1, 0600) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EEXIST, mkfifo("/etc/passwd", 0600) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EEXIST, mkfifo(path, 0600) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENAMETOOLONG, mkfifo(buf, 0600) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENOENT, mkfifo("/a/b/c/d/e/f/g", 0600) == -1);
ATF_REQUIRE(unlink(path) == 0);
}
ATF_TC_CLEANUP(mkfifo_err, tc)
{
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(mkfifo_nonblock);
ATF_TC_HEAD(mkfifo_nonblock, tc)
{
atf_tc_set_md_var(tc, "descr", "Test O_NONBLOCK with FIFOs");
}
ATF_TC_BODY(mkfifo_nonblock, tc)
{
int fd, sta;
pid_t pid;
support();
fd = -1;
ATF_REQUIRE(mkfifo(path, 0600) == 0);
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
/*
* If we open the FIFO as O_NONBLOCK, the O_RDONLY
* call should return immediately, whereas the call
* for write-only should fail with ENXIO.
*/
fd = open(path, O_RDONLY | O_NONBLOCK);
if (fd >= 0)
_exit(EXIT_SUCCESS);
(void)pause(); /* NOTREACHED */
}
(void)sleep(1);
errno = 0;
ATF_REQUIRE_ERRNO(ENXIO, open(path, O_WRONLY | O_NONBLOCK) == -1);
(void)kill(pid, SIGKILL);
(void)wait(&sta);
if (WIFSIGNALED(sta) != 0 || WTERMSIG(sta) == SIGKILL)
atf_tc_fail("FIFO blocked for O_NONBLOCK open(2)");
(void)close(fd);
(void)unlink(path);
}
ATF_TC_CLEANUP(mkfifo_nonblock, tc)
{
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(mkfifo_perm);
ATF_TC_HEAD(mkfifo_perm, tc)
{
atf_tc_set_md_var(tc, "descr", "Test permissions with mkfifo(2)");
atf_tc_set_md_var(tc, "require.user", "unprivileged");
}
ATF_TC_BODY(mkfifo_perm, tc)
{
support();
errno = 0;
ATF_REQUIRE_ERRNO(EACCES, mkfifo("/root/fifo", 0600) == -1);
ATF_REQUIRE(mkfifo(path, 0600) == 0);
/*
* For some reason this fails with EFTYPE...
*/
errno = 0;
ATF_REQUIRE_ERRNO(EFTYPE, chmod(path, 1777) == -1);
ATF_REQUIRE(unlink(path) == 0);
}
ATF_TC_CLEANUP(mkfifo_perm, tc)
{
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(mkfifo_stat);
ATF_TC_HEAD(mkfifo_stat, tc)
{
atf_tc_set_md_var(tc, "descr", "Test mkfifo(2) with stat");
}
ATF_TC_BODY(mkfifo_stat, tc)
{
struct stat st;
support();
(void)memset(&st, 0, sizeof(struct stat));
ATF_REQUIRE(mkfifo(path, 0600) == 0);
ATF_REQUIRE(stat(path, &st) == 0);
if (S_ISFIFO(st.st_mode) == 0)
atf_tc_fail("invalid mode from mkfifo(2)");
ATF_REQUIRE(unlink(path) == 0);
}
ATF_TC_CLEANUP(mkfifo_stat, tc)
{
(void)unlink(path);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, mkfifo_block);
ATF_TP_ADD_TC(tp, mkfifo_err);
ATF_TP_ADD_TC(tp, mkfifo_nonblock);
ATF_TP_ADD_TC(tp, mkfifo_perm);
ATF_TP_ADD_TC(tp, mkfifo_stat);
return atf_no_error();
}

View File

@ -0,0 +1,194 @@
/* $NetBSD: t_mknod.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_mknod.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
#include <sys/stat.h>
#include <atf-c.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <paths.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static char path[] = "node";
ATF_TC_WITH_CLEANUP(mknod_err);
ATF_TC_HEAD(mknod_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test error conditions of mknod(2)");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(mknod_err, tc)
{
char buf[PATH_MAX + 1];
(void)memset(buf, 'x', sizeof(buf));
/*
* See the old PR kern/45111.
*/
errno = 0;
ATF_REQUIRE_ERRNO(EINVAL, mknod(path, S_IFCHR, -1) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENAMETOOLONG, mknod(buf, S_IFCHR, 0) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, mknod((char *)-1, S_IFCHR, 0) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENOENT, mknod("/a/b/c/d/e/f/g", S_IFCHR, 0) == -1);
}
ATF_TC_CLEANUP(mknod_err, tc)
{
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(mknod_exist);
ATF_TC_HEAD(mknod_exist, tc)
{
atf_tc_set_md_var(tc, "descr", "Test EEXIST from mknod(2)");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(mknod_exist, tc)
{
int fd;
fd = open("/etc/passwd", O_RDONLY);
if (fd >= 0) {
(void)close(fd);
errno = 0;
ATF_REQUIRE_ERRNO(EEXIST,
mknod("/etc/passwd", S_IFCHR, 0) == -1);
}
ATF_REQUIRE(mknod(path, S_IFCHR, 0) == 0);
errno = 0;
ATF_REQUIRE_ERRNO(EEXIST, mknod(path, S_IFCHR, 0) == -1);
ATF_REQUIRE(unlink(path) == 0);
}
ATF_TC_CLEANUP(mknod_exist, tc)
{
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(mknod_perm);
ATF_TC_HEAD(mknod_perm, tc)
{
atf_tc_set_md_var(tc, "descr", "Test permissions of mknod(2)");
atf_tc_set_md_var(tc, "require.user", "unprivileged");
}
ATF_TC_BODY(mknod_perm, tc)
{
errno = 0;
ATF_REQUIRE_ERRNO(EPERM, mknod(path, S_IFCHR, 0) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EPERM, mknod(path, S_IFBLK, 0) == -1);
}
ATF_TC_CLEANUP(mknod_perm, tc)
{
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(mknod_stat);
ATF_TC_HEAD(mknod_stat, tc)
{
atf_tc_set_md_var(tc, "descr", "A basic test of mknod(2)");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(mknod_stat, tc)
{
struct stat st;
(void)memset(&st, 0, sizeof(struct stat));
ATF_REQUIRE(mknod(path, S_IFCHR, 0) == 0);
ATF_REQUIRE(stat(path, &st) == 0);
if (S_ISCHR(st.st_mode) == 0)
atf_tc_fail_nonfatal("invalid mode from mknod(2) (S_IFCHR)");
ATF_REQUIRE(unlink(path) == 0);
(void)memset(&st, 0, sizeof(struct stat));
ATF_REQUIRE(mknod(path, S_IFBLK, 0) == 0);
ATF_REQUIRE(stat(path, &st) == 0);
if (S_ISBLK(st.st_mode) == 0)
atf_tc_fail_nonfatal("invalid mode from mknod(2) (S_IFBLK)");
ATF_REQUIRE(unlink(path) == 0);
(void)memset(&st, 0, sizeof(struct stat));
ATF_REQUIRE(mknod(path, S_IFREG, 0) == 0);
ATF_REQUIRE(stat(path, &st) == 0);
if (S_ISREG(st.st_mode) == 0)
atf_tc_fail_nonfatal("invalid mode from mknod(2) (S_IFREG)");
ATF_REQUIRE(unlink(path) == 0);
}
ATF_TC_CLEANUP(mknod_stat, tc)
{
(void)unlink(path);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, mknod_err);
ATF_TP_ADD_TC(tp, mknod_exist);
ATF_TP_ADD_TC(tp, mknod_perm);
ATF_TP_ADD_TC(tp, mknod_stat);
return atf_no_error();
}

322
tests/lib/libc/sys/t_mmap.c Normal file
View File

@ -0,0 +1,322 @@
/* $NetBSD: t_mmap.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_mmap.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
#include <sys/param.h>
#include <sys/mman.h>
#include <sys/sysctl.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <atf-c.h>
static long page = 0;
static char path[] = "mmap";
static void map_check(void *, int);
static void map_sighandler(int);
static void
map_check(void *map, int flag)
{
if (flag != 0) {
ATF_REQUIRE(map == MAP_FAILED);
return;
}
ATF_REQUIRE(map != MAP_FAILED);
ATF_REQUIRE(munmap(map, page) == 0);
}
static void
map_sighandler(int signo)
{
_exit(signo);
}
ATF_TC(mmap_err);
ATF_TC_HEAD(mmap_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test error conditions of mmap(2)");
}
ATF_TC_BODY(mmap_err, tc)
{
size_t addr = SIZE_MAX;
void *map;
errno = 0;
map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, -1, 0);
ATF_REQUIRE(map == MAP_FAILED);
ATF_REQUIRE(errno == EBADF);
errno = 0;
map = mmap(&addr, page, PROT_READ, MAP_FIXED|MAP_PRIVATE, -1, 0);
ATF_REQUIRE(map == MAP_FAILED);
ATF_REQUIRE(errno == EINVAL);
errno = 0;
map = mmap(NULL, page, PROT_READ, MAP_ANON|MAP_PRIVATE, INT_MAX, 0);
ATF_REQUIRE(map == MAP_FAILED);
ATF_REQUIRE(errno == EINVAL);
}
ATF_TC_WITH_CLEANUP(mmap_prot_1);
ATF_TC_HEAD(mmap_prot_1, tc)
{
atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #1");
}
ATF_TC_BODY(mmap_prot_1, tc)
{
void *map;
int fd;
/*
* Open a file write-only and try to
* map it read-only. This should fail.
*/
fd = open(path, O_WRONLY | O_CREAT, 0700);
if (fd < 0)
return;
ATF_REQUIRE(write(fd, "XXX", 3) == 3);
map = mmap(NULL, 3, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0);
map_check(map, 1);
map = mmap(NULL, 3, PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd, 0);
map_check(map, 0);
ATF_REQUIRE(close(fd) == 0);
}
ATF_TC_CLEANUP(mmap_prot_1, tc)
{
(void)unlink(path);
}
ATF_TC(mmap_prot_2);
ATF_TC_HEAD(mmap_prot_2, tc)
{
atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #2");
}
ATF_TC_BODY(mmap_prot_2, tc)
{
char buf[2];
void *map;
pid_t pid;
int sta;
/*
* Make a PROT_NONE mapping and try to access it.
* If we catch a SIGSEGV, all works as expected.
*/
map = mmap(NULL, page, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0);
ATF_REQUIRE(map != MAP_FAILED);
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0);
}
(void)wait(&sta);
ATF_REQUIRE(WIFEXITED(sta) != 0);
ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
ATF_REQUIRE(munmap(map, page) == 0);
}
ATF_TC_WITH_CLEANUP(mmap_prot_3);
ATF_TC_HEAD(mmap_prot_3, tc)
{
atf_tc_set_md_var(tc, "descr", "Test mmap(2) protections, #3");
}
ATF_TC_BODY(mmap_prot_3, tc)
{
char buf[2];
int fd, sta;
void *map;
pid_t pid;
/*
* Open a file, change the permissions
* to read-only, and try to map it as
* PROT_NONE. This should succeed, but
* the access should generate SIGSEGV.
*/
fd = open(path, O_RDWR | O_CREAT, 0700);
if (fd < 0)
return;
ATF_REQUIRE(write(fd, "XXX", 3) == 3);
ATF_REQUIRE(close(fd) == 0);
ATF_REQUIRE(chmod(path, 0444) == 0);
fd = open(path, O_RDONLY);
ATF_REQUIRE(fd != -1);
map = mmap(NULL, 3, PROT_NONE, MAP_FILE | MAP_SHARED, fd, 0);
ATF_REQUIRE(map != MAP_FAILED);
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
ATF_REQUIRE(signal(SIGSEGV, map_sighandler) != SIG_ERR);
ATF_REQUIRE(strlcpy(buf, map, sizeof(buf)) != 0);
}
(void)wait(&sta);
ATF_REQUIRE(WIFEXITED(sta) != 0);
ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
ATF_REQUIRE(munmap(map, 3) == 0);
}
ATF_TC_CLEANUP(mmap_prot_3, tc)
{
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(mmap_truncate);
ATF_TC_HEAD(mmap_truncate, tc)
{
atf_tc_set_md_var(tc, "descr", "Test mmap(2) and ftruncate(2)");
}
ATF_TC_BODY(mmap_truncate, tc)
{
char *map;
long i;
int fd;
fd = open(path, O_RDWR | O_CREAT, 0700);
if (fd < 0)
return;
/*
* See that ftruncate(2) works
* while the file is mapped.
*/
ATF_REQUIRE(ftruncate(fd, page) == 0);
map = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_FILE|MAP_PRIVATE,
fd, 0);
ATF_REQUIRE(map != MAP_FAILED);
for (i = 0; i < page; i++)
map[i] = 'x';
ATF_REQUIRE(ftruncate(fd, 0) == 0);
ATF_REQUIRE(ftruncate(fd, page / 8) == 0);
ATF_REQUIRE(ftruncate(fd, page / 4) == 0);
ATF_REQUIRE(ftruncate(fd, page / 2) == 0);
ATF_REQUIRE(ftruncate(fd, page / 12) == 0);
ATF_REQUIRE(ftruncate(fd, page / 64) == 0);
ATF_REQUIRE(close(fd) == 0);
}
ATF_TC_CLEANUP(mmap_truncate, tc)
{
(void)unlink(path);
}
ATF_TC(mmap_va0);
ATF_TC_HEAD(mmap_va0, tc)
{
atf_tc_set_md_var(tc, "descr", "Test mmap(2) and vm.user_va0_disable");
}
ATF_TC_BODY(mmap_va0, tc)
{
int flags = MAP_ANON | MAP_FIXED | MAP_PRIVATE;
size_t len = sizeof(int);
void *map;
int val;
/*
* Make an anonymous fixed mapping at zero address. If the address
* is restricted as noted in security(7), the syscall should fail.
*/
if (sysctlbyname("vm.user_va0_disable", &val, &len, NULL, 0) != 0)
atf_tc_fail("failed to read vm.user_va0_disable");
map = mmap(NULL, page, PROT_EXEC, flags, -1, 0);
map_check(map, val);
map = mmap(NULL, page, PROT_READ, flags, -1, 0);
map_check(map, val);
map = mmap(NULL, page, PROT_WRITE, flags, -1, 0);
map_check(map, val);
map = mmap(NULL, page, PROT_READ|PROT_WRITE, flags, -1, 0);
map_check(map, val);
map = mmap(NULL, page, PROT_EXEC|PROT_READ|PROT_WRITE, flags, -1, 0);
map_check(map, val);
}
ATF_TP_ADD_TCS(tp)
{
page = sysconf(_SC_PAGESIZE);
ATF_REQUIRE(page >= 0);
ATF_TP_ADD_TC(tp, mmap_err);
ATF_TP_ADD_TC(tp, mmap_prot_1);
ATF_TP_ADD_TC(tp, mmap_prot_2);
ATF_TP_ADD_TC(tp, mmap_prot_3);
ATF_TP_ADD_TC(tp, mmap_truncate);
ATF_TP_ADD_TC(tp, mmap_va0);
return atf_no_error();
}

View File

@ -0,0 +1,273 @@
/* $NetBSD: t_mprotect.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_mprotect.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
#include <sys/param.h>
#include <sys/mman.h>
#include <sys/sysctl.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <atf-c.h>
static long page = 0;
static int pax_global = -1;
static int pax_enabled = -1;
static char path[] = "mmap";
static void sighandler(int);
static bool paxinit(void);
static bool paxset(int, int);
static void
sighandler(int signo)
{
_exit(signo);
}
static bool
paxinit(void)
{
size_t len = sizeof(int);
int rv;
rv = sysctlbyname("security.pax.mprotect.global",
&pax_global, &len, NULL, 0);
if (rv != 0)
return false;
rv = sysctlbyname("security.pax.mprotect.enabled",
&pax_enabled, &len, NULL, 0);
if (rv != 0)
return false;
return paxset(1, 1);
}
static bool
paxset(int global, int enabled)
{
size_t len = sizeof(int);
int rv;
rv = sysctlbyname("security.pax.mprotect.global",
NULL, NULL, &global, len);
if (rv != 0)
return false;
rv = sysctlbyname("security.pax.mprotect.enabled",
NULL, NULL, &enabled, len);
if (rv != 0)
return false;
return true;
}
ATF_TC_WITH_CLEANUP(mprotect_access);
ATF_TC_HEAD(mprotect_access, tc)
{
atf_tc_set_md_var(tc, "descr", "Test for EACCES from mprotect(2)");
}
ATF_TC_BODY(mprotect_access, tc)
{
int prot[2] = { PROT_NONE, PROT_READ };
void *map;
size_t i;
int fd;
fd = open(path, O_RDONLY | O_CREAT);
ATF_REQUIRE(fd >= 0);
/*
* The call should fail with EACCES if we try to mark
* a PROT_NONE or PROT_READ file/section as PROT_WRITE.
*/
for (i = 0; i < __arraycount(prot); i++) {
map = mmap(NULL, page, prot[i], MAP_SHARED, fd, 0);
if (map == MAP_FAILED)
continue;
errno = 0;
ATF_REQUIRE(mprotect(map, page, PROT_WRITE) != 0);
ATF_REQUIRE(errno == EACCES);
ATF_REQUIRE(munmap(map, page) == 0);
}
ATF_REQUIRE(close(fd) == 0);
}
ATF_TC_CLEANUP(mprotect_access, tc)
{
(void)unlink(path);
}
ATF_TC(mprotect_err);
ATF_TC_HEAD(mprotect_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test error conditions of mprotect(2)");
}
ATF_TC_BODY(mprotect_err, tc)
{
errno = 0;
ATF_REQUIRE(mprotect((char *)-1, 1, PROT_READ) != 0);
ATF_REQUIRE(errno == EINVAL);
}
ATF_TC(mprotect_pax);
ATF_TC_HEAD(mprotect_pax, tc)
{
atf_tc_set_md_var(tc, "descr", "PaX restrictions and mprotect(2),");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(mprotect_pax, tc)
{
const int prot[4] = { PROT_NONE, PROT_READ, PROT_WRITE };
const char *str = NULL;
void *map;
size_t i;
int rv;
if (paxinit() != true)
return;
/*
* As noted in the original PaX documentation [1],
* the following restrictions should apply:
*
* (1) creating executable anonymous mappings
*
* (2) creating executable/writable file mappings
*
* (3) making a non-executable mapping executable
*
* (4) making an executable/read-only file mapping
* writable except for performing relocations
* on an ET_DYN ELF file (non-PIC shared library)
*
* The following will test only the case (3).
*
* [1] http://pax.grsecurity.net/docs/mprotect.txt
*
* (Sun Apr 3 11:06:53 EEST 2011.)
*/
for (i = 0; i < __arraycount(prot); i++) {
map = mmap(NULL, page, prot[i], MAP_ANON, -1, 0);
if (map == MAP_FAILED)
continue;
rv = mprotect(map, 1, prot[i] | PROT_EXEC);
(void)munmap(map, page);
if (rv == 0) {
str = "non-executable mapping made executable";
goto out;
}
}
out:
if (pax_global != -1 && pax_enabled != -1)
(void)paxset(pax_global, pax_enabled);
if (str != NULL)
atf_tc_fail("%s", str);
}
ATF_TC(mprotect_write);
ATF_TC_HEAD(mprotect_write, tc)
{
atf_tc_set_md_var(tc, "descr", "Test mprotect(2) protections");
}
ATF_TC_BODY(mprotect_write, tc)
{
pid_t pid;
void *map;
int sta;
/*
* Map a page read/write, change the protection
* to read-only with mprotect(2), and try to write
* to the page. This should generate a SIGSEGV.
*/
map = mmap(NULL, page, PROT_WRITE|PROT_READ, MAP_ANON, -1, 0);
ATF_REQUIRE(map != MAP_FAILED);
ATF_REQUIRE(strlcpy(map, "XXX", 3) == 3);
ATF_REQUIRE(mprotect(map, page, PROT_READ) == 0);
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
ATF_REQUIRE(signal(SIGSEGV, sighandler) != SIG_ERR);
ATF_REQUIRE(strlcpy(map, "XXX", 3) == 0);
}
(void)wait(&sta);
ATF_REQUIRE(WIFEXITED(sta) != 0);
ATF_REQUIRE(WEXITSTATUS(sta) == SIGSEGV);
ATF_REQUIRE(munmap(map, page) == 0);
}
ATF_TP_ADD_TCS(tp)
{
page = sysconf(_SC_PAGESIZE);
ATF_REQUIRE(page >= 0);
ATF_TP_ADD_TC(tp, mprotect_access);
ATF_TP_ADD_TC(tp, mprotect_err);
ATF_TP_ADD_TC(tp, mprotect_pax);
ATF_TP_ADD_TC(tp, mprotect_write);
return atf_no_error();
}

View File

@ -0,0 +1,226 @@
/* $NetBSD: t_msync.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_msync.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
#include <sys/mman.h>
#include <atf-c.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static long page = 0;
static const off_t off = 512;
static const char path[] = "msync";
static const char *msync_sync(const char *, int);
static const char *
msync_sync(const char *garbage, int flags)
{
char *buf, *map = MAP_FAILED;
const char *str = NULL;
size_t i, len;
ssize_t tot;
int fd, rv;
/*
* Create a temporary file, write
* one page to it, and map the file.
*/
buf = malloc(page);
if (buf == NULL)
return NULL;
for (i = 0; i < (size_t)page; i++)
buf[i] = 'x';
fd = open(path, O_RDWR | O_CREAT, 0700);
if (fd < 0) {
str = "failed to open";
goto out;
}
tot = 0;
while (tot < page) {
rv = write(fd, buf, sizeof(buf));
if (rv < 0) {
str = "failed to write";
goto out;
}
tot += rv;
}
map = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_FILE|MAP_PRIVATE,
fd, 0);
if (map == MAP_FAILED) {
str = "failed to map";
goto out;
}
/*
* Seek to an arbitrary offset and
* write garbage to this position.
*/
if (lseek(fd, off, SEEK_SET) != off) {
str = "failed to seek";
goto out;
}
len = strlen(garbage);
rv = write(fd, garbage, len);
if (rv != (ssize_t)len) {
str = "failed to write garbage";
goto out;
}
/*
* Synchronize the mapping and verify
* that garbage is at the given offset.
*/
if (msync(map, page, flags) != 0) {
str = "failed to msync";
goto out;
}
if (memcmp(map + off, garbage, len) != 0) {
str = "msync did not synchronize";
goto out;
}
out:
free(buf);
(void)close(fd);
(void)unlink(path);
if (map != MAP_FAILED)
(void)munmap(map, page);
return str;
}
ATF_TC(msync_async);
ATF_TC_HEAD(msync_async, tc)
{
atf_tc_set_md_var(tc, "descr", "Test of msync(2), MS_ASYNC");
}
ATF_TC_BODY(msync_async, tc)
{
const char *str;
str = msync_sync("garbage", MS_ASYNC);
if (str != NULL)
atf_tc_fail("%s", str);
}
ATF_TC(msync_err);
ATF_TC_HEAD(msync_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test error conditions in msync(2)");
}
ATF_TC_BODY(msync_err, tc)
{
/*
* Test that invalid flags error out.
*/
ATF_REQUIRE(msync_sync("error", -1) != NULL);
ATF_REQUIRE(msync_sync("error", INT_MAX) != NULL);
errno = 0;
ATF_REQUIRE(msync((void *)INT_MAX, page, MS_SYNC) != 0);
ATF_REQUIRE(errno == EFAULT);
}
ATF_TC(msync_invalidate);
ATF_TC_HEAD(msync_invalidate, tc)
{
atf_tc_set_md_var(tc, "descr", "Test of msync(2), MS_INVALIDATE");
}
ATF_TC_BODY(msync_invalidate, tc)
{
const char *str;
str = msync_sync("garbage", MS_INVALIDATE);
if (str != NULL)
atf_tc_fail("%s", str);
}
ATF_TC(msync_sync);
ATF_TC_HEAD(msync_sync, tc)
{
atf_tc_set_md_var(tc, "descr", "Test of msync(2), MS_SYNC");
}
ATF_TC_BODY(msync_sync, tc)
{
const char *str;
str = msync_sync("garbage", MS_SYNC);
if (str != NULL)
atf_tc_fail("%s", str);
}
ATF_TP_ADD_TCS(tp)
{
page = sysconf(_SC_PAGESIZE);
ATF_REQUIRE(page >= 0);
ATF_REQUIRE(page > off);
ATF_TP_ADD_TC(tp, msync_async);
ATF_TP_ADD_TC(tp, msync_err);
ATF_TP_ADD_TC(tp, msync_invalidate);
ATF_TP_ADD_TC(tp, msync_sync);
return atf_no_error();
}

View File

@ -0,0 +1,177 @@
/* $NetBSD: t_nanosleep.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_nanosleep.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
#include <sys/time.h>
#include <sys/wait.h>
#include <atf-c.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
static void
handler(int signo)
{
/* Nothing. */
}
ATF_TC(nanosleep_basic);
ATF_TC_HEAD(nanosleep_basic, tc)
{
atf_tc_set_md_var(tc, "descr", "Test that nanosleep(2) works");
}
ATF_TC_BODY(nanosleep_basic, tc)
{
static const size_t maxiter = 10;
struct timespec ts1, ts2, tsn;
size_t i;
for (i = 1; i < maxiter; i++) {
tsn.tv_sec = 0;
tsn.tv_nsec = i;
(void)memset(&ts1, 0, sizeof(struct timespec));
(void)memset(&ts2, 0, sizeof(struct timespec));
ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts1) == 0);
ATF_REQUIRE(nanosleep(&tsn, NULL) == 0);
ATF_REQUIRE(clock_gettime(CLOCK_MONOTONIC, &ts2) == 0);
/*
* Verify that we slept at least one nanosecond.
*/
if (timespeccmp(&ts2, &ts1, <=) != 0) {
(void)fprintf(stderr,
"sleep time:: sec %llu, nsec %lu\n\t\t"
"ts1: sec %llu, nsec %lu\n\t\t"
"ts2: sec %llu, nsec %lu\n",
(unsigned long long)tsn.tv_sec, tsn.tv_nsec,
(unsigned long long)ts1.tv_sec, ts1.tv_nsec,
(unsigned long long)ts2.tv_sec, ts2.tv_nsec);
atf_tc_fail_nonfatal("inaccuracies in sleep time "
"(resolution = %lu nsec)", tsn.tv_nsec);
}
}
}
ATF_TC(nanosleep_err);
ATF_TC_HEAD(nanosleep_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test errors from nanosleep(2)");
}
ATF_TC_BODY(nanosleep_err, tc)
{
struct timespec ts;
ts.tv_sec = -1;
ts.tv_nsec = 1000;
errno = 0;
ATF_REQUIRE_ERRNO(EINVAL, nanosleep(&ts, NULL) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, nanosleep((void *)-1, NULL) == -1);
}
ATF_TC(nanosleep_sig);
ATF_TC_HEAD(nanosleep_sig, tc)
{
atf_tc_set_md_var(tc, "descr", "Test signal for nanosleep(2)");
}
ATF_TC_BODY(nanosleep_sig, tc)
{
struct timespec tsn, tsr;
pid_t pid;
int sta;
/*
* Test that a signal interrupts nanosleep(2).
*
* (In which case the return value should be -1 and the
* second parameter should contain the unslept time.)
*/
pid = fork();
ATF_REQUIRE(pid >= 0);
ATF_REQUIRE(signal(SIGINT, handler) == 0);
if (pid == 0) {
tsn.tv_sec = 10;
tsn.tv_nsec = 0;
tsr.tv_sec = 0;
tsr.tv_nsec = 0;
errno = 0;
if (nanosleep(&tsn, &tsr) != -1)
_exit(EXIT_FAILURE);
if (errno != EINTR)
_exit(EXIT_FAILURE);
if (tsr.tv_sec == 0 && tsr.tv_nsec == 0)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)sleep(1);
(void)kill(pid, SIGINT);
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("signal did not interrupt nanosleep(2)");
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, nanosleep_basic);
ATF_TP_ADD_TC(tp, nanosleep_err);
ATF_TP_ADD_TC(tp, nanosleep_sig);
return atf_no_error();
}

287
tests/lib/libc/sys/t_poll.c Normal file
View File

@ -0,0 +1,287 @@
/* $NetBSD: t_poll.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Matthias Scheler.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/time.h>
#include <atf-c.h>
#include <errno.h>
#include <fcntl.h>
#include <paths.h>
#include <poll.h>
#include <signal.h>
#include <unistd.h>
ATF_TC(poll_basic);
ATF_TC_HEAD(poll_basic, tc)
{
atf_tc_set_md_var(tc, "timeout", "10");
atf_tc_set_md_var(tc, "descr",
"Basis functionality test for poll(2)");
}
ATF_TC_BODY(poll_basic, tc)
{
int fds[2];
struct pollfd pfds[2];
int ret;
ATF_REQUIRE_EQ(pipe(fds), 0);
pfds[0].fd = fds[0];
pfds[0].events = POLLIN;
pfds[1].fd = fds[1];
pfds[1].events = POLLOUT;
/*
* Check that we get a timeout waiting for data on the read end
* of our pipe.
*/
pfds[0].revents = -1;
pfds[1].revents = -1;
ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[0], 1, 1), 0,
"got: %d", ret);
ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
/* Check that the write end of the pipe as reported as ready. */
pfds[0].revents = -1;
pfds[1].revents = -1;
ATF_REQUIRE_EQ_MSG(ret = poll(&pfds[1], 1, 1), 1,
"got: %d", ret);
ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
pfds[1].revents);
/* Check that only the write end of the pipe as reported as ready. */
pfds[0].revents = -1;
pfds[1].revents = -1;
ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 1,
"got: %d", ret);
ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
pfds[1].revents);
/* Write data to our pipe. */
ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
/* Check that both ends of our pipe are reported as ready. */
pfds[0].revents = -1;
pfds[1].revents = -1;
ATF_REQUIRE_EQ_MSG(ret = poll(pfds, 2, 1), 2,
"got: %d", ret);
ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
pfds[0].revents);
ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
pfds[1].revents);
ATF_REQUIRE_EQ(close(fds[0]), 0);
ATF_REQUIRE_EQ(close(fds[1]), 0);
}
ATF_TC(poll_err);
ATF_TC_HEAD(poll_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Check errors from poll(2)");
}
ATF_TC_BODY(poll_err, tc)
{
struct pollfd pfd;
int fd = 0;
pfd.fd = fd;
pfd.events = POLLIN;
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, poll((struct pollfd *)-1, 1, -1) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EINVAL, poll(&pfd, 1, -2) == -1);
}
ATF_TC(pollts_basic);
ATF_TC_HEAD(pollts_basic, tc)
{
atf_tc_set_md_var(tc, "timeout", "10");
atf_tc_set_md_var(tc, "descr",
"Basis functionality test for pollts(2)");
}
ATF_TC_BODY(pollts_basic, tc)
{
int fds[2];
struct pollfd pfds[2];
struct timespec timeout;
int ret;
ATF_REQUIRE_EQ(pipe(fds), 0);
pfds[0].fd = fds[0];
pfds[0].events = POLLIN;
pfds[1].fd = fds[1];
pfds[1].events = POLLOUT;
/* Use a timeout of 1 second. */
timeout.tv_sec = 1;
timeout.tv_nsec = 0;
/*
* Check that we get a timeout waiting for data on the read end
* of our pipe.
*/
pfds[0].revents = -1;
pfds[1].revents = -1;
ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[0], 1, &timeout, NULL), 0,
"got: %d", ret);
ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
ATF_REQUIRE_EQ_MSG(pfds[1].revents, -1, "got: %d", pfds[1].revents);
/* Check that the write end of the pipe as reported as ready. */
pfds[0].revents = -1;
pfds[1].revents = -1;
ATF_REQUIRE_EQ_MSG(ret = pollts(&pfds[1], 1, &timeout, NULL), 1,
"got: %d", ret);
ATF_REQUIRE_EQ_MSG(pfds[0].revents, -1, "got: %d", pfds[0].revents);
ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",\
pfds[1].revents);
/* Check that only the write end of the pipe as reported as ready. */
pfds[0].revents = -1;
pfds[1].revents = -1;
ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 1,
"got: %d", ret);
ATF_REQUIRE_EQ_MSG(pfds[0].revents, 0, "got: %d", pfds[0].revents);
ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
pfds[1].revents);
/* Write data to our pipe. */
ATF_REQUIRE_EQ(write(fds[1], "", 1), 1);
/* Check that both ends of our pipe are reported as ready. */
pfds[0].revents = -1;
pfds[1].revents = -1;
ATF_REQUIRE_EQ_MSG(ret = pollts(pfds, 2, &timeout, NULL), 2,
"got: %d", ret);
ATF_REQUIRE_EQ_MSG(pfds[0].revents, POLLIN, "got: %d",
pfds[0].revents);
ATF_REQUIRE_EQ_MSG(pfds[1].revents, POLLOUT, "got: %d",
pfds[1].revents);
ATF_REQUIRE_EQ(close(fds[0]), 0);
ATF_REQUIRE_EQ(close(fds[1]), 0);
}
ATF_TC(pollts_err);
ATF_TC_HEAD(pollts_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Check errors from pollts(2)");
}
ATF_TC_BODY(pollts_err, tc)
{
struct timespec timeout;
struct pollfd pfd;
int fd = 0;
pfd.fd = fd;
pfd.events = POLLIN;
timeout.tv_sec = 1;
timeout.tv_nsec = 0;
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, pollts((void *)-1, 1, &timeout, NULL) == -1);
timeout.tv_sec = -1;
timeout.tv_nsec = -1;
errno = 0;
ATF_REQUIRE_ERRNO(EINVAL, pollts(&pfd, 1, &timeout, NULL) == -1);
}
ATF_TC(pollts_sigmask);
ATF_TC_HEAD(pollts_sigmask, tc)
{
atf_tc_set_md_var(tc, "timeout", "10");
atf_tc_set_md_var(tc, "descr",
"Check that pollts(2) restores the signal mask");
}
ATF_TC_BODY(pollts_sigmask, tc)
{
int fd;
struct pollfd pfd;
struct timespec timeout;
sigset_t mask;
int ret;
/* Cf kern/44986 */
fd = open(_PATH_DEVNULL, O_RDONLY);
ATF_REQUIRE(fd >= 0);
pfd.fd = fd;
pfd.events = POLLIN;
/* Use a timeout of 1 second. */
timeout.tv_sec = 1;
timeout.tv_nsec = 0;
/* Unblock all signals. */
ATF_REQUIRE_EQ(sigfillset(&mask), 0);
ATF_REQUIRE_EQ(sigprocmask(SIG_UNBLOCK, &mask, NULL), 0);
/*
* Check that pollts(2) immediately returns. We block *all*
* signals during pollts(2).
*/
ATF_REQUIRE_EQ_MSG(ret = pollts(&pfd, 1, &timeout, &mask), 1,
"got: %d", ret);
/* Check that signals are now longer blocked. */
ATF_REQUIRE_EQ(sigprocmask(SIG_SETMASK, NULL, &mask), 0);
ATF_REQUIRE_EQ_MSG(sigismember(&mask, SIGUSR1), 0,
"signal mask was changed.");
ATF_REQUIRE_EQ(close(fd), 0);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, poll_basic);
ATF_TP_ADD_TC(tp, poll_err);
ATF_TP_ADD_TC(tp, pollts_basic);
ATF_TP_ADD_TC(tp, pollts_err);
ATF_TP_ADD_TC(tp, pollts_sigmask);
return atf_no_error();
}

View File

@ -0,0 +1,186 @@
/* $NetBSD: t_revoke.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_revoke.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
#include <sys/resource.h>
#include <sys/wait.h>
#include <atf-c.h>
#include <fcntl.h>
#include <errno.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static const char path[] = "revoke";
ATF_TC_WITH_CLEANUP(revoke_basic);
ATF_TC_HEAD(revoke_basic, tc)
{
atf_tc_set_md_var(tc, "descr", "A basic test of revoke(2)");
}
ATF_TC_BODY(revoke_basic, tc)
{
struct rlimit res;
char tmp[10];
size_t i, n;
int *buf;
(void)memset(&res, 0, sizeof(struct rlimit));
(void)getrlimit(RLIMIT_NOFILE, &res);
if ((n = res.rlim_cur / 10) == 0)
n = 10;
buf = calloc(n, sizeof(int));
ATF_REQUIRE(buf != NULL);
buf[0] = open(path, O_RDWR | O_CREAT, 0600);
ATF_REQUIRE(buf[0] >= 0);
for (i = 1; i < n; i++) {
buf[i] = open(path, O_RDWR);
ATF_REQUIRE(buf[i] >= 0);
}
ATF_REQUIRE(revoke(path) == 0);
for (i = 0; i < n; i++) {
ATF_REQUIRE(read(buf[i], tmp, sizeof(tmp)) == -1);
(void)close(buf[i]);
}
free(buf);
(void)unlink(path);
}
ATF_TC_CLEANUP(revoke_basic, tc)
{
(void)unlink(path);
}
ATF_TC(revoke_err);
ATF_TC_HEAD(revoke_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test errors from revoke(2)");
atf_tc_set_md_var(tc, "require.user", "unprivileged");
}
ATF_TC_BODY(revoke_err, tc)
{
char buf[1024 + 1]; /* XXX: From the manual page... */
(void)memset(buf, 'x', sizeof(buf));
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, revoke((char *)-1) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENAMETOOLONG, revoke(buf) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EPERM, revoke("/etc/passwd") == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENOENT, revoke("/etc/xxx/yyy") == -1);
}
ATF_TC_WITH_CLEANUP(revoke_perm);
ATF_TC_HEAD(revoke_perm, tc)
{
atf_tc_set_md_var(tc, "descr", "Test permissions revoke(2)");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(revoke_perm, tc)
{
struct passwd *pw;
int fd, sta;
pid_t pid;
pw = getpwnam("nobody");
fd = open(path, O_RDWR | O_CREAT, 0600);
ATF_REQUIRE(fd >= 0);
ATF_REQUIRE(pw != NULL);
ATF_REQUIRE(revoke(path) == 0);
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
if (setuid(pw->pw_uid) != 0)
_exit(EXIT_FAILURE);
errno = 0;
if (revoke(path) == 0)
_exit(EXIT_FAILURE);
if (errno != EACCES)
_exit(EXIT_FAILURE);
if (close(fd) != 0)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("revoke(2) did not obey permissions");
ATF_REQUIRE(unlink(path) == 0);
}
ATF_TC_CLEANUP(revoke_perm, tc)
{
(void)unlink(path);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, revoke_basic);
ATF_TP_ADD_TC(tp, revoke_err);
ATF_TP_ADD_TC(tp, revoke_perm);
return atf_no_error();
}

View File

@ -0,0 +1,217 @@
/* $NetBSD: t_select.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundatiom
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/wait.h>
#include <err.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <atf-c.h>
static sig_atomic_t keep_going = 1;
static void
sig_handler(int signum)
{
keep_going = 0;
}
static void
sigchld(int signum)
{
}
static char
xtoa(uint8_t n)
{
static const char xarray[] = "0123456789abcdef";
assert(n < sizeof(xarray));
return xarray[n];
}
static const char *
prmask(const sigset_t *m, char *buf, size_t len)
{
size_t j = 2;
assert(len >= 3 + sizeof(*m));
buf[0] = '0';
buf[1] = 'x';
#define N(p, a) (((p) >> ((a) * 4)) & 0xf)
for (size_t i = __arraycount(m->__bits); i > 0; i--) {
uint32_t p = m->__bits[i - 1];
for (size_t k = sizeof(p); k > 0; k--)
buf[j++] = xtoa(N(p, k - 1));
}
buf[j] = '\0';
return buf;
}
static void
child(const struct timespec *ts)
{
struct sigaction sa;
sigset_t set, oset, nset;
char obuf[sizeof(oset) + 3], nbuf[sizeof(nset) + 3];
int fd;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sig_handler;
if ((fd = open("/dev/null", O_RDONLY)) == -1)
err(1, "open");
if (sigaction(SIGTERM, &sa, NULL) == -1)
err(1, "sigaction");
sigfillset(&set);
if (sigprocmask(SIG_BLOCK, &set, NULL) == -1)
err(1, "sigprocmask");
if (sigprocmask(SIG_BLOCK, NULL, &oset) == -1)
err(1, "sigprocmask");
sigemptyset(&set);
for (;;) {
fd_set rset;
FD_ZERO(&rset);
FD_SET(fd, &rset);
if (pselect(1, &rset, NULL, NULL, ts, &set) == -1) {
if(errno == EINTR) {
if (!keep_going)
break;
}
}
if (ts)
break;
}
if (sigprocmask(SIG_BLOCK, NULL, &nset) == -1)
err(1, "sigprocmask");
if (memcmp(&oset, &nset, sizeof(oset)) != 0)
atf_tc_fail("pselect() masks don't match "
"after timeout %s != %s",
prmask(&nset, nbuf, sizeof(nbuf)),
prmask(&oset, obuf, sizeof(obuf)));
}
ATF_TC(pselect_sigmask);
ATF_TC_HEAD(pselect_sigmask, tc)
{
/* Cf. PR lib/43625. */
atf_tc_set_md_var(tc, "descr", "Checks pselect's temporary mask "
"setting when a signal is received");
}
ATF_TC_BODY(pselect_sigmask, tc)
{
pid_t pid;
int status;
signal(SIGCHLD, sigchld);
switch (pid = fork()) {
case 0:
child(NULL);
case -1:
err(1, "fork");
default:
sleep(1);
if (kill(pid, SIGTERM) == -1)
err(1, "kill");
sleep(1);
switch (waitpid(pid, &status, WNOHANG)) {
case -1:
err(1, "wait");
case 0:
if (kill(pid, SIGKILL) == -1)
err(1, "kill");
atf_tc_fail("pselect() did not receive signal");
break;
default:
break;
}
}
}
ATF_TC(pselect_timeout);
ATF_TC_HEAD(pselect_timeout, tc)
{
atf_tc_set_md_var(tc, "descr", "Checks pselect's temporary mask "
"setting when a timeout occurs");
}
ATF_TC_BODY(pselect_timeout, tc)
{
pid_t pid;
int status;
static const struct timespec zero = { 0, 0 };
signal(SIGCHLD, sigchld);
switch (pid = fork()) {
case 0:
child(&zero);
break;
case -1:
err(1, "fork");
default:
usleep(5000);
switch (waitpid(pid, &status, WNOHANG)) {
case -1:
err(1, "wait");
case 0:
if (kill(pid, SIGKILL) == -1)
err(1, "kill");
atf_tc_fail("pselect() did not receive signal");
break;
default:
break;
}
}
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, pselect_sigmask);
ATF_TP_ADD_TC(tp, pselect_timeout);
return atf_no_error();
}

View File

@ -0,0 +1,481 @@
/* $NetBSD: t_setrlimit.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_setrlimit.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
#include <sys/resource.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <atf-c.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static void sighandler(int);
static const char path[] = "setrlimit";
static const int rlimit[] = {
RLIMIT_AS,
RLIMIT_CORE,
RLIMIT_CPU,
RLIMIT_DATA,
RLIMIT_FSIZE,
RLIMIT_MEMLOCK,
RLIMIT_NOFILE,
RLIMIT_NPROC,
RLIMIT_RSS,
RLIMIT_SBSIZE,
RLIMIT_STACK
};
ATF_TC(setrlimit_basic);
ATF_TC_HEAD(setrlimit_basic, tc)
{
atf_tc_set_md_var(tc, "descr", "A basic soft limit test");
}
ATF_TC_BODY(setrlimit_basic, tc)
{
struct rlimit res;
int *buf, lim;
size_t i;
buf = calloc(__arraycount(rlimit), sizeof(int));
if (buf == NULL)
atf_tc_fail("initialization failed");
for (i = lim = 0; i < __arraycount(rlimit); i++) {
(void)memset(&res, 0, sizeof(struct rlimit));
if (getrlimit(rlimit[i], &res) != 0)
continue;
if (res.rlim_cur == RLIM_INFINITY || res.rlim_cur == 0)
continue;
if (res.rlim_cur == res.rlim_max) /* An unprivileged run. */
continue;
buf[i] = res.rlim_cur;
res.rlim_cur = res.rlim_cur - 1;
if (setrlimit(rlimit[i], &res) != 0) {
lim = rlimit[i];
goto out;
}
}
out:
for (i = 0; i < __arraycount(rlimit); i++) {
(void)memset(&res, 0, sizeof(struct rlimit));
if (buf[i] == 0)
continue;
if (getrlimit(rlimit[i], &res) != 0)
continue;
res.rlim_cur = buf[i];
(void)setrlimit(rlimit[i], &res);
}
if (lim != 0)
atf_tc_fail("failed to set limit (%d)", lim);
}
ATF_TC(setrlimit_current);
ATF_TC_HEAD(setrlimit_current, tc)
{
atf_tc_set_md_var(tc, "descr", "setrlimit(3) with current limits");
}
ATF_TC_BODY(setrlimit_current, tc)
{
struct rlimit res;
size_t i;
for (i = 0; i < __arraycount(rlimit); i++) {
(void)memset(&res, 0, sizeof(struct rlimit));
ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
ATF_REQUIRE(setrlimit(rlimit[i], &res) == 0);
}
}
ATF_TC(setrlimit_err);
ATF_TC_HEAD(setrlimit_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test error conditions");
}
ATF_TC_BODY(setrlimit_err, tc)
{
struct rlimit res;
size_t i;
for (i = 0; i < __arraycount(rlimit); i++) {
errno = 0;
ATF_REQUIRE(getrlimit(rlimit[i], (void *)0) != 0);
ATF_REQUIRE(errno == EFAULT);
}
errno = 0;
ATF_REQUIRE(getrlimit(INT_MAX, &res) != 0);
ATF_REQUIRE(errno == EINVAL);
}
ATF_TC_WITH_CLEANUP(setrlimit_fsize);
ATF_TC_HEAD(setrlimit_fsize, tc)
{
atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_FSIZE");
}
ATF_TC_BODY(setrlimit_fsize, tc)
{
struct rlimit res;
int fd, sta;
pid_t pid;
fd = open(path, O_RDWR | O_CREAT, 0700);
if (fd < 0)
atf_tc_fail("initialization failed");
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
res.rlim_cur = 2;
res.rlim_max = 2;
if (setrlimit(RLIMIT_FSIZE, &res) != 0)
_exit(EXIT_FAILURE);
if (signal(SIGXFSZ, sighandler) == SIG_ERR)
_exit(EXIT_FAILURE);
/*
* The third call should generate a SIGXFSZ.
*/
(void)write(fd, "X", 1);
(void)write(fd, "X", 1);
(void)write(fd, "X", 1);
_exit(EXIT_FAILURE);
}
(void)close(fd);
(void)wait(&sta);
(void)unlink(path);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("RLIMIT_FSIZE not enforced");
}
ATF_TC_CLEANUP(setrlimit_fsize, tc)
{
(void)unlink(path);
}
static void
sighandler(int signo)
{
if (signo != SIGXFSZ)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
ATF_TC(setrlimit_memlock);
ATF_TC_HEAD(setrlimit_memlock, tc)
{
atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_MEMLOCK");
}
ATF_TC_BODY(setrlimit_memlock, tc)
{
struct rlimit res;
void *buf;
long page;
pid_t pid;
int sta;
page = sysconf(_SC_PAGESIZE);
ATF_REQUIRE(page >= 0);
buf = malloc(page);
pid = fork();
if (buf == NULL || pid < 0)
atf_tc_fail("initialization failed");
if (pid == 0) {
/*
* Try to lock a page while
* RLIMIT_MEMLOCK is zero.
*/
if (mlock(buf, page) != 0)
_exit(EXIT_FAILURE);
if (munlock(buf, page) != 0)
_exit(EXIT_FAILURE);
res.rlim_cur = 0;
res.rlim_max = 0;
if (setrlimit(RLIMIT_MEMLOCK, &res) != 0)
_exit(EXIT_FAILURE);
if (mlock(buf, page) != 0)
_exit(EXIT_SUCCESS);
(void)munlock(buf, page);
_exit(EXIT_FAILURE);
}
free(buf);
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("RLIMIT_MEMLOCK not enforced");
}
ATF_TC(setrlimit_nofile_1);
ATF_TC_HEAD(setrlimit_nofile_1, tc)
{
atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #1");
}
ATF_TC_BODY(setrlimit_nofile_1, tc)
{
struct rlimit res;
int fd, i, rv, sta;
pid_t pid;
res.rlim_cur = 0;
res.rlim_max = 0;
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
/*
* Close all descriptors, set RLIMIT_NOFILE
* to zero, and try to open a random file.
* This should fail with EMFILE.
*/
for (i = 0; i < 1024; i++)
(void)close(i);
rv = setrlimit(RLIMIT_NOFILE, &res);
if (rv != 0)
_exit(EXIT_FAILURE);
errno = 0;
fd = open("/etc/passwd", O_RDONLY);
if (fd >= 0 || errno != EMFILE)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("RLIMIT_NOFILE not enforced");
}
ATF_TC(setrlimit_nofile_2);
ATF_TC_HEAD(setrlimit_nofile_2, tc)
{
atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #2");
}
ATF_TC_BODY(setrlimit_nofile_2, tc)
{
static const rlim_t lim = 12;
struct rlimit res;
int fd, i, rv, sta;
pid_t pid;
/*
* See that an arbitrary limit on
* open files is being enforced.
*/
res.rlim_cur = lim;
res.rlim_max = lim;
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
for (i = 0; i < 1024; i++)
(void)close(i);
rv = setrlimit(RLIMIT_NOFILE, &res);
if (rv != 0)
_exit(EXIT_FAILURE);
for (i = 0; i < (int)lim; i++) {
fd = open("/etc/passwd", O_RDONLY);
if (fd < 0)
_exit(EXIT_FAILURE);
}
/*
* After the limit has been reached,
* EMFILE should again follow.
*/
fd = open("/etc/passwd", O_RDONLY);
if (fd >= 0 || errno != EMFILE)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("RLIMIT_NOFILE not enforced");
}
ATF_TC(setrlimit_nproc);
ATF_TC_HEAD(setrlimit_nproc, tc)
{
atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NPROC");
atf_tc_set_md_var(tc, "require.user", "unprivileged");
}
ATF_TC_BODY(setrlimit_nproc, tc)
{
struct rlimit res;
pid_t pid, cpid;
int sta;
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
/*
* Set RLIMIT_NPROC to zero and try to fork.
*/
res.rlim_cur = 0;
res.rlim_max = 0;
if (setrlimit(RLIMIT_NPROC, &res) != 0)
_exit(EXIT_FAILURE);
cpid = fork();
if (cpid < 0)
_exit(EXIT_SUCCESS);
_exit(EXIT_FAILURE);
}
(void)waitpid(pid, &sta, 0);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("RLIMIT_NPROC not enforced");
}
ATF_TC(setrlimit_perm);
ATF_TC_HEAD(setrlimit_perm, tc)
{
atf_tc_set_md_var(tc, "descr", "Test setrlimit(2) for EPERM");
atf_tc_set_md_var(tc, "require.user", "unprivileged");
}
ATF_TC_BODY(setrlimit_perm, tc)
{
struct rlimit res;
size_t i;
/*
* Try to raise the maximum limits as an user.
*/
for (i = 0; i < __arraycount(rlimit); i++) {
ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
if (res.rlim_max == UINT64_MAX) /* Overflow. */
continue;
errno = 0;
res.rlim_max = res.rlim_max + 1;
ATF_REQUIRE(setrlimit(rlimit[i], &res) != 0);
ATF_REQUIRE(errno == EPERM);
}
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, setrlimit_basic);
ATF_TP_ADD_TC(tp, setrlimit_current);
ATF_TP_ADD_TC(tp, setrlimit_err);
ATF_TP_ADD_TC(tp, setrlimit_fsize);
ATF_TP_ADD_TC(tp, setrlimit_memlock);
ATF_TP_ADD_TC(tp, setrlimit_nofile_1);
ATF_TP_ADD_TC(tp, setrlimit_nofile_2);
ATF_TP_ADD_TC(tp, setrlimit_nproc);
ATF_TP_ADD_TC(tp, setrlimit_perm);
return atf_no_error();
}

View File

@ -0,0 +1,122 @@
/* $NetBSD: t_setuid.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_setuid.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
#include <sys/wait.h>
#include <atf-c.h>
#include <errno.h>
#include <pwd.h>
#include <stdlib.h>
#include <unistd.h>
ATF_TC(setuid_perm);
ATF_TC_HEAD(setuid_perm, tc)
{
atf_tc_set_md_var(tc, "descr", "Test setuid(0) as normal user");
atf_tc_set_md_var(tc, "require.user", "unprivileged");
}
ATF_TC_BODY(setuid_perm, tc)
{
errno = 0;
ATF_REQUIRE(setuid(0) == -1);
ATF_REQUIRE(errno == EPERM);
}
ATF_TC(setuid_real);
ATF_TC_HEAD(setuid_real, tc)
{
atf_tc_set_md_var(tc, "descr", "Test setuid(2) with real UID");
}
ATF_TC_BODY(setuid_real, tc)
{
uid_t uid = getuid();
ATF_REQUIRE(setuid(uid) == 0);
ATF_REQUIRE(getuid() == uid);
ATF_REQUIRE(geteuid() == uid);
}
ATF_TC(setuid_root);
ATF_TC_HEAD(setuid_root, tc)
{
atf_tc_set_md_var(tc, "descr", "A basic test of setuid(2)");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(setuid_root, tc)
{
struct passwd *pw;
int rv, sta;
pid_t pid;
uid_t uid;
while ((pw = getpwent()) != NULL) {
pid = fork();
ATF_REQUIRE(pid >= 0);
if (pid == 0) {
rv = setuid(pw->pw_uid);
if (rv != 0)
_exit(EXIT_FAILURE);
uid = getuid();
if (uid != pw->pw_uid)
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
atf_tc_fail("failed to change UID to %u", pw->pw_uid);
}
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, setuid_perm);
ATF_TP_ADD_TC(tp, setuid_real);
ATF_TP_ADD_TC(tp, setuid_root);
return atf_no_error();
}

374
tests/lib/libc/sys/t_stat.c Normal file
View File

@ -0,0 +1,374 @@
/* $NetBSD: t_stat.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_stat.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
#include <sys/stat.h>
#include <sys/types.h>
#include <atf-c.h>
#include <errno.h>
#include <fcntl.h>
#include <fts.h>
#include <limits.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
static const char *path = "stat";
ATF_TC_WITH_CLEANUP(stat_chflags);
ATF_TC_HEAD(stat_chflags, tc)
{
atf_tc_set_md_var(tc, "descr", "Test chflags(2) with stat(2)");
}
ATF_TC_BODY(stat_chflags, tc)
{
struct stat sa, sb;
int fd;
(void)memset(&sa, 0, sizeof(struct stat));
(void)memset(&sb, 0, sizeof(struct stat));
fd = open(path, O_RDONLY | O_CREAT);
ATF_REQUIRE(fd != -1);
ATF_REQUIRE(stat(path, &sa) == 0);
ATF_REQUIRE(chflags(path, UF_NODUMP) == 0);
ATF_REQUIRE(stat(path, &sb) == 0);
if (sa.st_flags == sb.st_flags)
atf_tc_fail("stat(2) did not detect chflags(2)");
ATF_REQUIRE(close(fd) == 0);
ATF_REQUIRE(unlink(path) == 0);
}
ATF_TC_CLEANUP(stat_chflags, tc)
{
(void)unlink(path);
}
ATF_TC(stat_dir);
ATF_TC_HEAD(stat_dir, tc)
{
atf_tc_set_md_var(tc, "descr", "Test stat(2) with directories");
}
ATF_TC_BODY(stat_dir, tc)
{
const short depth = 3;
struct stat sa, sb;
char *argv[2];
FTSENT *ftse;
FTS *fts;
int ops;
/*
* XXX: This is verified to panic at least a qemu/i386 guest.
*/
atf_tc_skip("the test may cause a panic");
argv[1] = NULL;
argv[0] = __UNCONST("/");
ops = FTS_NOCHDIR;
ops |= FTS_PHYSICAL;
fts = fts_open(argv, ops, NULL);
ATF_REQUIRE(fts != NULL);
while ((ftse = fts_read(fts)) != NULL) {
if (ftse->fts_level < 1)
continue;
if (ftse->fts_level > depth) {
(void)fts_set(fts, ftse, FTS_SKIP);
continue;
}
switch(ftse->fts_info) {
case FTS_DP:
(void)memset(&sa, 0, sizeof(struct stat));
(void)memset(&sb, 0, sizeof(struct stat));
ATF_REQUIRE(stat(ftse->fts_parent->fts_path,&sa) == 0);
ATF_REQUIRE(chdir(ftse->fts_path) == 0);
ATF_REQUIRE(stat(".", &sb) == 0);
/*
* The previous two stat(2) calls
* should be for the same directory.
*/
if (sa.st_dev != sb.st_dev || sa.st_ino != sb.st_ino)
atf_tc_fail("inconsistent stat(2)");
/*
* Check that fts(3)'s stat(2)
* call equals the manual one.
*/
if (sb.st_ino != ftse->fts_statp->st_ino)
atf_tc_fail("stat(2) and fts(3) differ");
break;
default:
break;
}
}
(void)fts_close(fts);
}
ATF_TC(stat_err);
ATF_TC_HEAD(stat_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test errors from the stat(2) family");
}
ATF_TC_BODY(stat_err, tc)
{
char buf[NAME_MAX + 1];
struct stat st;
(void)memset(buf, 'x', sizeof(buf));
errno = 0;
ATF_REQUIRE_ERRNO(EBADF, fstat(-1, &st) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENAMETOOLONG, stat(buf, &st) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENAMETOOLONG, lstat(buf, &st) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, stat((void *)-1, &st) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, lstat((void *)-1, &st) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, stat("/etc/passwd", (void *)-1) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, lstat("/etc/passwd", (void *)-1) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENOENT, stat("/a/b/c/d/e/f/g/h/i/j/k", &st) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENOENT, lstat("/a/b/c/d/e/f/g/h/i/j/k", &st) == -1);
}
ATF_TC_WITH_CLEANUP(stat_mtime);
ATF_TC_HEAD(stat_mtime, tc)
{
atf_tc_set_md_var(tc, "descr", "Test modification times with stat(2)");
}
ATF_TC_BODY(stat_mtime, tc)
{
struct stat sa, sb;
int fd[3];
size_t i;
for (i = 0; i < __arraycount(fd); i++) {
(void)memset(&sa, 0, sizeof(struct stat));
(void)memset(&sb, 0, sizeof(struct stat));
fd[i] = open(path, O_WRONLY | O_CREAT);
ATF_REQUIRE(fd[i] != -1);
ATF_REQUIRE(write(fd[i], "X", 1) == 1);
ATF_REQUIRE(stat(path, &sa) == 0);
(void)sleep(1);
ATF_REQUIRE(write(fd[i], "X", 1) == 1);
ATF_REQUIRE(stat(path, &sb) == 0);
ATF_REQUIRE(close(fd[i]) == 0);
ATF_REQUIRE(unlink(path) == 0);
if (sa.st_mtime == sb.st_mtime)
atf_tc_fail("mtimes did not change");
}
}
ATF_TC_CLEANUP(stat_mtime, tc)
{
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(stat_perm);
ATF_TC_HEAD(stat_perm, tc)
{
atf_tc_set_md_var(tc, "descr", "Test permissions with stat(2)");
atf_tc_set_md_var(tc, "require.user", "root");
}
ATF_TC_BODY(stat_perm, tc)
{
struct stat sa, sb;
gid_t gid;
uid_t uid;
int fd;
(void)memset(&sa, 0, sizeof(struct stat));
(void)memset(&sb, 0, sizeof(struct stat));
uid = getuid();
gid = getgid();
fd = open(path, O_RDONLY | O_CREAT);
ATF_REQUIRE(fd != -1);
ATF_REQUIRE(fstat(fd, &sa) == 0);
ATF_REQUIRE(stat(path, &sb) == 0);
if (gid != sa.st_gid || sa.st_gid != sb.st_gid)
atf_tc_fail("invalid GID");
if (uid != sa.st_uid || sa.st_uid != sb.st_uid)
atf_tc_fail("invalid UID");
ATF_REQUIRE(close(fd) == 0);
ATF_REQUIRE(unlink(path) == 0);
}
ATF_TC_CLEANUP(stat_perm, tc)
{
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(stat_size);
ATF_TC_HEAD(stat_size, tc)
{
atf_tc_set_md_var(tc, "descr", "Test file sizes with stat(2)");
}
ATF_TC_BODY(stat_size, tc)
{
struct stat sa, sb, sc;
const size_t n = 10;
size_t i;
int fd;
fd = open(path, O_WRONLY | O_CREAT);
ATF_REQUIRE(fd >= 0);
for (i = 0; i < n; i++) {
(void)memset(&sa, 0, sizeof(struct stat));
(void)memset(&sb, 0, sizeof(struct stat));
(void)memset(&sc, 0, sizeof(struct stat));
ATF_REQUIRE(fstat(fd, &sa) == 0);
ATF_REQUIRE(write(fd, "X", 1) == 1);
ATF_REQUIRE(fstat(fd, &sb) == 0);
ATF_REQUIRE(stat(path, &sc) == 0);
if (sa.st_size + 1 != sb.st_size)
atf_tc_fail("invalid file size");
if (sb.st_size != sc.st_size)
atf_tc_fail("stat(2) and fstat(2) mismatch");
}
ATF_REQUIRE(close(fd) == 0);
ATF_REQUIRE(unlink(path) == 0);
}
ATF_TC_CLEANUP(stat_size, tc)
{
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(stat_symlink);
ATF_TC_HEAD(stat_symlink, tc)
{
atf_tc_set_md_var(tc, "descr", "Test symbolic links with stat(2)");
}
ATF_TC_BODY(stat_symlink, tc)
{
const char *pathlink = "pathlink";
struct stat sa, sb;
int fd;
(void)memset(&sa, 0, sizeof(struct stat));
(void)memset(&sb, 0, sizeof(struct stat));
fd = open(path, O_WRONLY | O_CREAT);
ATF_REQUIRE(fd >= 0);
ATF_REQUIRE(symlink(path, pathlink) == 0);
ATF_REQUIRE(stat(pathlink, &sa) == 0);
ATF_REQUIRE(lstat(pathlink, &sb) == 0);
if (S_ISLNK(sa.st_mode) != 0)
atf_tc_fail("stat(2) detected symbolic link");
if (S_ISLNK(sb.st_mode) == 0)
atf_tc_fail("lstat(2) did not detect symbolic link");
if (sa.st_mode == sb.st_mode)
atf_tc_fail("inconsistencies between stat(2) and lstat(2)");
ATF_REQUIRE(unlink(path) == 0);
ATF_REQUIRE(unlink(pathlink) == 0);
}
ATF_TC_CLEANUP(stat_symlink, tc)
{
(void)unlink(path);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, stat_chflags);
ATF_TP_ADD_TC(tp, stat_dir);
ATF_TP_ADD_TC(tp, stat_err);
ATF_TP_ADD_TC(tp, stat_mtime);
ATF_TP_ADD_TC(tp, stat_perm);
ATF_TP_ADD_TC(tp, stat_size);
ATF_TP_ADD_TC(tp, stat_symlink);
return atf_no_error();
}

View File

@ -0,0 +1,345 @@
/* $NetBSD: t_timer_create.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <atf-c.h>
#include "../../../h_macros.h"
static void timer_signal_create(clockid_t, int);
static void timer_signal_handler(int, siginfo_t *, void *);
static int timer_wait(time_t);
#if 0
/*
* XXX: SIGEV_THREAD is not yet supported.
*/
static void timer_thread_create(clockid_t);
static void timer_thread_handler(sigval_t);
#endif
static timer_t t;
static bool error;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
ATF_TC(timer_create_bogus);
ATF_TC_HEAD(timer_create_bogus, tc)
{
/* Cf. PR lib/42434. */
atf_tc_set_md_var(tc, "descr",
"Checks timer_create(2)'s error checking");
}
ATF_TC_BODY(timer_create_bogus, tc)
{
struct sigevent evt;
(void)memset(&evt, 0, sizeof(struct sigevent));
evt.sigev_signo = -1;
evt.sigev_notify = SIGEV_SIGNAL;
if (timer_create(CLOCK_REALTIME, &evt, &t) == 0)
goto fail;
evt.sigev_signo = SIGUSR1;
evt.sigev_notify = SIGEV_THREAD + 100;
if (timer_create(CLOCK_REALTIME, &evt, &t) == 0)
goto fail;
evt.sigev_signo = SIGUSR1;
evt.sigev_value.sival_int = 0;
evt.sigev_notify = SIGEV_SIGNAL;
if (timer_create(CLOCK_REALTIME + 100, &evt, &t) == 0)
goto fail;
t = 0;
return;
fail:
atf_tc_fail("timer_create() successful with bogus values");
}
ATF_TC(timer_create_signal_realtime);
ATF_TC_HEAD(timer_create_signal_realtime, tc)
{
atf_tc_set_md_var(tc, "descr",
"Checks timer_create(2) with CLOCK_REALTIME and sigevent(3), "
"SIGEV_SIGNAL");
}
ATF_TC_BODY(timer_create_signal_realtime, tc)
{
int i, signals[6] = {
SIGALRM, SIGIO, SIGPROF, SIGUSR1, SIGUSR2, -1
};
for (i = 0; signals[i] > 0; i++)
timer_signal_create(CLOCK_REALTIME, signals[i]);
}
ATF_TC(timer_create_signal_monotonic);
ATF_TC_HEAD(timer_create_signal_monotonic, tc)
{
atf_tc_set_md_var(tc, "descr",
"Checks timer_create(2) with CLOCK_MONOTONIC and sigevent(3), "
"SIGEV_SIGNAL");
}
ATF_TC_BODY(timer_create_signal_monotonic, tc)
{
int i, signals[6] = {
SIGALRM, SIGIO, SIGPROF, SIGUSR1, SIGUSR2, -1
};
for (i = 0; signals[i] > 0; i++)
timer_signal_create(CLOCK_MONOTONIC, signals[i]);
}
static void
timer_signal_create(clockid_t cid, int sig)
{
struct itimerspec tim;
struct sigaction act;
struct sigevent evt;
const char *errstr;
sigset_t set;
error = true;
(void)memset(&evt, 0, sizeof(struct sigevent));
(void)memset(&act, 0, sizeof(struct sigaction));
(void)memset(&tim, 0, sizeof(struct itimerspec));
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = timer_signal_handler;
(void)sigemptyset(&act.sa_mask);
if (sigaction(sig, &act, NULL) != 0) {
errstr = "sigaction()";
goto fail;
}
(void)sigemptyset(&set);
(void)sigaddset(&set, sig);
if (sigprocmask(SIG_SETMASK, &set, NULL) != 0) {
errstr = "sigprocmask()";
goto fail;
}
evt.sigev_signo = sig;
evt.sigev_value.sival_ptr = &t;
evt.sigev_notify = SIGEV_SIGNAL;
if (timer_create(cid, &evt, &t) != 0) {
errstr = "timer_create()";
goto fail;
}
tim.it_value.tv_sec = 0;
tim.it_value.tv_nsec = 1000 * 1000;
if (timer_settime(t, 0, &tim, NULL) != 0) {
errstr = "timer_settime()";
goto fail;
}
if (sigprocmask(SIG_UNBLOCK, &set, NULL) != 0) {
errstr = "sigprocmask()";
goto fail;
}
errno = timer_wait(1);
if (errno != 0) {
errstr = "timer_wait()";
goto fail;
}
return;
fail:
atf_tc_fail_errno("%s failed (sig %d, clock %d)", errstr, sig, cid);
}
static void
timer_signal_handler(int signo, siginfo_t *si, void *osi)
{
timer_t *tp;
if (pthread_mutex_lock(&mtx) != 0)
return;
tp = si->si_value.sival_ptr;
if (*tp == t)
error = false;
(void)pthread_cond_signal(&cond);
(void)pthread_mutex_unlock(&mtx);
(void)signal(signo, SIG_IGN);
}
static int
timer_wait(time_t wait)
{
struct timespec ts;
int rv;
rv = pthread_mutex_lock(&mtx);
if (rv != 0)
return rv;
errno = 0;
if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
if (errno == 0)
errno = EFAULT;
return errno;
}
ts.tv_sec += wait;
rv = pthread_cond_timedwait(&cond, &mtx, &ts);
if (rv != 0)
return rv;
rv = pthread_mutex_unlock(&mtx);
if (rv != 0)
return rv;
if (error != false)
return EPROCUNAVAIL;
return timer_delete(t);
}
#if 0
ATF_TC(timer_create_thread);
ATF_TC_HEAD(timer_create_thread, tc)
{
atf_tc_set_md_var(tc, "descr",
"Checks timer_create(2) and sigevent(3), SIGEV_THREAD");
}
ATF_TC_BODY(timer_create_thread, tc)
{
timer_thread_create(CLOCK_REALTIME);
}
static void
timer_thread_create(clockid_t cid)
{
struct itimerspec tim;
struct sigevent evt;
const char *errstr;
error = true;
(void)memset(&evt, 0, sizeof(struct sigevent));
(void)memset(&tim, 0, sizeof(struct itimerspec));
evt.sigev_notify = SIGEV_THREAD;
evt.sigev_value.sival_ptr = &t;
evt.sigev_notify_function = timer_thread_handler;
evt.sigev_notify_attributes = NULL;
if (timer_create(cid, &evt, &t) != 0) {
errstr = "timer_create()";
goto fail;
}
tim.it_value.tv_sec = 1;
tim.it_value.tv_nsec = 0;
if (timer_settime(t, 0, &tim, NULL) != 0) {
errstr = "timer_settime()";
goto fail;
}
errno = timer_wait(3);
if (errno != 0) {
errstr = "timer_wait()";
goto fail;
}
return;
fail:
atf_tc_fail_errno("%s failed (clock %d)", errstr, cid);
}
static void
timer_thread_handler(sigval_t sv)
{
timer_t *tp;
if (pthread_mutex_lock(&mtx) != 0)
return;
tp = sv.sival_ptr;
if (*tp == t)
error = false;
(void)pthread_cond_signal(&cond);
(void)pthread_mutex_unlock(&mtx);
}
#endif
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, timer_create_bogus);
ATF_TP_ADD_TC(tp, timer_create_signal_realtime);
ATF_TP_ADD_TC(tp, timer_create_signal_monotonic);
/* ATF_TP_ADD_TC(tp, timer_create_thread); */
return atf_no_error();
}

View File

@ -0,0 +1,175 @@
/* $NetBSD: t_truncate.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_truncate.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
#include <sys/stat.h>
#include <atf-c.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static const char path[] = "truncate";
static const size_t sizes[] = { 8, 16, 512, 1024, 2048, 4094, 3000, 30 };
ATF_TC_WITH_CLEANUP(ftruncate_basic);
ATF_TC_HEAD(ftruncate_basic, tc)
{
atf_tc_set_md_var(tc, "descr", "A basic test of ftruncate(2)");
}
ATF_TC_BODY(ftruncate_basic, tc)
{
struct stat st;
size_t i;
int fd;
fd = open(path, O_RDWR | O_CREAT, 0600);
ATF_REQUIRE(fd >= 0);
for (i = 0; i < __arraycount(sizes); i++) {
(void)memset(&st, 0, sizeof(struct stat));
ATF_REQUIRE(ftruncate(fd, sizes[i]) == 0);
ATF_REQUIRE(fstat(fd, &st) == 0);
(void)fprintf(stderr, "truncating to %zu bytes\n", sizes[i]);
if (sizes[i] != (size_t)st.st_size)
atf_tc_fail("ftruncate(2) did not truncate");
}
(void)close(fd);
(void)unlink(path);
}
ATF_TC_CLEANUP(ftruncate_basic, tc)
{
(void)unlink(path);
}
ATF_TC(ftruncate_err);
ATF_TC_HEAD(ftruncate_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test errors from ftruncate(2)");
atf_tc_set_md_var(tc, "require.user", "unprivileged");
}
ATF_TC_BODY(ftruncate_err, tc)
{
int fd;
fd = open("/etc/passwd", O_RDONLY, 0400);
ATF_REQUIRE(fd >= 0);
errno = 0;
ATF_REQUIRE_ERRNO(EBADF, ftruncate(-1, 999) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EINVAL, ftruncate(fd, 999) == -1);
(void)close(fd);
}
ATF_TC_WITH_CLEANUP(truncate_basic);
ATF_TC_HEAD(truncate_basic, tc)
{
atf_tc_set_md_var(tc, "descr", "A basic test of truncate(2)");
}
ATF_TC_BODY(truncate_basic, tc)
{
struct stat st;
size_t i;
int fd;
fd = open(path, O_RDWR | O_CREAT, 0600);
ATF_REQUIRE(fd >= 0);
for (i = 0; i < __arraycount(sizes); i++) {
(void)memset(&st, 0, sizeof(struct stat));
ATF_REQUIRE(truncate(path, sizes[i]) == 0);
ATF_REQUIRE(fstat(fd, &st) == 0);
(void)fprintf(stderr, "truncating to %zu bytes\n", sizes[i]);
if (sizes[i] != (size_t)st.st_size)
atf_tc_fail("truncate(2) did not truncate");
}
(void)close(fd);
(void)unlink(path);
}
ATF_TC_CLEANUP(truncate_basic, tc)
{
(void)unlink(path);
}
ATF_TC(truncate_err);
ATF_TC_HEAD(truncate_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test errors from truncate(2)");
atf_tc_set_md_var(tc, "require.user", "unprivileged");
}
ATF_TC_BODY(truncate_err, tc)
{
errno = 0;
ATF_REQUIRE_ERRNO(EFAULT, truncate((void *)-1, 999) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EISDIR, truncate("/etc", 999) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENOENT, truncate("/a/b/c/d/e/f/g", 999) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EACCES, truncate("/root/.profile", 999) == -1);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, ftruncate_basic);
ATF_TP_ADD_TC(tp, ftruncate_err);
ATF_TP_ADD_TC(tp, truncate_basic);
ATF_TP_ADD_TC(tp, truncate_err);
return atf_no_error();
}

View File

@ -0,0 +1,205 @@
/* $NetBSD: t_umask.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_umask.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
#include <sys/stat.h>
#include <sys/wait.h>
#include <atf-c.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static const char path[] = "umask";
static const mode_t mask[] = {
S_IRWXU,
S_IRUSR,
S_IWUSR,
S_IXUSR,
S_IRWXG,
S_IRGRP,
S_IWGRP,
S_IXGRP,
S_IRWXO,
S_IROTH,
S_IWOTH,
S_IXOTH
};
ATF_TC_WITH_CLEANUP(umask_fork);
ATF_TC_HEAD(umask_fork, tc)
{
atf_tc_set_md_var(tc, "descr", "Check that umask(2) is inherited");
}
ATF_TC_BODY(umask_fork, tc)
{
mode_t mode;
pid_t pid;
size_t i;
int sta;
for (i = 0; i < __arraycount(mask) - 1; i++) {
(void)umask(mask[i] | mask[i + 1]);
pid = fork();
if (pid < 0)
continue;
if (pid == 0) {
mode = umask(mask[i]);
if (mode != (mask[i] | mask[i + 1]))
_exit(EXIT_FAILURE);
_exit(EXIT_SUCCESS);
}
(void)wait(&sta);
if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
goto fail;
}
return;
fail:
(void)umask(S_IWGRP | S_IWOTH);
atf_tc_fail("umask(2) was not inherited");
}
ATF_TC_CLEANUP(umask_fork, tc)
{
(void)umask(S_IWGRP | S_IWOTH);
}
ATF_TC_WITH_CLEANUP(umask_open);
ATF_TC_HEAD(umask_open, tc)
{
atf_tc_set_md_var(tc, "descr", "A basic test of open(2) and umask(2)");
}
ATF_TC_BODY(umask_open, tc)
{
const char *str = NULL;
struct stat st;
size_t i;
int fd;
for (i = 0; i < __arraycount(mask); i++) {
(void)umask(mask[i]);
fd = open(path, O_RDWR | O_CREAT, 0777);
if (fd < 0)
continue;
(void)memset(&st, 0, sizeof(struct stat));
if (stat(path, &st) != 0) {
str = "failed to stat(2)";
goto out;
}
if ((st.st_mode & mask[i]) != 0) {
str = "invalid umask(2)";
goto out;
}
if (unlink(path) != 0) {
str = "failed to unlink(2)";
goto out;
}
}
out:
(void)umask(S_IWGRP | S_IWOTH);
if (str != NULL)
atf_tc_fail("%s", str);
}
ATF_TC_CLEANUP(umask_open, tc)
{
(void)umask(S_IWGRP | S_IWOTH);
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(umask_previous);
ATF_TC_HEAD(umask_previous, tc)
{
atf_tc_set_md_var(tc, "descr", "Test the return value from umask(2)");
}
ATF_TC_BODY(umask_previous, tc)
{
mode_t mode;
size_t i;
for (i = 0; i < __arraycount(mask); i++) {
mode = umask(mask[i]);
mode = umask(mask[i]);
if (mode != mask[i])
goto fail;
}
return;
fail:
(void)umask(S_IWGRP | S_IWOTH);
atf_tc_fail("umask(2) did not return the previous mask");
}
ATF_TC_CLEANUP(umask_previous, tc)
{
(void)umask(S_IWGRP | S_IWOTH);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, umask_fork);
ATF_TP_ADD_TC(tp, umask_open);
ATF_TP_ADD_TC(tp, umask_previous);
return atf_no_error();
}

View File

@ -0,0 +1,154 @@
/* $NetBSD: t_unlink.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jukka Ruohonen.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: t_unlink.c,v 1.1 2011/07/07 06:57:54 jruoho Exp $");
#include <sys/stat.h>
#include <atf-c.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <string.h>
#include <unistd.h>
static char path[] = "unlink";
ATF_TC_WITH_CLEANUP(unlink_basic);
ATF_TC_HEAD(unlink_basic, tc)
{
atf_tc_set_md_var(tc, "descr", "A basic test of unlink(2)");
}
ATF_TC_BODY(unlink_basic, tc)
{
const size_t n = 512;
size_t i;
int fd;
for (i = 0; i < n; i++) {
fd = open(path, O_RDWR | O_CREAT, 0666);
ATF_REQUIRE(fd != -1);
ATF_REQUIRE(close(fd) == 0);
ATF_REQUIRE(unlink(path) == 0);
errno = 0;
ATF_REQUIRE_ERRNO(ENOENT, open(path, O_RDONLY) == -1);
}
}
ATF_TC_CLEANUP(unlink_basic, tc)
{
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(unlink_err);
ATF_TC_HEAD(unlink_err, tc)
{
atf_tc_set_md_var(tc, "descr", "Test error conditions of unlink(2)");
}
ATF_TC_BODY(unlink_err, tc)
{
char buf[PATH_MAX + 1];
(void)memset(buf, 'x', sizeof(buf));
errno = 0;
ATF_REQUIRE_ERRNO(EBUSY, unlink("/") == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENAMETOOLONG, unlink(buf) == -1);
errno = 0;
ATF_REQUIRE_ERRNO(ENOENT, unlink("/a/b/c/d/e/f/g/h/i/j/k/l/m") == -1);
}
ATF_TC_CLEANUP(unlink_err, tc)
{
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(unlink_fifo);
ATF_TC_HEAD(unlink_fifo, tc)
{
atf_tc_set_md_var(tc, "descr", "Test unlink(2) for a FIFO");
}
ATF_TC_BODY(unlink_fifo, tc)
{
ATF_REQUIRE(mkfifo(path, 0666) == 0);
ATF_REQUIRE(unlink(path) == 0);
errno = 0;
ATF_REQUIRE_ERRNO(ENOENT, open(path, O_RDONLY) == -1);
}
ATF_TC_CLEANUP(unlink_fifo, tc)
{
(void)unlink(path);
}
ATF_TC_WITH_CLEANUP(unlink_perm);
ATF_TC_HEAD(unlink_perm, tc)
{
atf_tc_set_md_var(tc, "descr", "Test permissions with unlink(2)");
atf_tc_set_md_var(tc, "require.user", "unprivileged");
}
ATF_TC_BODY(unlink_perm, tc)
{
errno = 0;
ATF_REQUIRE_ERRNO(EACCES, unlink("/etc") == -1);
errno = 0;
ATF_REQUIRE_ERRNO(EACCES, unlink("/root/.profile") == -1);
}
ATF_TC_CLEANUP(unlink_perm, tc)
{
(void)unlink(path);
}
ATF_TP_ADD_TCS(tp)
{
ATF_TP_ADD_TC(tp, unlink_basic);
ATF_TP_ADD_TC(tp, unlink_err);
ATF_TP_ADD_TC(tp, unlink_fifo);
ATF_TP_ADD_TC(tp, unlink_perm);
return atf_no_error();
}