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:
parent
dc1519dda0
commit
068fb4f133
@ -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>
|
||||
|
||||
|
210
tests/lib/libc/sys/t_access.c
Normal file
210
tests/lib/libc/sys/t_access.c
Normal 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();
|
||||
}
|
313
tests/lib/libc/sys/t_chroot.c
Normal file
313
tests/lib/libc/sys/t_chroot.c
Normal 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
184
tests/lib/libc/sys/t_dup.c
Normal 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();
|
||||
}
|
119
tests/lib/libc/sys/t_fsync.c
Normal file
119
tests/lib/libc/sys/t_fsync.c
Normal 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();
|
||||
}
|
171
tests/lib/libc/sys/t_getgroups.c
Normal file
171
tests/lib/libc/sys/t_getgroups.c
Normal 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();
|
||||
}
|
215
tests/lib/libc/sys/t_getitimer.c
Normal file
215
tests/lib/libc/sys/t_getitimer.c
Normal 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();
|
||||
}
|
237
tests/lib/libc/sys/t_getlogin.c
Normal file
237
tests/lib/libc/sys/t_getlogin.c
Normal 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();
|
||||
}
|
134
tests/lib/libc/sys/t_getpid.c
Normal file
134
tests/lib/libc/sys/t_getpid.c
Normal 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();
|
||||
}
|
192
tests/lib/libc/sys/t_getrusage.c
Normal file
192
tests/lib/libc/sys/t_getrusage.c
Normal 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();
|
||||
}
|
119
tests/lib/libc/sys/t_getsid.c
Normal file
119
tests/lib/libc/sys/t_getsid.c
Normal 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();
|
||||
}
|
86
tests/lib/libc/sys/t_gettimeofday.c
Normal file
86
tests/lib/libc/sys/t_gettimeofday.c
Normal 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();
|
||||
}
|
148
tests/lib/libc/sys/t_issetugid.c
Normal file
148
tests/lib/libc/sys/t_issetugid.c
Normal 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
312
tests/lib/libc/sys/t_kill.c
Normal 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
225
tests/lib/libc/sys/t_link.c
Normal 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();
|
||||
}
|
189
tests/lib/libc/sys/t_mincore.c
Normal file
189
tests/lib/libc/sys/t_mincore.c
Normal 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();
|
||||
}
|
280
tests/lib/libc/sys/t_mkfifo.c
Normal file
280
tests/lib/libc/sys/t_mkfifo.c
Normal 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();
|
||||
}
|
194
tests/lib/libc/sys/t_mknod.c
Normal file
194
tests/lib/libc/sys/t_mknod.c
Normal 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
322
tests/lib/libc/sys/t_mmap.c
Normal 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();
|
||||
}
|
273
tests/lib/libc/sys/t_mprotect.c
Normal file
273
tests/lib/libc/sys/t_mprotect.c
Normal 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();
|
||||
}
|
226
tests/lib/libc/sys/t_msync.c
Normal file
226
tests/lib/libc/sys/t_msync.c
Normal 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();
|
||||
}
|
177
tests/lib/libc/sys/t_nanosleep.c
Normal file
177
tests/lib/libc/sys/t_nanosleep.c
Normal 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
287
tests/lib/libc/sys/t_poll.c
Normal 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();
|
||||
}
|
186
tests/lib/libc/sys/t_revoke.c
Normal file
186
tests/lib/libc/sys/t_revoke.c
Normal 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();
|
||||
}
|
217
tests/lib/libc/sys/t_select.c
Normal file
217
tests/lib/libc/sys/t_select.c
Normal 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();
|
||||
}
|
481
tests/lib/libc/sys/t_setrlimit.c
Normal file
481
tests/lib/libc/sys/t_setrlimit.c
Normal 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();
|
||||
}
|
122
tests/lib/libc/sys/t_setuid.c
Normal file
122
tests/lib/libc/sys/t_setuid.c
Normal 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
374
tests/lib/libc/sys/t_stat.c
Normal 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();
|
||||
}
|
345
tests/lib/libc/sys/t_timer_create.c
Normal file
345
tests/lib/libc/sys/t_timer_create.c
Normal 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();
|
||||
}
|
175
tests/lib/libc/sys/t_truncate.c
Normal file
175
tests/lib/libc/sys/t_truncate.c
Normal 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();
|
||||
}
|
205
tests/lib/libc/sys/t_umask.c
Normal file
205
tests/lib/libc/sys/t_umask.c
Normal 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();
|
||||
}
|
154
tests/lib/libc/sys/t_unlink.c
Normal file
154
tests/lib/libc/sys/t_unlink.c
Normal 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();
|
||||
}
|
Loading…
Reference in New Issue
Block a user