From 2ca8472c6d47b882e31bc8594e83e4e30bc1731b Mon Sep 17 00:00:00 2001 From: guenther Date: Sun, 27 Apr 2014 22:18:25 +0000 Subject: [PATCH] Regress for access() --- regress/sys/kern/Makefile | 4 +- regress/sys/kern/access/Makefile | 5 + regress/sys/kern/access/access.c | 189 +++++++++++++++++++++++++++++++ 3 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 regress/sys/kern/access/Makefile create mode 100644 regress/sys/kern/access/access.c diff --git a/regress/sys/kern/Makefile b/regress/sys/kern/Makefile index 77df15b6c47..eae0ab7d8b5 100644 --- a/regress/sys/kern/Makefile +++ b/regress/sys/kern/Makefile @@ -1,6 +1,6 @@ -# $OpenBSD: Makefile,v 1.61 2013/10/07 15:52:17 jsing Exp $ +# $OpenBSD: Makefile,v 1.62 2014/04/27 22:18:25 guenther Exp $ -SUBDIR+= __syscall accept dup2 dup2_self exec_self execve exit extent +SUBDIR+= __syscall access accept dup2 dup2_self exec_self execve exit extent SUBDIR+= fchdir SUBDIR+= fcntl_dup SUBDIR+= flock diff --git a/regress/sys/kern/access/Makefile b/regress/sys/kern/access/Makefile new file mode 100644 index 00000000000..3b52907c6c6 --- /dev/null +++ b/regress/sys/kern/access/Makefile @@ -0,0 +1,5 @@ +# $OpenBSD: Makefile,v 1.1 2014/04/27 22:18:25 guenther Exp $ + +PROG= access + +.include diff --git a/regress/sys/kern/access/access.c b/regress/sys/kern/access/access.c new file mode 100644 index 00000000000..318f164d2b3 --- /dev/null +++ b/regress/sys/kern/access/access.c @@ -0,0 +1,189 @@ +/* $OpenBSD: access.c,v 1.1 2014/04/27 22:18:25 guenther Exp $ */ +/* + * Written by Philip Guenther 2014 Public Domain. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define UID_YES 991 +#define UID_NO 990 +#define GID_YES 991 +#define GID_NO 990 + +char dir[] = "testdir"; +char exists[] = "testdir/testfile"; +char r_r_exists[] = "testdir/testfile_r_r"; +char r_w_exists[] = "testdir/testfile_r_w"; +char w_r_exists[] = "testdir/testfile_w_r"; +char w_w_exists[] = "testdir/testfile_w_w"; +char x_x_exists[] = "testdir/testfile_x_x"; +char noexists[] = "testdir/nosuchfile"; + +char temp[] = "/tmp/accessXXXXXXXXX"; + +struct tests { + int err, eaccess; + uid_t ruid, euid; + gid_t rgid, egid; + int amode; + const char *filename; +} tests[] = { + /* RETURNS EACC RUID EUID RGID EGID AMODE FILENAME */ + /* negative tests */ + /* unable to search through the directory */ + { EACCES, 0, UID_NO, UID_NO, GID_NO, GID_NO, F_OK, exists }, + { EACCES, 0, UID_NO, UID_YES, GID_NO, GID_NO, F_OK, exists }, + { EACCES, 0, UID_NO, UID_NO, GID_NO, GID_YES, F_OK, exists }, + { EACCES, 0, UID_NO, UID_YES, GID_NO, GID_YES, F_OK, exists }, + { EACCES, 1, UID_NO, UID_NO, GID_NO, GID_NO, F_OK, exists }, + { EACCES, 1, UID_YES, UID_NO, GID_NO, GID_NO, F_OK, exists }, + { EACCES, 1, UID_NO, UID_NO, GID_YES, GID_NO, F_OK, exists }, + { EACCES, 1, UID_YES, UID_NO, GID_YES, GID_NO, F_OK, exists }, + /* can search to it, but the file ain't there */ + { ENOENT, 0, UID_YES, UID_NO, GID_NO, GID_NO, F_OK, noexists }, + { ENOENT, 0, UID_NO, UID_NO, GID_YES, GID_NO, F_OK, noexists }, + { ENOENT, 0, UID_YES, UID_NO, GID_YES, GID_NO, F_OK, noexists }, + { ENOENT, 1, UID_NO, UID_YES, GID_NO, GID_NO, F_OK, noexists }, + { ENOENT, 1, UID_NO, UID_NO, GID_NO, GID_YES, F_OK, noexists }, + { ENOENT, 1, UID_NO, UID_YES, GID_NO, GID_YES, F_OK, noexists }, + /* can search to it, but the file doesn't have read perm */ + { EACCES, 0, UID_YES, UID_NO, GID_NO, GID_NO, R_OK, w_w_exists }, + { EACCES, 0, UID_NO, UID_NO, GID_YES, GID_NO, R_OK, w_w_exists }, + { EACCES, 0, UID_YES, UID_NO, GID_YES, GID_NO, R_OK, w_w_exists }, + { EACCES, 1, UID_NO, UID_YES, GID_NO, GID_NO, R_OK, w_w_exists }, + { EACCES, 1, UID_NO, UID_NO, GID_NO, GID_YES, R_OK, w_w_exists }, + /* can search to it, but the file doesn't have the right read perm */ + { EACCES, 0, UID_YES, UID_NO, GID_NO, GID_NO, R_OK, w_r_exists }, + { EACCES, 0, UID_NO, UID_NO, GID_YES, GID_NO, R_OK, r_w_exists }, + { EACCES, 1, UID_NO, UID_YES, GID_NO, GID_NO, R_OK, w_r_exists }, + { EACCES, 1, UID_NO, UID_NO, GID_NO, GID_YES, R_OK, r_w_exists }, + /* if correct user, then group perms are ignored */ + { EACCES, 0, UID_YES, UID_NO, GID_YES, GID_NO, R_OK, w_r_exists }, + { EACCES, 1, UID_NO, UID_YES, GID_NO, GID_YES, R_OK, w_r_exists }, + { EACCES, 0, UID_YES, UID_YES, GID_YES, GID_YES, R_OK, w_r_exists }, + { EACCES, 1, UID_YES, UID_YES, GID_YES, GID_YES, R_OK, w_r_exists }, + + /* positive tests */ + { 0, 0, UID_YES, UID_NO, GID_NO, GID_NO, R_OK, r_w_exists }, + { 0, 0, UID_NO, UID_NO, GID_YES, GID_NO, R_OK, w_r_exists }, + { 0, 0, UID_YES, UID_NO, GID_YES, GID_NO, R_OK, r_w_exists }, + { 0, 0, UID_YES, UID_NO, GID_YES, GID_NO, R_OK, r_r_exists }, + { 0, 1, UID_NO, UID_YES, GID_NO, GID_NO, R_OK, r_w_exists }, + { 0, 1, UID_NO, UID_NO, GID_NO, GID_YES, R_OK, w_r_exists }, + { 0, 1, UID_NO, UID_YES, GID_NO, GID_YES, R_OK, r_w_exists }, + { 0, 1, UID_NO, UID_YES, GID_NO, GID_YES, R_OK, r_r_exists }, + + { 0, 0, UID_YES, UID_YES, GID_YES, GID_YES, R_OK, r_w_exists }, + { 0, 0, UID_YES, UID_YES, GID_YES, GID_YES, R_OK, r_r_exists }, + { 0, 1, UID_YES, UID_YES, GID_YES, GID_YES, R_OK, r_w_exists }, + { 0, 1, UID_YES, UID_YES, GID_YES, GID_YES, R_OK, r_r_exists }, + + { 0 } +}; + +static void +prepfile(const char *filename, mode_t mode) +{ + int fd; + + if ((fd = open(filename, O_WRONLY|O_CREAT, 600)) < 0) + err(1, "open %s", filename); + close(fd); + if (chown(filename, UID_YES, GID_YES)) + err(1, "chown %s %d:%d", filename, UID_YES, GID_YES); + if (chmod(filename, mode)) + err(1, "chmod %s %o", filename, mode); +} + +static void +docleanup(void) +{ + setresuid(0, 0, 0); + remove(exists); + remove(r_r_exists); + remove(r_w_exists); + remove(w_r_exists); + remove(w_w_exists); + remove(x_x_exists); + remove(dir); + chdir("/"); + remove(temp); +} + +int +main(int argc, char *argv[]) +{ + char buf[200]; + struct tests *t; + int ret, result; + gid_t supp_group = GID_NO; + + if (geteuid() != 0) { + if (getuid() != 0) + errx(0, "must be run as root"); + else if (setuid(0)) + err(1, "setuid"); + } + if (setgroups(1, &supp_group)) + err(1, "setgroups"); + + if (mkdtemp(temp) == NULL) + err(1, "mkdtemp"); + + if (chdir(temp)) { + ret = errno; + remove(temp); + errc(1, ret, "chdir"); + } + if (chmod(temp, 0755)) + err(1, "chmod %s %o", temp, 0755); + + atexit(docleanup); + + umask(0); + if (mkdir(dir, 0750)) + err(1, "mkdir"); + prepfile(exists, 0); + prepfile(r_r_exists, 0440); + prepfile(r_w_exists, 0420); + prepfile(w_r_exists, 0240); + prepfile(w_w_exists, 0220); + prepfile(x_x_exists, 0110); + if (chown(dir, UID_YES, GID_YES)) + err(1, "chown %s %d:%d", dir, UID_YES, GID_YES); + + result = 0; + for (t = tests; t->filename != NULL; t++) { + if (setresgid(t->rgid, t->egid, 0)) + err(1, "setresgid"); + if (setresuid(t->ruid, t->euid, 0)) + err(1, "setresuid"); + ret = faccessat(AT_FDCWD, t->filename, t->amode, + t->eaccess ? AT_EACCESS : 0); + if (ret) { + ret = errno; + strerror_r(ret, buf, sizeof buf); + } + if (ret != t->err) { + result = 1; + warnx("uid %d/%d gid %d/%d mode %d eaccess %d %s:" + " %s instead of %s", + t->ruid, t->euid, t->rgid, t->egid, + t->amode, t->eaccess, t->filename, + ret ? buf : "success", + t->err ? strerror(t->err) : "success"); + } + if (setresuid(0, 0, 0)) + err(1, "setresuid restore"); + } + + return (result); +} -- 2.20.1