setns01.c revision eecee42404c961f6ee63ecaffd144b91fb1ca6a2
1/* 2 * Copyright (C) 2013 Linux Test Project, Inc. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of version 2 of the GNU General Public 6 * License as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it would be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * Further, this software is distributed without any warranty that it 13 * is free of the rightful claim of any third person regarding 14 * infringement or the like. Any license provided herein, whether 15 * implied or otherwise, applies only to this software file. Patent 16 * licenses, if any, provided herein do not apply to combinations of 17 * this program with other software, or any other product whatsoever. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write the Free Software 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 22 * 02110-1301, USA. 23 */ 24/* 25 * errno tests for setns(2) - reassociate thread with a namespace 26 */ 27#define _GNU_SOURCE 28#include <sys/stat.h> 29#include <sys/syscall.h> 30#include <sys/types.h> 31#include <errno.h> 32#include <sched.h> 33#include <pwd.h> 34#include <string.h> 35#include "config.h" 36#include "test.h" 37#include "usctest.h" 38#include "linux_syscall_numbers.h" 39#include "safe_macros.h" 40 41char *TCID = "setns01"; 42 43#if defined(__NR_setns) 44#include "setns.h" 45 46struct testcase_t { 47 const char *msg; 48 int fd; 49 int ns_type; 50 int exp_ret; 51 int exp_errno; 52 int skip; 53 void (*setup) (struct testcase_t *, int i); 54 void (*cleanup) (struct testcase_t *); 55}; 56 57static void setup(void); 58static void cleanup(void); 59static void setup0(struct testcase_t *, int); 60static void setup1(struct testcase_t *, int); 61static void setup2(struct testcase_t *, int); 62static void setup3(struct testcase_t *, int); 63static void setup4(struct testcase_t *, int); 64static void cleanup1(struct testcase_t *); 65static void cleanup4(struct testcase_t *); 66 67struct testcase_t tdat[] = { 68 { 69 .msg = "invalid fd", 70 .fd = -1, 71 .exp_ret = -1, 72 .exp_errno = EBADF, 73 .setup = setup0, 74 }, 75 { 76 .msg = "regular file fd", 77 .exp_ret = -1, 78 .exp_errno = EINVAL, 79 .setup = setup1, 80 .cleanup = cleanup1 81 }, 82 { 83 .msg = "invalid ns_type", 84 .ns_type = -1, 85 .exp_ret = -1, 86 .exp_errno = EINVAL, 87 .setup = setup2, 88 }, 89 { 90 .msg = "mismatch ns_type/fd", 91 .exp_ret = -1, 92 .exp_errno = EINVAL, 93 .setup = setup3, 94 }, 95 { 96 .msg = "without CAP_SYS_ADMIN", 97 .exp_ret = -1, 98 .exp_errno = EPERM, 99 .setup = setup4, 100 .cleanup = cleanup4, 101 } 102}; 103 104static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); 105static const char nobody_uid[] = "nobody"; 106static struct passwd *ltpuser; 107 108static void setup0(struct testcase_t *t, int i) 109{ 110 t->ns_type = ns_types[i]; 111} 112 113static void setup1(struct testcase_t *t, int i) 114{ 115 t->ns_type = ns_types[i]; 116 t->fd = open("dummy", O_RDWR|O_CREAT, 0600); 117 if (t->fd == -1) 118 tst_brkm(TFAIL|TERRNO, cleanup, "setup1:open failed"); 119 unlink("dummy"); 120} 121 122static void cleanup1(struct testcase_t *t) 123{ 124 close(t->fd); 125} 126 127static void setup2(struct testcase_t *t, int i) 128{ 129 t->fd = ns_fds[i]; 130} 131 132static void setup3(struct testcase_t *t, int i) 133{ 134 if (ns_total < 2) { 135 t->skip = 1; 136 return; 137 } 138 139 t->fd = ns_fds[i]; 140 t->ns_type = ns_types[(i+1) % ns_total]; 141} 142 143static void setup4(struct testcase_t *t, int i) 144{ 145 if (seteuid(ltpuser->pw_uid) == -1) 146 tst_brkm(TBROK | TERRNO, NULL, "seteuid failed"); 147 148 t->fd = ns_fds[i]; 149 t->ns_type = ns_types[i]; 150} 151 152static void cleanup4(struct testcase_t *t) 153{ 154 if (seteuid(0) == -1) 155 tst_brkm(TBROK | TERRNO, NULL, "seteuid restore failed"); 156} 157 158static void test_setns(struct testcase_t *t) 159{ 160 int ret, i; 161 162 for (i = 0; i < ns_total; i++) { 163 if (t->setup) 164 t->setup(t, i); 165 166 if (t->skip) { 167 tst_resm(TINFO, "skip %s", tdat->msg); 168 continue; 169 } 170 171 tst_resm(TINFO, "setns(%d, 0x%x)", t->fd, t->ns_type); 172 ret = syscall(__NR_setns, t->fd, t->ns_type); 173 if (ret == t->exp_ret) { 174 if (ret == -1 && errno == t->exp_errno) 175 tst_resm(TPASS, "%s exp_errno=%d", t->msg, 176 t->exp_errno); 177 else 178 tst_resm(TFAIL|TERRNO, "%s exp_errno=%d", 179 t->msg, t->exp_errno); 180 } else { 181 tst_resm(TFAIL, "%s ret=%d expected=%d", t->msg, 182 ret, t->exp_ret); 183 } 184 185 if (t->cleanup) 186 t->cleanup(t); 187 } 188} 189 190int main(int argc, char *argv[]) 191{ 192 int lc, testno; 193 char *msg; 194 195 msg = parse_opts(argc, argv, NULL, NULL); 196 if (msg != NULL) 197 tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg); 198 199 setup(); 200 for (lc = 0; TEST_LOOPING(lc); lc++) { 201 for (testno = 0; testno < TST_TOTAL; testno++) 202 test_setns(&tdat[testno]); 203 } 204 cleanup(); 205 tst_exit(); 206} 207 208static void setup(void) 209{ 210 tst_require_root(NULL); 211 212 /* runtime check if syscall is supported */ 213 ltp_syscall(__NR_setns, -1, 0); 214 215 init_available_ns(); 216 if (ns_total == 0) 217 tst_brkm(TCONF, NULL, "no ns types/proc entries"); 218 219 ltpuser = getpwnam(nobody_uid); 220 if (ltpuser == NULL) 221 tst_brkm(TBROK | TERRNO, NULL, "getpwnam failed"); 222 223 224 tst_tmpdir(); 225 TEST_PAUSE; 226} 227 228static void cleanup(void) 229{ 230 close_ns_fds(); 231 tst_rmdir(); 232 TEST_CLEANUP; 233} 234#else 235int main(int argc, char *argv[]) 236{ 237 tst_brkm(TCONF, NULL, "__NR_setns is not defined on your system."); 238 239} 240#endif 241