1272343Sngie/* $NetBSD: t_unpriv.c,v 1.11 2014/08/29 17:39:18 gson Exp $ */ 2272343Sngie 3272343Sngie/*- 4272343Sngie * Copyright (c) 2011 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * Redistribution and use in source and binary forms, with or without 8272343Sngie * modification, are permitted provided that the following conditions 9272343Sngie * are met: 10272343Sngie * 1. Redistributions of source code must retain the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer. 12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 13272343Sngie * notice, this list of conditions and the following disclaimer in the 14272343Sngie * documentation and/or other materials provided with the distribution. 15272343Sngie * 16272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26272343Sngie * POSSIBILITY OF SUCH DAMAGE. 27272343Sngie */ 28272343Sngie 29272343Sngie#include <sys/stat.h> 30272343Sngie#include <sys/time.h> 31272343Sngie 32272343Sngie#include <atf-c.h> 33272343Sngie#include <libgen.h> 34272343Sngie#include <limits.h> 35272343Sngie#include <unistd.h> 36272343Sngie 37272343Sngie#include <rump/rump_syscalls.h> 38272343Sngie#include <rump/rump.h> 39272343Sngie 40272343Sngie#include "../common/h_fsmacros.h" 41272343Sngie#include "../../h_macros.h" 42272343Sngie 43272343Sngie#define USES_OWNER \ 44272343Sngie if (FSTYPE_MSDOS(tc)) \ 45272343Sngie atf_tc_skip("owner not supported by file system") 46272343Sngie 47272343Sngiestatic void 48272343Sngieowner(const atf_tc_t *tc, const char *mp) 49272343Sngie{ 50272343Sngie 51272343Sngie USES_OWNER; 52272343Sngie 53272343Sngie FSTEST_ENTER(); 54272343Sngie 55272343Sngie rump_pub_lwproc_rfork(RUMP_RFCFDG); 56272343Sngie if (rump_sys_setuid(1) == -1) 57272343Sngie atf_tc_fail_errno("setuid"); 58272343Sngie if (FSTYPE_ZFS(tc)) 59272343Sngie atf_tc_expect_fail("PR kern/47656: Test known to be broken"); 60272343Sngie if (rump_sys_chown(".", 1, -1) != -1 || errno != EPERM) 61272343Sngie atf_tc_fail_errno("chown"); 62272343Sngie if (rump_sys_chmod(".", 0000) != -1 || errno != EPERM) 63272343Sngie atf_tc_fail_errno("chmod"); 64272343Sngie rump_pub_lwproc_releaselwp(); 65272343Sngie 66272343Sngie if (rump_sys_chown(".", 1, -1) == -1) 67272343Sngie atf_tc_fail_errno("chown"); 68272343Sngie 69272343Sngie rump_pub_lwproc_rfork(RUMP_RFCFDG); 70272343Sngie if (rump_sys_setuid(1) == -1) 71272343Sngie atf_tc_fail_errno("setuid"); 72272343Sngie if (rump_sys_chown(".", 1, -1) == -1) 73272343Sngie atf_tc_fail_errno("chown"); 74272343Sngie if (rump_sys_chmod(".", 0000) == -1) 75272343Sngie atf_tc_fail_errno("chmod"); 76272343Sngie rump_pub_lwproc_releaselwp(); 77272343Sngie 78272343Sngie FSTEST_EXIT(); 79272343Sngie} 80272343Sngie 81272343Sngiestatic void 82272343Sngiedirperms(const atf_tc_t *tc, const char *mp) 83272343Sngie{ 84272343Sngie char name[] = "dir.test/file.test"; 85272343Sngie char *dir = dirname(name); 86272343Sngie int fd; 87272343Sngie 88272343Sngie if (FSTYPE_SYSVBFS(tc)) 89272343Sngie atf_tc_skip("directories not supported by file system"); 90272343Sngie 91272343Sngie FSTEST_ENTER(); 92272343Sngie 93272343Sngie if (rump_sys_mkdir(dir, 0777) == -1) 94272343Sngie atf_tc_fail_errno("mkdir"); 95272343Sngie 96272343Sngie rump_pub_lwproc_rfork(RUMP_RFCFDG); 97272343Sngie if (rump_sys_setuid(1) == -1) 98272343Sngie atf_tc_fail_errno("setuid"); 99272343Sngie if (FSTYPE_ZFS(tc)) 100272343Sngie atf_tc_expect_fail("PR kern/47656: Test known to be broken"); 101272343Sngie if (rump_sys_open(name, O_RDWR|O_CREAT, 0666) != -1 || errno != EACCES) 102272343Sngie atf_tc_fail_errno("open"); 103272343Sngie rump_pub_lwproc_releaselwp(); 104272343Sngie 105272343Sngie if ((fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666)) == -1) 106272343Sngie atf_tc_fail_errno("open"); 107272343Sngie if (rump_sys_close(fd) == -1) 108272343Sngie atf_tc_fail_errno("close"); 109272343Sngie 110272343Sngie rump_pub_lwproc_rfork(RUMP_RFCFDG); 111272343Sngie if (rump_sys_setuid(1) == -1) 112272343Sngie atf_tc_fail_errno("setuid"); 113272343Sngie if (rump_sys_unlink(name) != -1 || errno != EACCES) 114272343Sngie atf_tc_fail_errno("unlink"); 115272343Sngie rump_pub_lwproc_releaselwp(); 116272343Sngie 117272343Sngie if (rump_sys_unlink(name) == -1) 118272343Sngie atf_tc_fail_errno("unlink"); 119272343Sngie 120272343Sngie if (rump_sys_rmdir(dir) == -1) 121272343Sngie atf_tc_fail_errno("rmdir"); 122272343Sngie 123272343Sngie FSTEST_EXIT(); 124272343Sngie} 125272343Sngie 126272343Sngiestatic void 127272343Sngietimes(const atf_tc_t *tc, const char *mp) 128272343Sngie{ 129272343Sngie const char *name = "file.test"; 130272343Sngie int fd; 131272343Sngie unsigned int i, j; 132272343Sngie struct timeval tmv[2]; 133272343Sngie static struct timeval tmvs[] = { 134272343Sngie { QUAD_MIN, 0 }, 135272343Sngie { 0, 0 }, 136272343Sngie { QUAD_MAX, 999999 } 137272343Sngie }; 138272343Sngie 139272343Sngie FSTEST_ENTER(); 140272343Sngie 141272343Sngie if ((fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666)) == -1) 142272343Sngie atf_tc_fail_errno("open"); 143272343Sngie if (rump_sys_close(fd) == -1) 144272343Sngie atf_tc_fail_errno("close"); 145272343Sngie 146272343Sngie rump_pub_lwproc_rfork(RUMP_RFCFDG); 147272343Sngie if (rump_sys_setuid(1) == -1) 148272343Sngie atf_tc_fail_errno("setuid"); 149272343Sngie if (FSTYPE_ZFS(tc)) 150272343Sngie atf_tc_expect_fail("PR kern/47656: Test known to be broken"); 151272343Sngie if (rump_sys_utimes(name, NULL) != -1 || errno != EACCES) 152272343Sngie atf_tc_fail_errno("utimes"); 153272343Sngie rump_pub_lwproc_releaselwp(); 154272343Sngie 155272343Sngie if (rump_sys_utimes(name, NULL) == -1) 156272343Sngie atf_tc_fail_errno("utimes"); 157272343Sngie 158272343Sngie for (i = 0; i < sizeof(tmvs) / sizeof(tmvs[0]); i++) { 159272343Sngie for (j = 0; j < sizeof(tmvs) / sizeof(tmvs[0]); j++) { 160272343Sngie tmv[0] = tmvs[i]; 161272343Sngie tmv[1] = tmvs[j]; 162272343Sngie rump_pub_lwproc_rfork(RUMP_RFCFDG); 163272343Sngie if (rump_sys_setuid(1) == -1) 164272343Sngie atf_tc_fail_errno("setuid"); 165272343Sngie if (rump_sys_utimes(name, tmv) != -1 || errno != EPERM) 166272343Sngie atf_tc_fail_errno("utimes"); 167272343Sngie rump_pub_lwproc_releaselwp(); 168272343Sngie 169272343Sngie if (rump_sys_utimes(name, tmv) == -1) 170272343Sngie atf_tc_fail_errno("utimes"); 171272343Sngie } 172272343Sngie } 173272343Sngie 174272343Sngie if (rump_sys_unlink(name) == -1) 175272343Sngie atf_tc_fail_errno("unlink"); 176272343Sngie 177272343Sngie FSTEST_EXIT(); 178272343Sngie} 179272343Sngie 180272343Sngiestatic void 181272343Sngieflags(const atf_tc_t *tc, const char *mp) 182272343Sngie{ 183272343Sngie const char *name = "file.test"; 184272343Sngie int fd, fflags; 185272343Sngie struct stat st; 186272343Sngie 187272343Sngie FSTEST_ENTER(); 188272343Sngie 189272343Sngie if ((fd = rump_sys_open(name, O_RDWR|O_CREAT, 0666)) == -1) 190272343Sngie atf_tc_fail_errno("open"); 191272343Sngie if (rump_sys_close(fd) == -1) 192272343Sngie atf_tc_fail_errno("close"); 193272343Sngie 194272343Sngie if (rump_sys_stat(name, &st) == -1) 195272343Sngie atf_tc_fail_errno("stat"); 196272343Sngie if (FSTYPE_ZFS(tc)) 197272343Sngie atf_tc_expect_fail("PR kern/47656: Test known to be broken"); 198272343Sngie if (rump_sys_chflags(name, st.st_flags) == -1) { 199272343Sngie if (errno == EOPNOTSUPP) 200272343Sngie atf_tc_skip("file flags not supported by file system"); 201272343Sngie atf_tc_fail_errno("chflags"); 202272343Sngie } 203272343Sngie 204272343Sngie fflags = st.st_flags | UF_IMMUTABLE; 205272343Sngie 206272343Sngie rump_pub_lwproc_rfork(RUMP_RFCFDG); 207272343Sngie if (rump_sys_setuid(1) == -1) 208272343Sngie atf_tc_fail_errno("setuid"); 209272343Sngie fflags |= UF_IMMUTABLE; 210272343Sngie if (rump_sys_chflags(name, fflags) != -1 || errno != EPERM) 211272343Sngie atf_tc_fail_errno("chflags"); 212272343Sngie rump_pub_lwproc_releaselwp(); 213272343Sngie 214272343Sngie if (rump_sys_chflags(name, fflags) == -1) 215272343Sngie atf_tc_fail_errno("chflags"); 216272343Sngie 217272343Sngie fflags &= ~UF_IMMUTABLE; 218272343Sngie if (rump_sys_chflags(name, fflags) == -1) 219272343Sngie atf_tc_fail_errno("chflags"); 220272343Sngie 221272343Sngie if (rump_sys_unlink(name) == -1) 222272343Sngie atf_tc_fail_errno("unlink"); 223272343Sngie 224272343Sngie FSTEST_EXIT(); 225272343Sngie} 226272343Sngie 227272343SngieATF_TC_FSAPPLY(owner, "owner unprivileged checks"); 228272343SngieATF_TC_FSAPPLY(dirperms, "directory permission checks"); 229272343SngieATF_TC_FSAPPLY(times, "time set checks"); 230272343SngieATF_TC_FSAPPLY(flags, "file flags checks"); 231272343Sngie 232272343SngieATF_TP_ADD_TCS(tp) 233272343Sngie{ 234272343Sngie 235272343Sngie ATF_TP_FSAPPLY(owner); 236272343Sngie ATF_TP_FSAPPLY(dirperms); 237272343Sngie ATF_TP_FSAPPLY(times); 238272343Sngie ATF_TP_FSAPPLY(flags); 239272343Sngie 240272343Sngie return atf_no_error(); 241272343Sngie} 242