From: Jan S. <jst...@re...> - 2013-02-05 15:57:51
|
This patchset adds 2 new syscall tests for setns(2). Sample output: setns01 1 TPASS : invalid fd exp_errno=9 setns01 2 TPASS : regular file fd exp_errno=22 setns01 3 TPASS : invalid ns_type exp_errno=22 setns01 4 TPASS : mismatch ns_type/fd exp_errno=22 setns01 5 TPASS : without CAP_SYS_ADMIN exp_errno=1 setns02 0 TINFO : test_newuts setns02 0 TINFO : creating child with clone_flag=0x4000000, ns_flag=0x4000000 setns02 0 TINFO : (child) hostnane (inherited from parent): dhcp-27-145.brq.redhat.com setns02 0 TINFO : (child) hostname changed to: setns_dummy_uts setns02 1 TPASS : (child) hostname is different in parent/child setns02 0 TINFO : (child) attemping to switch ns back to parent ns setns02 0 TINFO : (child) hostname: dhcp-27-145.brq.redhat.com setns02 2 TPASS : (child) hostname now as expected setns02 1 TPASS : child finished succesfully setns02 0 TINFO : creating child with clone_flag=0x4000000, ns_flag=0x0 setns02 0 TINFO : (child) hostnane (inherited from parent): dhcp-27-145.brq.redhat.com setns02 0 TINFO : (child) hostname changed to: setns_dummy_uts setns02 2 TPASS : (child) hostname is different in parent/child setns02 0 TINFO : (child) attemping to switch ns back to parent ns setns02 0 TINFO : (child) hostname: dhcp-27-145.brq.redhat.com setns02 3 TPASS : (child) hostname now as expected setns02 2 TPASS : child finished succesfully setns02 0 TINFO : test_newipc setns02 0 TINFO : creating child with clone_flag=0x8000000, ns_flag=0x8000000 setns02 3 TPASS : (child) shmat failed as expected: errno=EINVAL(22): Invalid argument setns02 0 TINFO : (child) attemping to switch ns back to parent ns setns02 4 TPASS : (child) shmat suceeded setns02 3 TPASS : child finished succesfully setns02 0 TINFO : creating child with clone_flag=0x8000000, ns_flag=0x0 setns02 4 TPASS : (child) shmat failed as expected: errno=EINVAL(22): Invalid argument setns02 0 TINFO : (child) attemping to switch ns back to parent ns setns02 5 TPASS : (child) shmat suceeded setns02 4 TPASS : child finished succesfully Jan Stancek (3): setns: setup directory at kernel/syscalls/setns setns: add new syscall test setns01 setns: add new syscall test setns02 runtest/syscalls | 3 + testcases/kernel/syscalls/.gitignore | 2 + testcases/kernel/syscalls/setns/Makefile | 22 +++ testcases/kernel/syscalls/setns/setns.h | 41 +++++ testcases/kernel/syscalls/setns/setns01.c | 245 +++++++++++++++++++++++++++++ testcases/kernel/syscalls/setns/setns02.c | 231 +++++++++++++++++++++++++++ 6 files changed, 544 insertions(+), 0 deletions(-) create mode 100644 testcases/kernel/syscalls/setns/Makefile create mode 100644 testcases/kernel/syscalls/setns/setns.h create mode 100644 testcases/kernel/syscalls/setns/setns01.c create mode 100644 testcases/kernel/syscalls/setns/setns02.c |
From: Jan S. <jst...@re...> - 2013-02-05 15:57:52
|
Signed-off-by: Jan Stancek <jst...@re...> --- testcases/kernel/syscalls/setns/Makefile | 22 ++++++++++++++++++++++ 1 files changed, 22 insertions(+), 0 deletions(-) create mode 100644 testcases/kernel/syscalls/setns/Makefile diff --git a/testcases/kernel/syscalls/setns/Makefile b/testcases/kernel/syscalls/setns/Makefile new file mode 100644 index 0000000..b1179c4 --- /dev/null +++ b/testcases/kernel/syscalls/setns/Makefile @@ -0,0 +1,22 @@ +# +# Copyright (C) 2013 Linux Test Project, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +# the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +top_srcdir ?= ../../../.. + +include $(top_srcdir)/include/mk/testcases.mk +include $(top_srcdir)/include/mk/generic_leaf_target.mk -- 1.7.1 |
From: Wanlong G. <gao...@cn...> - 2013-02-06 08:45:03
|
On 02/05/2013 11:57 PM, Jan Stancek wrote: > Signed-off-by: Jan Stancek <jst...@re...> Acked-by: Wanlong Gao <gao...@cn...> > --- > testcases/kernel/syscalls/setns/Makefile | 22 ++++++++++++++++++++++ > 1 files changed, 22 insertions(+), 0 deletions(-) > create mode 100644 testcases/kernel/syscalls/setns/Makefile > > diff --git a/testcases/kernel/syscalls/setns/Makefile b/testcases/kernel/syscalls/setns/Makefile > new file mode 100644 > index 0000000..b1179c4 > --- /dev/null > +++ b/testcases/kernel/syscalls/setns/Makefile > @@ -0,0 +1,22 @@ > +# > +# Copyright (C) 2013 Linux Test Project, Inc. > +# > +# This program is free software; you can redistribute it and/or modify > +# it under the terms of the GNU General Public License as published by > +# the Free Software Foundation; either version 2 of the License, or > +# (at your option) any later version. > +# > +# This program is distributed in the hope that it will be useful, > +# but WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > +# the GNU General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program; if not, write to the Free Software > +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA > +# > + > +top_srcdir ?= ../../../.. > + > +include $(top_srcdir)/include/mk/testcases.mk > +include $(top_srcdir)/include/mk/generic_leaf_target.mk > |
From: Jan S. <jst...@re...> - 2013-02-05 15:57:53
|
errno tests for setns(2) - reassociate thread with a namespace Signed-off-by: Jan Stancek <jst...@re...> --- runtest/syscalls | 2 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/setns/setns.h | 41 +++++ testcases/kernel/syscalls/setns/setns01.c | 245 +++++++++++++++++++++++++++++ 4 files changed, 289 insertions(+), 0 deletions(-) create mode 100644 testcases/kernel/syscalls/setns/setns.h create mode 100644 testcases/kernel/syscalls/setns/setns01.c diff --git a/runtest/syscalls b/runtest/syscalls index db5a075..a881479 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -962,6 +962,8 @@ setitimer01 setitimer01 setitimer02 setitimer02 setitimer03 setitimer03 +setns01 setns01 + setpgid01 setpgid01 setpgid02 setpgid02 setpgid03 setpgid03 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index 003c5d0..d3bf8b7 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -763,6 +763,7 @@ /setitimer/setitimer01 /setitimer/setitimer02 /setitimer/setitimer03 +/setns/setns01 /setpgid/setpgid01 /setpgid/setpgid02 /setpgid/setpgid03 diff --git a/testcases/kernel/syscalls/setns/setns.h b/testcases/kernel/syscalls/setns/setns.h new file mode 100644 index 0000000..1613e6c --- /dev/null +++ b/testcases/kernel/syscalls/setns/setns.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2013 Linux Test Project, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +static int get_ns_fd(int pid, const char *ns) +{ + char tmp[PATH_MAX]; + struct stat st; + int fd = -1; + + sprintf(tmp, "/proc/%d/%s", pid, ns); + if (stat(tmp, &st) == 0) { + fd = open(tmp, O_RDONLY); + if (fd == -1) + tst_brkm(TBROK|TERRNO, NULL, "failed to open %s", tmp); + } else { + if (errno != ENOENT) + tst_brkm(TBROK|TERRNO, NULL, "failed to stat %s", tmp); + } + return fd; +} diff --git a/testcases/kernel/syscalls/setns/setns01.c b/testcases/kernel/syscalls/setns/setns01.c new file mode 100644 index 0000000..6469266 --- /dev/null +++ b/testcases/kernel/syscalls/setns/setns01.c @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2013 Linux Test Project, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +/* + * errno tests for setns(2) - reassociate thread with a namespace + */ +#define _GNU_SOURCE +#include <sys/stat.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <errno.h> +#include <sched.h> +#include <pwd.h> +#include <string.h> +#include "config.h" +#include "test.h" +#include "usctest.h" +#include "linux_syscall_numbers.h" +#include "safe_macros.h" + +#define NS_TOTAL 3 +char *TCID = "setns01"; + +#if defined(__NR_setns) && defined(CLONE_NEWIPC) && defined(CLONE_NEWUTS) \ + && defined(CLONE_NEWNET) +#include "setns.h" + +struct testcase_t { + const char *msg; + int fd; + int ns_type; + int exp_ret; + int exp_errno; + int skip; + void (*setup) (struct testcase_t *); + void (*cleanup) (struct testcase_t *); +}; + +static void setup(void); +static void cleanup(void); +static void setup1(struct testcase_t *); +static void setup2(struct testcase_t *); +static void setup3(struct testcase_t *); +static void setup4(struct testcase_t *); +static void cleanup1(struct testcase_t *); +static void cleanup4(struct testcase_t *); + +struct testcase_t tdat[] = { + { + .msg = "invalid fd", + .fd = -1, + .ns_type = CLONE_NEWIPC, + .exp_ret = -1, + .exp_errno = EBADF, + }, + { + .msg = "regular file fd", + .ns_type = CLONE_NEWIPC, + .exp_ret = -1, + .exp_errno = EINVAL, + .setup = setup1, + .cleanup = cleanup1 + }, + { + .msg = "invalid ns_type", + .ns_type = -1, + .exp_ret = -1, + .exp_errno = EINVAL, + .setup = setup2, + }, + { + .msg = "mismatch ns_type/fd", + .exp_ret = -1, + .exp_errno = EINVAL, + .setup = setup3, + }, + { + .msg = "without CAP_SYS_ADMIN", + .exp_ret = -1, + .exp_errno = EPERM, + .setup = setup4, + .cleanup = cleanup4, + } +}; + +static const char *ns_names[NS_TOTAL] = {"ns/ipc", "ns/net", "ns/uts"}; +static int ns_types[NS_TOTAL] = { CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWUTS }; +static int ns_fds[NS_TOTAL]; +static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); +static const char nobody_uid[] = "nobody"; +static struct passwd *ltpuser; + +static void setup1(struct testcase_t *t) +{ + t->fd = open("dummy", O_CREAT); + if (t->fd == -1) + tst_brkm(TFAIL|TERRNO, cleanup, "setup1:open failed"); + unlink("dummy"); +} + +static void cleanup1(struct testcase_t *t) +{ + close(t->fd); +} + +static void setup2(struct testcase_t *t) +{ + int i; + for (i = 0; i < NS_TOTAL; i++) + if (ns_fds[i] != -1) { + t->fd = ns_fds[i]; + return; + } + t->skip = 1; +} + +static void setup3(struct testcase_t *t) +{ + int i; + for (i = 0; i < NS_TOTAL; i++) + if (ns_fds[i] != -1) { + t->fd = ns_fds[i]; + t->ns_type = ns_types[(i+1) % NS_TOTAL]; + return; + } + t->skip = 1; +} + +static void setup4(struct testcase_t *t) +{ + if (seteuid(ltpuser->pw_uid) == -1) + tst_brkm(TBROK | TERRNO, NULL, "seteuid failed"); +} + +static void cleanup4(struct testcase_t *t) +{ + if (seteuid(0) == -1) + tst_brkm(TBROK | TERRNO, NULL, "seteuid restore failed"); +} + +static void test_setns(struct testcase_t *t) +{ + int ret; + + if (t->setup) + t->setup(t); + + if (t->skip) { + tst_resm(TINFO, "skip %s", tdat->msg); + return; + } + + ret = syscall(__NR_setns, t->fd, t->ns_type); + if (ret == t->exp_ret) { + if (ret == -1 && errno == t->exp_errno) + tst_resm(TPASS, "%s exp_errno=%d", t->msg, + t->exp_errno); + else + tst_resm(TFAIL|TERRNO, "%s exp_errno=%d", t->msg, + t->exp_errno); + } else { + tst_resm(TFAIL, "%s ret=%d expected=%d", t->msg, + ret, t->exp_ret); + } + + if (t->cleanup) + t->cleanup(t); +} + +int main(int argc, char *argv[]) +{ + int lc, testno; + char *msg; + + msg = parse_opts(argc, argv, NULL, NULL); + if (msg != NULL) + tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg); + + setup(); + for (lc = 0; TEST_LOOPING(lc); lc++) { + for (testno = 0; testno < TST_TOTAL; testno++) + test_setns(&tdat[testno]); + } + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + int i; + + tst_require_root(NULL); + + /* runtime check if syscall is supported */ + syscall(__NR_setns, -1, 0); + + ltpuser = getpwnam(nobody_uid); + if (ltpuser == NULL) + tst_brkm(TBROK | TERRNO, NULL, "getpwnam failed"); + + for (i = 0; i < NS_TOTAL; i++) + ns_fds[i] = get_ns_fd(getpid(), ns_names[i]); + + tst_tmpdir(); + TEST_PAUSE; +} + +static void cleanup(void) +{ + int i; + + for (i = 0; i < NS_TOTAL; i++) + if (ns_fds[i] != -1) + close(ns_fds[i]); + tst_rmdir(); + TEST_CLEANUP; +} +#else +int main(int argc, char *argv[]) +{ + tst_brkm(TCONF, NULL, "__NR_setns, CLONE_NEWIPC, CLONE_NEWNET or " + "CLONE_NEWUTS is not defined on your system."); + +} +#endif -- 1.7.1 |
From: Jan S. <jst...@re...> - 2013-02-05 15:57:55
|
functional test for setns(2) - reassociate thread with a namespace Signed-off-by: Jan Stancek <jst...@re...> --- runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/setns/setns02.c | 231 +++++++++++++++++++++++++++++ 3 files changed, 233 insertions(+), 0 deletions(-) create mode 100644 testcases/kernel/syscalls/setns/setns02.c diff --git a/runtest/syscalls b/runtest/syscalls index a881479..c70bcbd 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -963,6 +963,7 @@ setitimer02 setitimer02 setitimer03 setitimer03 setns01 setns01 +setns02 setns02 setpgid01 setpgid01 setpgid02 setpgid02 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index d3bf8b7..90b521e 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -764,6 +764,7 @@ /setitimer/setitimer02 /setitimer/setitimer03 /setns/setns01 +/setns/setns02 /setpgid/setpgid01 /setpgid/setpgid02 /setpgid/setpgid03 diff --git a/testcases/kernel/syscalls/setns/setns02.c b/testcases/kernel/syscalls/setns/setns02.c new file mode 100644 index 0000000..fa8ea74 --- /dev/null +++ b/testcases/kernel/syscalls/setns/setns02.c @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2013 Linux Test Project, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +/* + * functional test for setns(2) - reassociate thread with a namespace + * 1. create child with CLONE_NEWUTS, set different hostname in child, + * set namespace back to parent ns and check that hostname has changed + * 2. create child with CLONE_NEWIPC, set up shared memory in parent + * and verify that child can't shmat it, then set namespace + * back to parent one and verify that child is able to do shmat + */ +#define _GNU_SOURCE +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/stat.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <sys/utsname.h> +#include <sys/wait.h> +#include <errno.h> +#include <sched.h> +#include <string.h> +#include "config.h" +#include "test.h" +#include "usctest.h" +#include "linux_syscall_numbers.h" +#include "safe_macros.h" + +#define CHILD_STACK_SIZE (1024*1024) +#define CP "(child) " +char *TCID = "setns02"; + +#if defined(__NR_setns) && defined(CLONE_NEWIPC) && defined(CLONE_NEWUTS) +#include "setns.h" + +static char *dummy_hostname = "setns_dummy_uts"; +static int ns_ipc_fd; +static int ns_uts_fd; +static key_t ipc_key; +static int shmid; + +static void setup(void); +static void cleanup(void); + +static int do_child_newuts(void *arg) +{ + struct utsname uts, uts_parent; + int ns_flag = *(int *)arg; + + if (uname(&uts_parent) == -1) + tst_resm(TFAIL|TERRNO, CP"uname"); + tst_resm(TINFO, CP"hostnane (inherited from parent): %s", + uts_parent.nodename); + + if (sethostname(dummy_hostname, strlen(dummy_hostname)) == -1) + tst_resm(TFAIL|TERRNO, CP"sethostname"); + if (uname(&uts) == -1) + tst_resm(TFAIL|TERRNO, CP"uname"); + + tst_resm(TINFO, CP"hostname changed to: %s", uts.nodename); + if (strcmp(uts_parent.nodename, uts.nodename) == 0) { + tst_resm(TFAIL, CP"expected hostname to be different"); + return 1; + } else { + tst_resm(TPASS, CP"hostname is different in parent/child"); + } + + tst_resm(TINFO, CP"attemping to switch ns back to parent ns"); + if (syscall(__NR_setns, ns_uts_fd, ns_flag) == -1) { + tst_resm(TFAIL|TERRNO, CP"setns"); + return 2; + } + if (uname(&uts) == -1) + tst_resm(TFAIL|TERRNO, CP"uname"); + + tst_resm(TINFO, CP"hostname: %s", uts.nodename); + if (strcmp(uts_parent.nodename, uts.nodename) != 0) { + tst_resm(TFAIL, CP"expected hostname to match parent"); + return 3; + } else { + tst_resm(TPASS, CP"hostname now as expected"); + } + return 0; +} + +static int do_child_newipc(void *arg) +{ + void *p; + int ns_flag = *(int *)arg; + + p = shmat(shmid, NULL, 0); + if (p == (void *) -1) { + tst_resm(TPASS|TERRNO, CP"shmat failed as expected"); + } else { + tst_resm(TFAIL, CP"shmat unexpectedly suceeded"); + shmdt(p); + return 1; + } + + tst_resm(TINFO, CP"attemping to switch ns back to parent ns"); + if (syscall(__NR_setns, ns_ipc_fd, ns_flag) == -1) { + tst_resm(TFAIL|TERRNO, CP"setns"); + return 2; + } + + p = shmat(shmid, NULL, 0); + if (p == (void *) -1) { + tst_resm(TFAIL|TERRNO, CP"shmat failed after setns"); + return 3; + } else { + tst_resm(TPASS, CP"shmat suceeded"); + shmdt(p); + } + + return 0; +} + +static void test_flag(int clone_flag, int ns_flag, int (*fn) (void *arg)) +{ + void *child_stack; + int ret, status; + + child_stack = malloc(CHILD_STACK_SIZE); + if (child_stack == NULL) + tst_brkm(TBROK, cleanup, "Cannot allocate stack for child"); + + tst_resm(TINFO, "creating child with clone_flag=0x%x, ns_flag=0x%x", + clone_flag, ns_flag); + ret = ltp_clone(SIGCHLD|clone_flag, fn, &ns_flag, + CHILD_STACK_SIZE, child_stack); + if (ret == -1) + tst_brkm(TBROK|TERRNO, cleanup, "ltp_clone"); + + if (waitpid(ret, &status, 0) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + tst_resm(TFAIL, "child returns %d", status); + else + tst_resm(TPASS, "child finished succesfully"); + free(child_stack); +} + +int main(int argc, char *argv[]) +{ + int lc; + char *msg; + + msg = parse_opts(argc, argv, NULL, NULL); + if (msg != NULL) + tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg); + + setup(); + for (lc = 0; TEST_LOOPING(lc); lc++) { + if (ns_uts_fd != -1) { + tst_resm(TINFO, "test_newuts"); + test_flag(CLONE_NEWUTS, CLONE_NEWUTS, do_child_newuts); + test_flag(CLONE_NEWUTS, 0, do_child_newuts); + } + if (ns_ipc_fd != -1) { + tst_resm(TINFO, "test_newipc"); + test_flag(CLONE_NEWIPC, CLONE_NEWIPC, do_child_newipc); + test_flag(CLONE_NEWIPC, 0, do_child_newipc); + } + } + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + char tmp[PATH_MAX]; + + tst_require_root(NULL); + + /* runtime check if syscall is supported */ + syscall(__NR_setns, -1, 0); + + /* check if kernel has CONFIG_*_NS set and exports /proc entries */ + ns_ipc_fd = get_ns_fd(getpid(), "ns/ipc"); + ns_uts_fd = get_ns_fd(getpid(), "ns/uts"); + if (ns_ipc_fd == -1 && ns_uts_fd == -1) + tst_brkm(TCONF, NULL, "your kernel has CONFIG_IPC_NS, " + "CONFIG_UTS_NS or CONFIG_PROC disabled"); + + if (getcwd(tmp, PATH_MAX) == NULL) + tst_brkm(TBROK|TERRNO, NULL, "getcwd"); + ipc_key = ftok(tmp, 65); + shmid = shmget(ipc_key, getpagesize(), IPC_CREAT | 0666); + if (shmid == -1) + tst_brkm(TBROK|TERRNO, NULL, "shmget"); + + TEST_PAUSE; +} + +static void cleanup(void) +{ + if (ns_ipc_fd != -1) + close(ns_ipc_fd); + if (ns_uts_fd != -1) + close(ns_uts_fd); + + shmctl(shmid, IPC_RMID, NULL); + TEST_CLEANUP; +} +#else +int main(int argc, char *argv[]) +{ + tst_brkm(TCONF, NULL, "__NR_setns, CLONE_NEWIPC or CLONE_NEWUTS " + " is not defined on your system."); +} +#endif -- 1.7.1 |
From: Wanlong G. <gao...@cn...> - 2013-02-06 08:44:50
|
On 02/05/2013 11:57 PM, Jan Stancek wrote: > functional test for setns(2) - reassociate thread with a namespace > > Signed-off-by: Jan Stancek <jst...@re...> > --- > runtest/syscalls | 1 + > testcases/kernel/syscalls/.gitignore | 1 + > testcases/kernel/syscalls/setns/setns02.c | 231 +++++++++++++++++++++++++++++ > 3 files changed, 233 insertions(+), 0 deletions(-) > create mode 100644 testcases/kernel/syscalls/setns/setns02.c > > diff --git a/runtest/syscalls b/runtest/syscalls > index a881479..c70bcbd 100644 > --- a/runtest/syscalls > +++ b/runtest/syscalls > @@ -963,6 +963,7 @@ setitimer02 setitimer02 > setitimer03 setitimer03 > > setns01 setns01 > +setns02 setns02 > > setpgid01 setpgid01 > setpgid02 setpgid02 > diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore > index d3bf8b7..90b521e 100644 > --- a/testcases/kernel/syscalls/.gitignore > +++ b/testcases/kernel/syscalls/.gitignore > @@ -764,6 +764,7 @@ > /setitimer/setitimer02 > /setitimer/setitimer03 > /setns/setns01 > +/setns/setns02 > /setpgid/setpgid01 > /setpgid/setpgid02 > /setpgid/setpgid03 > diff --git a/testcases/kernel/syscalls/setns/setns02.c b/testcases/kernel/syscalls/setns/setns02.c > new file mode 100644 > index 0000000..fa8ea74 > --- /dev/null > +++ b/testcases/kernel/syscalls/setns/setns02.c > @@ -0,0 +1,231 @@ > +/* > + * Copyright (C) 2013 Linux Test Project, Inc. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of version 2 of the GNU General Public > + * License as published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it would be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. > + * > + * Further, this software is distributed without any warranty that it > + * is free of the rightful claim of any third person regarding > + * infringement or the like. Any license provided herein, whether > + * implied or otherwise, applies only to this software file. Patent > + * licenses, if any, provided herein do not apply to combinations of > + * this program with other software, or any other product whatsoever. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > + * 02110-1301, USA. > + */ > +/* > + * functional test for setns(2) - reassociate thread with a namespace > + * 1. create child with CLONE_NEWUTS, set different hostname in child, > + * set namespace back to parent ns and check that hostname has changed > + * 2. create child with CLONE_NEWIPC, set up shared memory in parent > + * and verify that child can't shmat it, then set namespace > + * back to parent one and verify that child is able to do shmat > + */ > +#define _GNU_SOURCE > +#include <sys/ipc.h> > +#include <sys/shm.h> > +#include <sys/stat.h> > +#include <sys/syscall.h> > +#include <sys/types.h> > +#include <sys/utsname.h> > +#include <sys/wait.h> > +#include <errno.h> > +#include <sched.h> > +#include <string.h> > +#include "config.h" > +#include "test.h" > +#include "usctest.h" > +#include "linux_syscall_numbers.h" > +#include "safe_macros.h" > + > +#define CHILD_STACK_SIZE (1024*1024) > +#define CP "(child) " > +char *TCID = "setns02"; > + > +#if defined(__NR_setns) && defined(CLONE_NEWIPC) && defined(CLONE_NEWUTS) > +#include "setns.h" > + > +static char *dummy_hostname = "setns_dummy_uts"; > +static int ns_ipc_fd; > +static int ns_uts_fd; > +static key_t ipc_key; > +static int shmid; > + > +static void setup(void); > +static void cleanup(void); > + > +static int do_child_newuts(void *arg) > +{ > + struct utsname uts, uts_parent; > + int ns_flag = *(int *)arg; > + > + if (uname(&uts_parent) == -1) > + tst_resm(TFAIL|TERRNO, CP"uname"); > + tst_resm(TINFO, CP"hostnane (inherited from parent): %s", s/hostnane/hostname/ > + uts_parent.nodename); > + > + if (sethostname(dummy_hostname, strlen(dummy_hostname)) == -1) > + tst_resm(TFAIL|TERRNO, CP"sethostname"); > + if (uname(&uts) == -1) > + tst_resm(TFAIL|TERRNO, CP"uname"); > + > + tst_resm(TINFO, CP"hostname changed to: %s", uts.nodename); > + if (strcmp(uts_parent.nodename, uts.nodename) == 0) { > + tst_resm(TFAIL, CP"expected hostname to be different"); > + return 1; > + } else { > + tst_resm(TPASS, CP"hostname is different in parent/child"); > + } > + > + tst_resm(TINFO, CP"attemping to switch ns back to parent ns"); s/attemping/attempting/ > + if (syscall(__NR_setns, ns_uts_fd, ns_flag) == -1) { > + tst_resm(TFAIL|TERRNO, CP"setns"); > + return 2; > + } > + if (uname(&uts) == -1) > + tst_resm(TFAIL|TERRNO, CP"uname"); > + > + tst_resm(TINFO, CP"hostname: %s", uts.nodename); > + if (strcmp(uts_parent.nodename, uts.nodename) != 0) { > + tst_resm(TFAIL, CP"expected hostname to match parent"); > + return 3; > + } else { > + tst_resm(TPASS, CP"hostname now as expected"); > + } > + return 0; > +} > + > +static int do_child_newipc(void *arg) > +{ > + void *p; > + int ns_flag = *(int *)arg; > + > + p = shmat(shmid, NULL, 0); > + if (p == (void *) -1) { > + tst_resm(TPASS|TERRNO, CP"shmat failed as expected"); > + } else { > + tst_resm(TFAIL, CP"shmat unexpectedly suceeded"); > + shmdt(p); > + return 1; > + } > + > + tst_resm(TINFO, CP"attemping to switch ns back to parent ns"); s/attemping/attempting/ Acked-by: Wanlong Gao <gao...@cn...> Thanks, Wanlong Gao > + if (syscall(__NR_setns, ns_ipc_fd, ns_flag) == -1) { > + tst_resm(TFAIL|TERRNO, CP"setns"); > + return 2; > + } > + > + p = shmat(shmid, NULL, 0); > + if (p == (void *) -1) { > + tst_resm(TFAIL|TERRNO, CP"shmat failed after setns"); > + return 3; > + } else { > + tst_resm(TPASS, CP"shmat suceeded"); > + shmdt(p); > + } > + > + return 0; > +} > + > +static void test_flag(int clone_flag, int ns_flag, int (*fn) (void *arg)) > +{ > + void *child_stack; > + int ret, status; > + > + child_stack = malloc(CHILD_STACK_SIZE); > + if (child_stack == NULL) > + tst_brkm(TBROK, cleanup, "Cannot allocate stack for child"); > + > + tst_resm(TINFO, "creating child with clone_flag=0x%x, ns_flag=0x%x", > + clone_flag, ns_flag); > + ret = ltp_clone(SIGCHLD|clone_flag, fn, &ns_flag, > + CHILD_STACK_SIZE, child_stack); > + if (ret == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "ltp_clone"); > + > + if (waitpid(ret, &status, 0) == -1) > + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); > + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) > + tst_resm(TFAIL, "child returns %d", status); > + else > + tst_resm(TPASS, "child finished succesfully"); > + free(child_stack); > +} > + > +int main(int argc, char *argv[]) > +{ > + int lc; > + char *msg; > + > + msg = parse_opts(argc, argv, NULL, NULL); > + if (msg != NULL) > + tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg); > + > + setup(); > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + if (ns_uts_fd != -1) { > + tst_resm(TINFO, "test_newuts"); > + test_flag(CLONE_NEWUTS, CLONE_NEWUTS, do_child_newuts); > + test_flag(CLONE_NEWUTS, 0, do_child_newuts); > + } > + if (ns_ipc_fd != -1) { > + tst_resm(TINFO, "test_newipc"); > + test_flag(CLONE_NEWIPC, CLONE_NEWIPC, do_child_newipc); > + test_flag(CLONE_NEWIPC, 0, do_child_newipc); > + } > + } > + cleanup(); > + tst_exit(); > +} > + > +static void setup(void) > +{ > + char tmp[PATH_MAX]; > + > + tst_require_root(NULL); > + > + /* runtime check if syscall is supported */ > + syscall(__NR_setns, -1, 0); > + > + /* check if kernel has CONFIG_*_NS set and exports /proc entries */ > + ns_ipc_fd = get_ns_fd(getpid(), "ns/ipc"); > + ns_uts_fd = get_ns_fd(getpid(), "ns/uts"); > + if (ns_ipc_fd == -1 && ns_uts_fd == -1) > + tst_brkm(TCONF, NULL, "your kernel has CONFIG_IPC_NS, " > + "CONFIG_UTS_NS or CONFIG_PROC disabled"); > + > + if (getcwd(tmp, PATH_MAX) == NULL) > + tst_brkm(TBROK|TERRNO, NULL, "getcwd"); > + ipc_key = ftok(tmp, 65); > + shmid = shmget(ipc_key, getpagesize(), IPC_CREAT | 0666); > + if (shmid == -1) > + tst_brkm(TBROK|TERRNO, NULL, "shmget"); > + > + TEST_PAUSE; > +} > + > +static void cleanup(void) > +{ > + if (ns_ipc_fd != -1) > + close(ns_ipc_fd); > + if (ns_uts_fd != -1) > + close(ns_uts_fd); > + > + shmctl(shmid, IPC_RMID, NULL); > + TEST_CLEANUP; > +} > +#else > +int main(int argc, char *argv[]) > +{ > + tst_brkm(TCONF, NULL, "__NR_setns, CLONE_NEWIPC or CLONE_NEWUTS " > + " is not defined on your system."); > +} > +#endif > |
From: Wanlong G. <gao...@cn...> - 2013-02-06 07:06:04
|
On 02/05/2013 11:57 PM, Jan Stancek wrote: > errno tests for setns(2) - reassociate thread with a namespace > > Signed-off-by: Jan Stancek <jst...@re...> > --- > runtest/syscalls | 2 + > testcases/kernel/syscalls/.gitignore | 1 + > testcases/kernel/syscalls/setns/setns.h | 41 +++++ > testcases/kernel/syscalls/setns/setns01.c | 245 +++++++++++++++++++++++++++++ > 4 files changed, 289 insertions(+), 0 deletions(-) > create mode 100644 testcases/kernel/syscalls/setns/setns.h > create mode 100644 testcases/kernel/syscalls/setns/setns01.c > > diff --git a/runtest/syscalls b/runtest/syscalls > index db5a075..a881479 100644 > --- a/runtest/syscalls > +++ b/runtest/syscalls > @@ -962,6 +962,8 @@ setitimer01 setitimer01 > setitimer02 setitimer02 > setitimer03 setitimer03 > > +setns01 setns01 > + > setpgid01 setpgid01 > setpgid02 setpgid02 > setpgid03 setpgid03 > diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore > index 003c5d0..d3bf8b7 100644 > --- a/testcases/kernel/syscalls/.gitignore > +++ b/testcases/kernel/syscalls/.gitignore > @@ -763,6 +763,7 @@ > /setitimer/setitimer01 > /setitimer/setitimer02 > /setitimer/setitimer03 > +/setns/setns01 > /setpgid/setpgid01 > /setpgid/setpgid02 > /setpgid/setpgid03 > diff --git a/testcases/kernel/syscalls/setns/setns.h b/testcases/kernel/syscalls/setns/setns.h > new file mode 100644 > index 0000000..1613e6c > --- /dev/null > +++ b/testcases/kernel/syscalls/setns/setns.h > @@ -0,0 +1,41 @@ > +/* > + * Copyright (C) 2013 Linux Test Project, Inc. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of version 2 of the GNU General Public > + * License as published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it would be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. > + * > + * Further, this software is distributed without any warranty that it > + * is free of the rightful claim of any third person regarding > + * infringement or the like. Any license provided herein, whether > + * implied or otherwise, applies only to this software file. Patent > + * licenses, if any, provided herein do not apply to combinations of > + * this program with other software, or any other product whatsoever. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > + * 02110-1301, USA. > + */ > + > +static int get_ns_fd(int pid, const char *ns) > +{ > + char tmp[PATH_MAX]; > + struct stat st; > + int fd = -1; > + > + sprintf(tmp, "/proc/%d/%s", pid, ns); > + if (stat(tmp, &st) == 0) { > + fd = open(tmp, O_RDONLY); > + if (fd == -1) > + tst_brkm(TBROK|TERRNO, NULL, "failed to open %s", tmp); > + } else { > + if (errno != ENOENT) > + tst_brkm(TBROK|TERRNO, NULL, "failed to stat %s", tmp); > + } > + return fd; > +} > diff --git a/testcases/kernel/syscalls/setns/setns01.c b/testcases/kernel/syscalls/setns/setns01.c > new file mode 100644 > index 0000000..6469266 > --- /dev/null > +++ b/testcases/kernel/syscalls/setns/setns01.c > @@ -0,0 +1,245 @@ > +/* > + * Copyright (C) 2013 Linux Test Project, Inc. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of version 2 of the GNU General Public > + * License as published by the Free Software Foundation. > + * > + * This program is distributed in the hope that it would be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. > + * > + * Further, this software is distributed without any warranty that it > + * is free of the rightful claim of any third person regarding > + * infringement or the like. Any license provided herein, whether > + * implied or otherwise, applies only to this software file. Patent > + * licenses, if any, provided herein do not apply to combinations of > + * this program with other software, or any other product whatsoever. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA > + * 02110-1301, USA. > + */ > +/* > + * errno tests for setns(2) - reassociate thread with a namespace > + */ > +#define _GNU_SOURCE > +#include <sys/stat.h> > +#include <sys/syscall.h> > +#include <sys/types.h> > +#include <errno.h> > +#include <sched.h> > +#include <pwd.h> > +#include <string.h> > +#include "config.h" > +#include "test.h" > +#include "usctest.h" > +#include "linux_syscall_numbers.h" > +#include "safe_macros.h" > + > +#define NS_TOTAL 3 > +char *TCID = "setns01"; > + > +#if defined(__NR_setns) && defined(CLONE_NEWIPC) && defined(CLONE_NEWUTS) \ > + && defined(CLONE_NEWNET) > +#include "setns.h" > + > +struct testcase_t { > + const char *msg; > + int fd; > + int ns_type; > + int exp_ret; > + int exp_errno; > + int skip; > + void (*setup) (struct testcase_t *); > + void (*cleanup) (struct testcase_t *); > +}; > + > +static void setup(void); > +static void cleanup(void); > +static void setup1(struct testcase_t *); > +static void setup2(struct testcase_t *); > +static void setup3(struct testcase_t *); > +static void setup4(struct testcase_t *); > +static void cleanup1(struct testcase_t *); > +static void cleanup4(struct testcase_t *); > + > +struct testcase_t tdat[] = { > + { > + .msg = "invalid fd", > + .fd = -1, > + .ns_type = CLONE_NEWIPC, > + .exp_ret = -1, > + .exp_errno = EBADF, > + }, > + { > + .msg = "regular file fd", > + .ns_type = CLONE_NEWIPC, > + .exp_ret = -1, > + .exp_errno = EINVAL, > + .setup = setup1, > + .cleanup = cleanup1 > + }, > + { > + .msg = "invalid ns_type", > + .ns_type = -1, > + .exp_ret = -1, > + .exp_errno = EINVAL, > + .setup = setup2, > + }, > + { > + .msg = "mismatch ns_type/fd", > + .exp_ret = -1, > + .exp_errno = EINVAL, > + .setup = setup3, > + }, > + { > + .msg = "without CAP_SYS_ADMIN", > + .exp_ret = -1, > + .exp_errno = EPERM, > + .setup = setup4, > + .cleanup = cleanup4, > + } In order to allow unprivileged use of namespace, Eric has changed the permission check to the install methods. Then, the fd and nstype check will go before the core permission check. So, in order to test the permission, you should set an valid fd and nstype first. Please see the following commit in kernel. commit 142e1d1d5f088e7a38659daca6e84a730967774a Author: Eric W. Biederman <ebi...@xm...> Date: Thu Jul 26 01:13:20 2012 -0700 userns: Allow unprivileged use of setns. - Push the permission check from the core setns syscall into the setns install methods where the user namespace of the target namespace can be determined, and used in a ns_capable call. Acked-by: Serge Hallyn <ser...@ca...> Signed-off-by: "Eric W. Biederman" <ebi...@xm...> Thanks, Wanlong Gao > +}; > + > +static const char *ns_names[NS_TOTAL] = {"ns/ipc", "ns/net", "ns/uts"}; > +static int ns_types[NS_TOTAL] = { CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWUTS }; > +static int ns_fds[NS_TOTAL]; > +static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); > +static const char nobody_uid[] = "nobody"; > +static struct passwd *ltpuser; > + > +static void setup1(struct testcase_t *t) > +{ > + t->fd = open("dummy", O_CREAT); > + if (t->fd == -1) > + tst_brkm(TFAIL|TERRNO, cleanup, "setup1:open failed"); > + unlink("dummy"); > +} > + > +static void cleanup1(struct testcase_t *t) > +{ > + close(t->fd); > +} > + > +static void setup2(struct testcase_t *t) > +{ > + int i; > + for (i = 0; i < NS_TOTAL; i++) > + if (ns_fds[i] != -1) { > + t->fd = ns_fds[i]; > + return; > + } > + t->skip = 1; > +} > + > +static void setup3(struct testcase_t *t) > +{ > + int i; > + for (i = 0; i < NS_TOTAL; i++) > + if (ns_fds[i] != -1) { > + t->fd = ns_fds[i]; > + t->ns_type = ns_types[(i+1) % NS_TOTAL]; > + return; > + } > + t->skip = 1; > +} > + > +static void setup4(struct testcase_t *t) > +{ > + if (seteuid(ltpuser->pw_uid) == -1) > + tst_brkm(TBROK | TERRNO, NULL, "seteuid failed"); > +} > + > +static void cleanup4(struct testcase_t *t) > +{ > + if (seteuid(0) == -1) > + tst_brkm(TBROK | TERRNO, NULL, "seteuid restore failed"); > +} > + > +static void test_setns(struct testcase_t *t) > +{ > + int ret; > + > + if (t->setup) > + t->setup(t); > + > + if (t->skip) { > + tst_resm(TINFO, "skip %s", tdat->msg); > + return; > + } > + > + ret = syscall(__NR_setns, t->fd, t->ns_type); > + if (ret == t->exp_ret) { > + if (ret == -1 && errno == t->exp_errno) > + tst_resm(TPASS, "%s exp_errno=%d", t->msg, > + t->exp_errno); > + else > + tst_resm(TFAIL|TERRNO, "%s exp_errno=%d", t->msg, > + t->exp_errno); > + } else { > + tst_resm(TFAIL, "%s ret=%d expected=%d", t->msg, > + ret, t->exp_ret); > + } > + > + if (t->cleanup) > + t->cleanup(t); > +} > + > +int main(int argc, char *argv[]) > +{ > + int lc, testno; > + char *msg; > + > + msg = parse_opts(argc, argv, NULL, NULL); > + if (msg != NULL) > + tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg); > + > + setup(); > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + for (testno = 0; testno < TST_TOTAL; testno++) > + test_setns(&tdat[testno]); > + } > + cleanup(); > + tst_exit(); > +} > + > +static void setup(void) > +{ > + int i; > + > + tst_require_root(NULL); > + > + /* runtime check if syscall is supported */ > + syscall(__NR_setns, -1, 0); > + > + ltpuser = getpwnam(nobody_uid); > + if (ltpuser == NULL) > + tst_brkm(TBROK | TERRNO, NULL, "getpwnam failed"); > + > + for (i = 0; i < NS_TOTAL; i++) > + ns_fds[i] = get_ns_fd(getpid(), ns_names[i]); > + > + tst_tmpdir(); > + TEST_PAUSE; > +} > + > +static void cleanup(void) > +{ > + int i; > + > + for (i = 0; i < NS_TOTAL; i++) > + if (ns_fds[i] != -1) > + close(ns_fds[i]); > + tst_rmdir(); > + TEST_CLEANUP; > +} > +#else > +int main(int argc, char *argv[]) > +{ > + tst_brkm(TCONF, NULL, "__NR_setns, CLONE_NEWIPC, CLONE_NEWNET or " > + "CLONE_NEWUTS is not defined on your system."); > + > +} > +#endif > |
From: Wanlong G. <gao...@cn...> - 2013-02-06 08:49:00
|
On 02/06/2013 03:05 PM, Wanlong Gao wrote: > On 02/05/2013 11:57 PM, Jan Stancek wrote: >> errno tests for setns(2) - reassociate thread with a namespace >> >> Signed-off-by: Jan Stancek <jst...@re...> >> --- >> runtest/syscalls | 2 + >> testcases/kernel/syscalls/.gitignore | 1 + >> testcases/kernel/syscalls/setns/setns.h | 41 +++++ >> testcases/kernel/syscalls/setns/setns01.c | 245 +++++++++++++++++++++++++++++ >> 4 files changed, 289 insertions(+), 0 deletions(-) >> create mode 100644 testcases/kernel/syscalls/setns/setns.h >> create mode 100644 testcases/kernel/syscalls/setns/setns01.c >> >> diff --git a/runtest/syscalls b/runtest/syscalls >> index db5a075..a881479 100644 >> --- a/runtest/syscalls >> +++ b/runtest/syscalls >> @@ -962,6 +962,8 @@ setitimer01 setitimer01 >> setitimer02 setitimer02 >> setitimer03 setitimer03 >> >> +setns01 setns01 >> + >> setpgid01 setpgid01 >> setpgid02 setpgid02 >> setpgid03 setpgid03 >> diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore >> index 003c5d0..d3bf8b7 100644 >> --- a/testcases/kernel/syscalls/.gitignore >> +++ b/testcases/kernel/syscalls/.gitignore >> @@ -763,6 +763,7 @@ >> /setitimer/setitimer01 >> /setitimer/setitimer02 >> /setitimer/setitimer03 >> +/setns/setns01 >> /setpgid/setpgid01 >> /setpgid/setpgid02 >> /setpgid/setpgid03 >> diff --git a/testcases/kernel/syscalls/setns/setns.h b/testcases/kernel/syscalls/setns/setns.h >> new file mode 100644 >> index 0000000..1613e6c >> --- /dev/null >> +++ b/testcases/kernel/syscalls/setns/setns.h >> @@ -0,0 +1,41 @@ >> +/* >> + * Copyright (C) 2013 Linux Test Project, Inc. >> + * >> + * This program is free software; you can redistribute it and/or >> + * modify it under the terms of version 2 of the GNU General Public >> + * License as published by the Free Software Foundation. >> + * >> + * This program is distributed in the hope that it would be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. >> + * >> + * Further, this software is distributed without any warranty that it >> + * is free of the rightful claim of any third person regarding >> + * infringement or the like. Any license provided herein, whether >> + * implied or otherwise, applies only to this software file. Patent >> + * licenses, if any, provided herein do not apply to combinations of >> + * this program with other software, or any other product whatsoever. >> + * >> + * You should have received a copy of the GNU General Public License >> + * along with this program; if not, write the Free Software >> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA >> + * 02110-1301, USA. >> + */ >> + >> +static int get_ns_fd(int pid, const char *ns) >> +{ >> + char tmp[PATH_MAX]; >> + struct stat st; >> + int fd = -1; >> + >> + sprintf(tmp, "/proc/%d/%s", pid, ns); >> + if (stat(tmp, &st) == 0) { >> + fd = open(tmp, O_RDONLY); >> + if (fd == -1) >> + tst_brkm(TBROK|TERRNO, NULL, "failed to open %s", tmp); >> + } else { >> + if (errno != ENOENT) >> + tst_brkm(TBROK|TERRNO, NULL, "failed to stat %s", tmp); >> + } >> + return fd; >> +} >> diff --git a/testcases/kernel/syscalls/setns/setns01.c b/testcases/kernel/syscalls/setns/setns01.c >> new file mode 100644 >> index 0000000..6469266 >> --- /dev/null >> +++ b/testcases/kernel/syscalls/setns/setns01.c >> @@ -0,0 +1,245 @@ >> +/* >> + * Copyright (C) 2013 Linux Test Project, Inc. >> + * >> + * This program is free software; you can redistribute it and/or >> + * modify it under the terms of version 2 of the GNU General Public >> + * License as published by the Free Software Foundation. >> + * >> + * This program is distributed in the hope that it would be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. >> + * >> + * Further, this software is distributed without any warranty that it >> + * is free of the rightful claim of any third person regarding >> + * infringement or the like. Any license provided herein, whether >> + * implied or otherwise, applies only to this software file. Patent >> + * licenses, if any, provided herein do not apply to combinations of >> + * this program with other software, or any other product whatsoever. >> + * >> + * You should have received a copy of the GNU General Public License >> + * along with this program; if not, write the Free Software >> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA >> + * 02110-1301, USA. >> + */ >> +/* >> + * errno tests for setns(2) - reassociate thread with a namespace >> + */ >> +#define _GNU_SOURCE >> +#include <sys/stat.h> >> +#include <sys/syscall.h> >> +#include <sys/types.h> >> +#include <errno.h> >> +#include <sched.h> >> +#include <pwd.h> >> +#include <string.h> >> +#include "config.h" >> +#include "test.h" >> +#include "usctest.h" >> +#include "linux_syscall_numbers.h" >> +#include "safe_macros.h" >> + >> +#define NS_TOTAL 3 >> +char *TCID = "setns01"; >> + >> +#if defined(__NR_setns) && defined(CLONE_NEWIPC) && defined(CLONE_NEWUTS) \ >> + && defined(CLONE_NEWNET) >> +#include "setns.h" >> + >> +struct testcase_t { >> + const char *msg; >> + int fd; >> + int ns_type; >> + int exp_ret; >> + int exp_errno; >> + int skip; >> + void (*setup) (struct testcase_t *); >> + void (*cleanup) (struct testcase_t *); >> +}; >> + >> +static void setup(void); >> +static void cleanup(void); >> +static void setup1(struct testcase_t *); >> +static void setup2(struct testcase_t *); >> +static void setup3(struct testcase_t *); >> +static void setup4(struct testcase_t *); >> +static void cleanup1(struct testcase_t *); >> +static void cleanup4(struct testcase_t *); >> + >> +struct testcase_t tdat[] = { >> + { >> + .msg = "invalid fd", >> + .fd = -1, >> + .ns_type = CLONE_NEWIPC, >> + .exp_ret = -1, >> + .exp_errno = EBADF, >> + }, >> + { >> + .msg = "regular file fd", >> + .ns_type = CLONE_NEWIPC, >> + .exp_ret = -1, >> + .exp_errno = EINVAL, >> + .setup = setup1, >> + .cleanup = cleanup1 >> + }, >> + { >> + .msg = "invalid ns_type", >> + .ns_type = -1, >> + .exp_ret = -1, >> + .exp_errno = EINVAL, >> + .setup = setup2, >> + }, >> + { >> + .msg = "mismatch ns_type/fd", >> + .exp_ret = -1, >> + .exp_errno = EINVAL, >> + .setup = setup3, >> + }, >> + { >> + .msg = "without CAP_SYS_ADMIN", >> + .exp_ret = -1, >> + .exp_errno = EPERM, >> + .setup = setup4, >> + .cleanup = cleanup4, >> + } > > In order to allow unprivileged use of namespace, Eric has changed the permission > check to the install methods. Then, the fd and nstype check will go before the > core permission check. So, in order to test the permission, you should set an > valid fd and nstype first. Please see the following commit in kernel. > > commit 142e1d1d5f088e7a38659daca6e84a730967774a > Author: Eric W. Biederman <ebi...@xm...> > Date: Thu Jul 26 01:13:20 2012 -0700 > > userns: Allow unprivileged use of setns. > > - Push the permission check from the core setns syscall into > the setns install methods where the user namespace of the > target namespace can be determined, and used in a ns_capable > call. > > Acked-by: Serge Hallyn <ser...@ca...> > Signed-off-by: "Eric W. Biederman" <ebi...@xm...> > > > Thanks, > Wanlong Gao > > >> +}; >> + >> +static const char *ns_names[NS_TOTAL] = {"ns/ipc", "ns/net", "ns/uts"}; >> +static int ns_types[NS_TOTAL] = { CLONE_NEWIPC, CLONE_NEWNET, CLONE_NEWUTS }; >> +static int ns_fds[NS_TOTAL]; >> +static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); >> +static const char nobody_uid[] = "nobody"; >> +static struct passwd *ltpuser; >> + >> +static void setup1(struct testcase_t *t) >> +{ >> + t->fd = open("dummy", O_CREAT); >> + if (t->fd == -1) >> + tst_brkm(TFAIL|TERRNO, cleanup, "setup1:open failed"); >> + unlink("dummy"); >> +} >> + >> +static void cleanup1(struct testcase_t *t) >> +{ >> + close(t->fd); >> +} >> + >> +static void setup2(struct testcase_t *t) >> +{ >> + int i; >> + for (i = 0; i < NS_TOTAL; i++) >> + if (ns_fds[i] != -1) { >> + t->fd = ns_fds[i]; >> + return; >> + } >> + t->skip = 1; >> +} >> + >> +static void setup3(struct testcase_t *t) >> +{ >> + int i; >> + for (i = 0; i < NS_TOTAL; i++) >> + if (ns_fds[i] != -1) { >> + t->fd = ns_fds[i]; >> + t->ns_type = ns_types[(i+1) % NS_TOTAL]; >> + return; >> + } >> + t->skip = 1; >> +} >> + >> +static void setup4(struct testcase_t *t) >> +{ So, how about adding fd and ns_type setting in setup4: + int i; + for (i = 0; i < NS_TOTAL; i++) + if (ns_fds[i] != -1) { + t->fd = ns_fds[i]; + t->ns_type = ns_types[i]; + return; + } + t->skip = 1; Acked-by: Wanlong Gao <gao...@cn...> Thanks, Wanlong Gao >> + if (seteuid(ltpuser->pw_uid) == -1) >> + tst_brkm(TBROK | TERRNO, NULL, "seteuid failed"); >> +} >> + >> +static void cleanup4(struct testcase_t *t) >> +{ >> + if (seteuid(0) == -1) >> + tst_brkm(TBROK | TERRNO, NULL, "seteuid restore failed"); >> +} >> + >> +static void test_setns(struct testcase_t *t) >> +{ >> + int ret; >> + >> + if (t->setup) >> + t->setup(t); >> + >> + if (t->skip) { >> + tst_resm(TINFO, "skip %s", tdat->msg); >> + return; >> + } >> + >> + ret = syscall(__NR_setns, t->fd, t->ns_type); >> + if (ret == t->exp_ret) { >> + if (ret == -1 && errno == t->exp_errno) >> + tst_resm(TPASS, "%s exp_errno=%d", t->msg, >> + t->exp_errno); >> + else >> + tst_resm(TFAIL|TERRNO, "%s exp_errno=%d", t->msg, >> + t->exp_errno); >> + } else { >> + tst_resm(TFAIL, "%s ret=%d expected=%d", t->msg, >> + ret, t->exp_ret); >> + } >> + >> + if (t->cleanup) >> + t->cleanup(t); >> +} >> + >> +int main(int argc, char *argv[]) >> +{ >> + int lc, testno; >> + char *msg; >> + >> + msg = parse_opts(argc, argv, NULL, NULL); >> + if (msg != NULL) >> + tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg); >> + >> + setup(); >> + for (lc = 0; TEST_LOOPING(lc); lc++) { >> + for (testno = 0; testno < TST_TOTAL; testno++) >> + test_setns(&tdat[testno]); >> + } >> + cleanup(); >> + tst_exit(); >> +} >> + >> +static void setup(void) >> +{ >> + int i; >> + >> + tst_require_root(NULL); >> + >> + /* runtime check if syscall is supported */ >> + syscall(__NR_setns, -1, 0); >> + >> + ltpuser = getpwnam(nobody_uid); >> + if (ltpuser == NULL) >> + tst_brkm(TBROK | TERRNO, NULL, "getpwnam failed"); >> + >> + for (i = 0; i < NS_TOTAL; i++) >> + ns_fds[i] = get_ns_fd(getpid(), ns_names[i]); >> + >> + tst_tmpdir(); >> + TEST_PAUSE; >> +} >> + >> +static void cleanup(void) >> +{ >> + int i; >> + >> + for (i = 0; i < NS_TOTAL; i++) >> + if (ns_fds[i] != -1) >> + close(ns_fds[i]); >> + tst_rmdir(); >> + TEST_CLEANUP; >> +} >> +#else >> +int main(int argc, char *argv[]) >> +{ >> + tst_brkm(TCONF, NULL, "__NR_setns, CLONE_NEWIPC, CLONE_NEWNET or " >> + "CLONE_NEWUTS is not defined on your system."); >> + >> +} >> +#endif >> > > > ------------------------------------------------------------------------------ > Free Next-Gen Firewall Hardware Offer > Buy your Sophos next-gen firewall before the end March 2013 > and get the hardware for free! Learn more. > http://p.sf.net/sfu/sophos-d2d-feb > _______________________________________________ > Ltp-list mailing list > Ltp...@li... > https://lists.sourceforge.net/lists/listinfo/ltp-list > |
From: Jan S. <jst...@re...> - 2013-02-06 08:57:16
|
----- Original Message ----- > From: "Wanlong Gao" <gao...@cn...> > To: "Jan Stancek" <jst...@re...> > Cc: gao...@cn..., ltp...@li... > Sent: Wednesday, 6 February, 2013 9:48:17 AM > Subject: Re: [LTP] [PATCH 2/3] setns: add new syscall test setns01 > > > So, how about adding fd and ns_type setting in setup4: > > + int i; > + for (i = 0; i < NS_TOTAL; i++) > + if (ns_fds[i] != -1) { > + t->fd = ns_fds[i]; > + t->ns_type = ns_types[i]; > + return; > + } > + t->skip = 1; > > > Acked-by: Wanlong Gao <gao...@cn...> > > Thanks, > Wanlong Gao Thanks for having a look. I was thinking the same, I'm just building latest kernel tree to double check it. I'll send v2 afterwards. Regards, Jan |
From: Wanlong G. <gao...@cn...> - 2013-02-06 09:07:51
|
On 02/06/2013 04:57 PM, Jan Stancek wrote: > > > ----- Original Message ----- >> From: "Wanlong Gao" <gao...@cn...> >> To: "Jan Stancek" <jst...@re...> >> Cc: gao...@cn..., ltp...@li... >> Sent: Wednesday, 6 February, 2013 9:48:17 AM >> Subject: Re: [LTP] [PATCH 2/3] setns: add new syscall test setns01 >> >> >> So, how about adding fd and ns_type setting in setup4: >> >> + int i; >> + for (i = 0; i < NS_TOTAL; i++) >> + if (ns_fds[i] != -1) { >> + t->fd = ns_fds[i]; >> + t->ns_type = ns_types[i]; >> + return; >> + } >> + t->skip = 1; >> >> >> Acked-by: Wanlong Gao <gao...@cn...> >> >> Thanks, >> Wanlong Gao > > Thanks for having a look. I was thinking the same, I'm just building > latest kernel tree to double check it. I'll send v2 afterwards. Yeah, thank you. namespace part is in heavy development recently, your contribution is very useful. 8-) Thanks, Wanlong Gao > > Regards, > Jan > |
From: Jan S. <jst...@re...> - 2013-02-06 11:55:24
|
Changes in v2: - fixed setns01 to work with commit 142e1d1d5f088e7a38659daca6e84a730967774a - revamped setns01 to use namespace any fd/types available, at the moment any from: ipc, mnt, net, pid, uts - setns01 now runs each test for each namespace type - fixed typo errors in setns02 - tested with 3.7 and 3.8.0-rc6 Sample output from 3.8.0-rc6+: setns01 0 TINFO : ns_fds[0]=3, ns_types[0]=0x8000000 setns01 0 TINFO : ns_fds[1]=4, ns_types[1]=0x20000 setns01 0 TINFO : ns_fds[2]=5, ns_types[2]=0x40000000 setns01 0 TINFO : ns_fds[3]=6, ns_types[3]=0x20000000 setns01 0 TINFO : ns_fds[4]=7, ns_types[4]=0x4000000 setns01 0 TINFO : setns(-1, 0x8000000) setns01 1 TPASS : invalid fd exp_errno=9 setns01 0 TINFO : setns(-1, 0x20000) setns01 2 TPASS : invalid fd exp_errno=9 setns01 0 TINFO : setns(-1, 0x40000000) setns01 3 TPASS : invalid fd exp_errno=9 setns01 0 TINFO : setns(-1, 0x20000000) setns01 4 TPASS : invalid fd exp_errno=9 setns01 0 TINFO : setns(-1, 0x4000000) setns01 5 TPASS : invalid fd exp_errno=9 setns01 0 TINFO : setns(8, 0x8000000) setns01 6 TPASS : regular file fd exp_errno=22 setns01 0 TINFO : setns(8, 0x20000) setns01 7 TPASS : regular file fd exp_errno=22 setns01 0 TINFO : setns(8, 0x40000000) setns01 8 TPASS : regular file fd exp_errno=22 setns01 0 TINFO : setns(8, 0x20000000) setns01 9 TPASS : regular file fd exp_errno=22 setns01 0 TINFO : setns(8, 0x4000000) setns01 10 TPASS : regular file fd exp_errno=22 setns01 0 TINFO : setns(3, 0xffffffff) setns01 11 TPASS : invalid ns_type exp_errno=22 setns01 0 TINFO : setns(4, 0xffffffff) setns01 12 TPASS : invalid ns_type exp_errno=22 setns01 0 TINFO : setns(5, 0xffffffff) setns01 13 TPASS : invalid ns_type exp_errno=22 setns01 0 TINFO : setns(6, 0xffffffff) setns01 14 TPASS : invalid ns_type exp_errno=22 setns01 0 TINFO : setns(7, 0xffffffff) setns01 15 TPASS : invalid ns_type exp_errno=22 setns01 0 TINFO : setns(3, 0x20000) setns01 16 TPASS : mismatch ns_type/fd exp_errno=22 setns01 0 TINFO : setns(4, 0x40000000) setns01 17 TPASS : mismatch ns_type/fd exp_errno=22 setns01 0 TINFO : setns(5, 0x20000000) setns01 18 TPASS : mismatch ns_type/fd exp_errno=22 setns01 0 TINFO : setns(6, 0x4000000) setns01 19 TPASS : mismatch ns_type/fd exp_errno=22 setns01 0 TINFO : setns(7, 0x8000000) setns01 20 TPASS : mismatch ns_type/fd exp_errno=22 setns01 0 TINFO : setns(3, 0x8000000) setns01 21 TPASS : without CAP_SYS_ADMIN exp_errno=1 setns01 0 TINFO : setns(4, 0x20000) setns01 22 TPASS : without CAP_SYS_ADMIN exp_errno=1 setns01 0 TINFO : setns(5, 0x40000000) setns01 23 TPASS : without CAP_SYS_ADMIN exp_errno=1 setns01 0 TINFO : setns(6, 0x20000000) setns01 24 TPASS : without CAP_SYS_ADMIN exp_errno=1 setns01 0 TINFO : setns(7, 0x4000000) setns01 25 TPASS : without CAP_SYS_ADMIN exp_errno=1 setns02 0 TINFO : test_newuts setns02 0 TINFO : creating child with clone_flag=0x4000000, ns_flag=0x4000000 setns02 0 TINFO : (child) hostname (inherited from parent): dell-pe1950-05.lab.bos.redhat.com setns02 0 TINFO : (child) hostname changed to: setns_dummy_uts setns02 1 TPASS : (child) hostname is different in parent/child setns02 0 TINFO : (child) attempting to switch ns back to parent ns setns02 0 TINFO : (child) hostname: dell-pe1950-05.lab.bos.redhat.com setns02 2 TPASS : (child) hostname now as expected setns02 1 TPASS : child finished succesfully setns02 0 TINFO : creating child with clone_flag=0x4000000, ns_flag=0x0 setns02 0 TINFO : (child) hostname (inherited from parent): dell-pe1950-05.lab.bos.redhat.com setns02 0 TINFO : (child) hostname changed to: setns_dummy_uts setns02 2 TPASS : (child) hostname is different in parent/child setns02 0 TINFO : (child) attempting to switch ns back to parent ns setns02 0 TINFO : (child) hostname: dell-pe1950-05.lab.bos.redhat.com setns02 3 TPASS : (child) hostname now as expected setns02 2 TPASS : child finished succesfully setns02 0 TINFO : test_newipc setns02 0 TINFO : creating child with clone_flag=0x8000000, ns_flag=0x8000000 setns02 3 TPASS : (child) shmat failed as expected: errno=EINVAL(22): Invalid argument setns02 0 TINFO : (child) attempting to switch ns back to parent ns setns02 4 TPASS : (child) shmat suceeded setns02 3 TPASS : child finished succesfully setns02 0 TINFO : creating child with clone_flag=0x8000000, ns_flag=0x0 setns02 4 TPASS : (child) shmat failed as expected: errno=EINVAL(22): Invalid argument setns02 0 TINFO : (child) attempting to switch ns back to parent ns setns02 5 TPASS : (child) shmat suceeded setns02 4 TPASS : child finished succesfully Jan Stancek (3): setns: setup directory at kernel/syscalls/setns setns: add new syscall test setns01 setns: add new syscall test setns02 runtest/syscalls | 3 + testcases/kernel/syscalls/.gitignore | 2 + testcases/kernel/syscalls/setns/Makefile | 23 +++ testcases/kernel/syscalls/setns/setns.h | 89 +++++++++++ testcases/kernel/syscalls/setns/setns01.c | 240 +++++++++++++++++++++++++++++ testcases/kernel/syscalls/setns/setns02.c | 231 +++++++++++++++++++++++++++ 6 files changed, 588 insertions(+), 0 deletions(-) create mode 100644 testcases/kernel/syscalls/setns/Makefile create mode 100644 testcases/kernel/syscalls/setns/setns.h create mode 100644 testcases/kernel/syscalls/setns/setns01.c create mode 100644 testcases/kernel/syscalls/setns/setns02.c |
From: Jan S. <jst...@re...> - 2013-02-06 11:55:24
|
Signed-off-by: Jan Stancek <jst...@re...> --- testcases/kernel/syscalls/setns/Makefile | 23 +++++++++++++++++++++++ 1 files changed, 23 insertions(+), 0 deletions(-) create mode 100644 testcases/kernel/syscalls/setns/Makefile diff --git a/testcases/kernel/syscalls/setns/Makefile b/testcases/kernel/syscalls/setns/Makefile new file mode 100644 index 0000000..f1b5129 --- /dev/null +++ b/testcases/kernel/syscalls/setns/Makefile @@ -0,0 +1,23 @@ +# +# Copyright (C) 2013 Linux Test Project, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +# the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +top_srcdir ?= ../../../.. + +include $(top_srcdir)/include/mk/testcases.mk +CPPFLAGS += -Wno-unused-function +include $(top_srcdir)/include/mk/generic_leaf_target.mk -- 1.7.1 |
From: Jan S. <jst...@re...> - 2013-02-06 11:55:26
|
errno tests for setns(2) - reassociate thread with a namespace Signed-off-by: Jan Stancek <jst...@re...> --- runtest/syscalls | 2 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/setns/setns.h | 89 +++++++++++ testcases/kernel/syscalls/setns/setns01.c | 240 +++++++++++++++++++++++++++++ 4 files changed, 332 insertions(+), 0 deletions(-) create mode 100644 testcases/kernel/syscalls/setns/setns.h create mode 100644 testcases/kernel/syscalls/setns/setns01.c diff --git a/runtest/syscalls b/runtest/syscalls index db5a075..a881479 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -962,6 +962,8 @@ setitimer01 setitimer01 setitimer02 setitimer02 setitimer03 setitimer03 +setns01 setns01 + setpgid01 setpgid01 setpgid02 setpgid02 setpgid03 setpgid03 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index 003c5d0..d3bf8b7 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -763,6 +763,7 @@ /setitimer/setitimer01 /setitimer/setitimer02 /setitimer/setitimer03 +/setns/setns01 /setpgid/setpgid01 /setpgid/setpgid02 /setpgid/setpgid03 diff --git a/testcases/kernel/syscalls/setns/setns.h b/testcases/kernel/syscalls/setns/setns.h new file mode 100644 index 0000000..094bfe9 --- /dev/null +++ b/testcases/kernel/syscalls/setns/setns.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2013 Linux Test Project, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#define NS_MAX 5 +static int ns_types[NS_MAX]; +static int ns_fds[NS_MAX]; +static int ns_total; + +static int get_ns_fd(int pid, const char *ns) +{ + char tmp[PATH_MAX]; + struct stat st; + int fd = -1; + + sprintf(tmp, "/proc/%d/%s", pid, ns); + if (stat(tmp, &st) == 0) { + fd = open(tmp, O_RDONLY); + if (fd == -1) + tst_brkm(TBROK|TERRNO, NULL, "failed to open %s", tmp); + } else { + if (errno != ENOENT) + tst_brkm(TBROK|TERRNO, NULL, "failed to stat %s", tmp); + } + return fd; +} + +static void init_available_ns() +{ +#define INIT_NS_TYPE(clone_type, proc_name) \ +{ \ + int fd; \ + fd = get_ns_fd(getpid(), "ns/"proc_name); \ + if (fd != -1) { \ + ns_types[ns_total] = clone_type; \ + ns_fds[ns_total] = fd; \ + tst_resm(TINFO, "ns_fds[%d]=%d, ns_types[%d]=0x%x", ns_total, \ + fd, ns_total, clone_type); \ + ns_total++; \ + } \ +} + +#if defined(CLONE_NEWIPC) + INIT_NS_TYPE(CLONE_NEWIPC, "ipc"); +#endif +#if defined(CLONE_NEWNS) + INIT_NS_TYPE(CLONE_NEWNS, "mnt"); +#endif +#if defined(CLONE_NEWNET) + INIT_NS_TYPE(CLONE_NEWNET, "net"); +#endif +#if defined(CLONE_NEWPID) + INIT_NS_TYPE(CLONE_NEWPID, "pid"); +#endif +#if defined(CLONE_NEWUTS) + INIT_NS_TYPE(CLONE_NEWUTS, "uts"); +#endif + +#undef INIT_NS_TYPE +} + +static void close_ns_fds() +{ + int i; + + for (i = 0; i < ns_total; i++) + if (ns_fds[i] != -1) + close(ns_fds[i]); +} diff --git a/testcases/kernel/syscalls/setns/setns01.c b/testcases/kernel/syscalls/setns/setns01.c new file mode 100644 index 0000000..b83022c --- /dev/null +++ b/testcases/kernel/syscalls/setns/setns01.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2013 Linux Test Project, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +/* + * errno tests for setns(2) - reassociate thread with a namespace + */ +#define _GNU_SOURCE +#include <sys/stat.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <errno.h> +#include <sched.h> +#include <pwd.h> +#include <string.h> +#include "config.h" +#include "test.h" +#include "usctest.h" +#include "linux_syscall_numbers.h" +#include "safe_macros.h" + +char *TCID = "setns01"; + +#if defined(__NR_setns) +#include "setns.h" + +struct testcase_t { + const char *msg; + int fd; + int ns_type; + int exp_ret; + int exp_errno; + int skip; + void (*setup) (struct testcase_t *, int i); + void (*cleanup) (struct testcase_t *); +}; + +static void setup(void); +static void cleanup(void); +static void setup0(struct testcase_t *, int); +static void setup1(struct testcase_t *, int); +static void setup2(struct testcase_t *, int); +static void setup3(struct testcase_t *, int); +static void setup4(struct testcase_t *, int); +static void cleanup1(struct testcase_t *); +static void cleanup4(struct testcase_t *); + +struct testcase_t tdat[] = { + { + .msg = "invalid fd", + .fd = -1, + .exp_ret = -1, + .exp_errno = EBADF, + .setup = setup0, + }, + { + .msg = "regular file fd", + .exp_ret = -1, + .exp_errno = EINVAL, + .setup = setup1, + .cleanup = cleanup1 + }, + { + .msg = "invalid ns_type", + .ns_type = -1, + .exp_ret = -1, + .exp_errno = EINVAL, + .setup = setup2, + }, + { + .msg = "mismatch ns_type/fd", + .exp_ret = -1, + .exp_errno = EINVAL, + .setup = setup3, + }, + { + .msg = "without CAP_SYS_ADMIN", + .exp_ret = -1, + .exp_errno = EPERM, + .setup = setup4, + .cleanup = cleanup4, + } +}; + +static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); +static const char nobody_uid[] = "nobody"; +static struct passwd *ltpuser; + +static void setup0(struct testcase_t *t, int i) +{ + t->ns_type = ns_types[i]; +} + +static void setup1(struct testcase_t *t, int i) +{ + t->ns_type = ns_types[i]; + t->fd = open("dummy", O_CREAT); + if (t->fd == -1) + tst_brkm(TFAIL|TERRNO, cleanup, "setup1:open failed"); + unlink("dummy"); +} + +static void cleanup1(struct testcase_t *t) +{ + close(t->fd); +} + +static void setup2(struct testcase_t *t, int i) +{ + t->fd = ns_fds[i]; +} + +static void setup3(struct testcase_t *t, int i) +{ + if (ns_total < 2) { + t->skip = 1; + return; + } + + t->fd = ns_fds[i]; + t->ns_type = ns_types[(i+1) % ns_total]; +} + +static void setup4(struct testcase_t *t, int i) +{ + if (seteuid(ltpuser->pw_uid) == -1) + tst_brkm(TBROK | TERRNO, NULL, "seteuid failed"); + + t->fd = ns_fds[i]; + t->ns_type = ns_types[i]; +} + +static void cleanup4(struct testcase_t *t) +{ + if (seteuid(0) == -1) + tst_brkm(TBROK | TERRNO, NULL, "seteuid restore failed"); +} + +static void test_setns(struct testcase_t *t) +{ + int ret, i; + + for (i = 0; i < ns_total; i++) { + if (t->setup) + t->setup(t, i); + + if (t->skip) { + tst_resm(TINFO, "skip %s", tdat->msg); + continue; + } + + tst_resm(TINFO, "setns(%d, 0x%x)", t->fd, t->ns_type); + ret = syscall(__NR_setns, t->fd, t->ns_type); + if (ret == t->exp_ret) { + if (ret == -1 && errno == t->exp_errno) + tst_resm(TPASS, "%s exp_errno=%d", t->msg, + t->exp_errno); + else + tst_resm(TFAIL|TERRNO, "%s exp_errno=%d", + t->msg, t->exp_errno); + } else { + tst_resm(TFAIL, "%s ret=%d expected=%d", t->msg, + ret, t->exp_ret); + } + + if (t->cleanup) + t->cleanup(t); + } +} + +int main(int argc, char *argv[]) +{ + int lc, testno; + char *msg; + + msg = parse_opts(argc, argv, NULL, NULL); + if (msg != NULL) + tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg); + + setup(); + for (lc = 0; TEST_LOOPING(lc); lc++) { + for (testno = 0; testno < TST_TOTAL; testno++) + test_setns(&tdat[testno]); + } + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + tst_require_root(NULL); + + /* runtime check if syscall is supported */ + syscall(__NR_setns, -1, 0); + + init_available_ns(); + if (ns_total == 0) + tst_brkm(TCONF, NULL, "no ns types/proc entries"); + + ltpuser = getpwnam(nobody_uid); + if (ltpuser == NULL) + tst_brkm(TBROK | TERRNO, NULL, "getpwnam failed"); + + + tst_tmpdir(); + TEST_PAUSE; +} + +static void cleanup(void) +{ + close_ns_fds(); + tst_rmdir(); + TEST_CLEANUP; +} +#else +int main(int argc, char *argv[]) +{ + tst_brkm(TCONF, NULL, "__NR_setns is not defined on your system."); + +} +#endif -- 1.7.1 |
From: <ch...@su...> - 2013-02-12 12:32:56
|
Hi! > +#define NS_MAX 5 > +static int ns_types[NS_MAX]; > +static int ns_fds[NS_MAX]; > +static int ns_total; > + > +static int get_ns_fd(int pid, const char *ns) > +{ > + char tmp[PATH_MAX]; > + struct stat st; > + int fd = -1; > + > + sprintf(tmp, "/proc/%d/%s", pid, ns); > + if (stat(tmp, &st) == 0) { > + fd = open(tmp, O_RDONLY); > + if (fd == -1) > + tst_brkm(TBROK|TERRNO, NULL, "failed to open %s", tmp); > + } else { > + if (errno != ENOENT) > + tst_brkm(TBROK|TERRNO, NULL, "failed to stat %s", tmp); > + } > + return fd; > +} > + > +static void init_available_ns() Missing void in the function parameters. > +{ > +#define INIT_NS_TYPE(clone_type, proc_name) \ > +{ \ > + int fd; \ > + fd = get_ns_fd(getpid(), "ns/"proc_name); \ > + if (fd != -1) { \ > + ns_types[ns_total] = clone_type; \ > + ns_fds[ns_total] = fd; \ > + tst_resm(TINFO, "ns_fds[%d]=%d, ns_types[%d]=0x%x", ns_total, \ > + fd, ns_total, clone_type); \ > + ns_total++; \ > + } \ > +} I'm wondering why this is a macro and not regular function. The only thing that I see and that wouldn't work is the string concatenation, which should have been done before the function is called. Or the get_ns_fd() could have additional parameter, since it uses sprintf() anyway. > +#if defined(CLONE_NEWIPC) > + INIT_NS_TYPE(CLONE_NEWIPC, "ipc"); > +#endif > +#if defined(CLONE_NEWNS) > + INIT_NS_TYPE(CLONE_NEWNS, "mnt"); > +#endif > +#if defined(CLONE_NEWNET) > + INIT_NS_TYPE(CLONE_NEWNET, "net"); > +#endif > +#if defined(CLONE_NEWPID) > + INIT_NS_TYPE(CLONE_NEWPID, "pid"); > +#endif > +#if defined(CLONE_NEWUTS) > + INIT_NS_TYPE(CLONE_NEWUTS, "uts"); > +#endif > + > +#undef INIT_NS_TYPE > +} > + > +static void close_ns_fds() Here missing void as well. > +{ > + int i; > + > + for (i = 0; i < ns_total; i++) > + if (ns_fds[i] != -1) > + close(ns_fds[i]); > +} -- Cyril Hrubis ch...@su... |
From: Jan S. <jst...@re...> - 2013-02-06 11:55:26
|
functional test for setns(2) - reassociate thread with a namespace involving CLONE_NEWIPC and CLONE_NEWUTS. Signed-off-by: Jan Stancek <jst...@re...> --- runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/setns/setns02.c | 231 +++++++++++++++++++++++++++++ 3 files changed, 233 insertions(+), 0 deletions(-) create mode 100644 testcases/kernel/syscalls/setns/setns02.c diff --git a/runtest/syscalls b/runtest/syscalls index a881479..c70bcbd 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -963,6 +963,7 @@ setitimer02 setitimer02 setitimer03 setitimer03 setns01 setns01 +setns02 setns02 setpgid01 setpgid01 setpgid02 setpgid02 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index d3bf8b7..90b521e 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -764,6 +764,7 @@ /setitimer/setitimer02 /setitimer/setitimer03 /setns/setns01 +/setns/setns02 /setpgid/setpgid01 /setpgid/setpgid02 /setpgid/setpgid03 diff --git a/testcases/kernel/syscalls/setns/setns02.c b/testcases/kernel/syscalls/setns/setns02.c new file mode 100644 index 0000000..e8173af --- /dev/null +++ b/testcases/kernel/syscalls/setns/setns02.c @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2013 Linux Test Project, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +/* + * functional test for setns(2) - reassociate thread with a namespace + * 1. create child with CLONE_NEWUTS, set different hostname in child, + * set namespace back to parent ns and check that hostname has changed + * 2. create child with CLONE_NEWIPC, set up shared memory in parent + * and verify that child can't shmat it, then set namespace + * back to parent one and verify that child is able to do shmat + */ +#define _GNU_SOURCE +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/stat.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <sys/utsname.h> +#include <sys/wait.h> +#include <errno.h> +#include <sched.h> +#include <string.h> +#include "config.h" +#include "test.h" +#include "usctest.h" +#include "linux_syscall_numbers.h" +#include "safe_macros.h" + +#define CHILD_STACK_SIZE (1024*1024) +#define CP "(child) " +char *TCID = "setns02"; + +#if defined(__NR_setns) && defined(CLONE_NEWIPC) && defined(CLONE_NEWUTS) +#include "setns.h" + +static char *dummy_hostname = "setns_dummy_uts"; +static int ns_ipc_fd; +static int ns_uts_fd; +static key_t ipc_key; +static int shmid; + +static void setup(void); +static void cleanup(void); + +static int do_child_newuts(void *arg) +{ + struct utsname uts, uts_parent; + int ns_flag = *(int *)arg; + + if (uname(&uts_parent) == -1) + tst_resm(TFAIL|TERRNO, CP"uname"); + tst_resm(TINFO, CP"hostname (inherited from parent): %s", + uts_parent.nodename); + + if (sethostname(dummy_hostname, strlen(dummy_hostname)) == -1) + tst_resm(TFAIL|TERRNO, CP"sethostname"); + if (uname(&uts) == -1) + tst_resm(TFAIL|TERRNO, CP"uname"); + + tst_resm(TINFO, CP"hostname changed to: %s", uts.nodename); + if (strcmp(uts_parent.nodename, uts.nodename) == 0) { + tst_resm(TFAIL, CP"expected hostname to be different"); + return 1; + } else { + tst_resm(TPASS, CP"hostname is different in parent/child"); + } + + tst_resm(TINFO, CP"attempting to switch ns back to parent ns"); + if (syscall(__NR_setns, ns_uts_fd, ns_flag) == -1) { + tst_resm(TFAIL|TERRNO, CP"setns"); + return 2; + } + if (uname(&uts) == -1) + tst_resm(TFAIL|TERRNO, CP"uname"); + + tst_resm(TINFO, CP"hostname: %s", uts.nodename); + if (strcmp(uts_parent.nodename, uts.nodename) != 0) { + tst_resm(TFAIL, CP"expected hostname to match parent"); + return 3; + } else { + tst_resm(TPASS, CP"hostname now as expected"); + } + return 0; +} + +static int do_child_newipc(void *arg) +{ + void *p; + int ns_flag = *(int *)arg; + + p = shmat(shmid, NULL, 0); + if (p == (void *) -1) { + tst_resm(TPASS|TERRNO, CP"shmat failed as expected"); + } else { + tst_resm(TFAIL, CP"shmat unexpectedly suceeded"); + shmdt(p); + return 1; + } + + tst_resm(TINFO, CP"attempting to switch ns back to parent ns"); + if (syscall(__NR_setns, ns_ipc_fd, ns_flag) == -1) { + tst_resm(TFAIL|TERRNO, CP"setns"); + return 2; + } + + p = shmat(shmid, NULL, 0); + if (p == (void *) -1) { + tst_resm(TFAIL|TERRNO, CP"shmat failed after setns"); + return 3; + } else { + tst_resm(TPASS, CP"shmat suceeded"); + shmdt(p); + } + + return 0; +} + +static void test_flag(int clone_flag, int ns_flag, int (*fn) (void *arg)) +{ + void *child_stack; + int ret, status; + + child_stack = malloc(CHILD_STACK_SIZE); + if (child_stack == NULL) + tst_brkm(TBROK, cleanup, "Cannot allocate stack for child"); + + tst_resm(TINFO, "creating child with clone_flag=0x%x, ns_flag=0x%x", + clone_flag, ns_flag); + ret = ltp_clone(SIGCHLD|clone_flag, fn, &ns_flag, + CHILD_STACK_SIZE, child_stack); + if (ret == -1) + tst_brkm(TBROK|TERRNO, cleanup, "ltp_clone"); + + if (waitpid(ret, &status, 0) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + tst_resm(TFAIL, "child returns %d", status); + else + tst_resm(TPASS, "child finished succesfully"); + free(child_stack); +} + +int main(int argc, char *argv[]) +{ + int lc; + char *msg; + + msg = parse_opts(argc, argv, NULL, NULL); + if (msg != NULL) + tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg); + + setup(); + for (lc = 0; TEST_LOOPING(lc); lc++) { + if (ns_uts_fd != -1) { + tst_resm(TINFO, "test_newuts"); + test_flag(CLONE_NEWUTS, CLONE_NEWUTS, do_child_newuts); + test_flag(CLONE_NEWUTS, 0, do_child_newuts); + } + if (ns_ipc_fd != -1) { + tst_resm(TINFO, "test_newipc"); + test_flag(CLONE_NEWIPC, CLONE_NEWIPC, do_child_newipc); + test_flag(CLONE_NEWIPC, 0, do_child_newipc); + } + } + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + char tmp[PATH_MAX]; + + tst_require_root(NULL); + + /* runtime check if syscall is supported */ + syscall(__NR_setns, -1, 0); + + /* check if kernel has CONFIG_*_NS set and exports /proc entries */ + ns_ipc_fd = get_ns_fd(getpid(), "ns/ipc"); + ns_uts_fd = get_ns_fd(getpid(), "ns/uts"); + if (ns_ipc_fd == -1 && ns_uts_fd == -1) + tst_brkm(TCONF, NULL, "your kernel has CONFIG_IPC_NS, " + "CONFIG_UTS_NS or CONFIG_PROC disabled"); + + if (getcwd(tmp, PATH_MAX) == NULL) + tst_brkm(TBROK|TERRNO, NULL, "getcwd"); + ipc_key = ftok(tmp, 65); + shmid = shmget(ipc_key, getpagesize(), IPC_CREAT | 0666); + if (shmid == -1) + tst_brkm(TBROK|TERRNO, NULL, "shmget"); + + TEST_PAUSE; +} + +static void cleanup(void) +{ + if (ns_ipc_fd != -1) + close(ns_ipc_fd); + if (ns_uts_fd != -1) + close(ns_uts_fd); + + shmctl(shmid, IPC_RMID, NULL); + TEST_CLEANUP; +} +#else +int main(int argc, char *argv[]) +{ + tst_brkm(TCONF, NULL, "__NR_setns, CLONE_NEWIPC or CLONE_NEWUTS " + " is not defined on your system."); +} +#endif -- 1.7.1 |
From: <ch...@su...> - 2013-02-12 12:41:21
|
Hi! > +static void setup(void) > +{ > + char tmp[PATH_MAX]; > + > + tst_require_root(NULL); > + > + /* runtime check if syscall is supported */ > + syscall(__NR_setns, -1, 0); > + What happens when the syscall is not supported? The call should return -1 and errno should be set to ENOSYS but the return value is not checked, I'm puzzled. > + /* check if kernel has CONFIG_*_NS set and exports /proc entries */ > + ns_ipc_fd = get_ns_fd(getpid(), "ns/ipc"); > + ns_uts_fd = get_ns_fd(getpid(), "ns/uts"); > + if (ns_ipc_fd == -1 && ns_uts_fd == -1) > + tst_brkm(TCONF, NULL, "your kernel has CONFIG_IPC_NS, " > + "CONFIG_UTS_NS or CONFIG_PROC disabled"); > + > + if (getcwd(tmp, PATH_MAX) == NULL) > + tst_brkm(TBROK|TERRNO, NULL, "getcwd"); > + ipc_key = ftok(tmp, 65); > + shmid = shmget(ipc_key, getpagesize(), IPC_CREAT | 0666); > + if (shmid == -1) > + tst_brkm(TBROK|TERRNO, NULL, "shmget"); > + > + TEST_PAUSE; > +} -- Cyril Hrubis ch...@su... |
From: Jan S. <jst...@re...> - 2013-02-12 13:05:03
|
----- Original Message ----- > From: ch...@su... > To: "Jan Stancek" <jst...@re...> > Cc: ltp...@li... > Sent: Tuesday, 12 February, 2013 1:41:49 PM > Subject: Re: [LTP] [PATCH v2 3/3] setns: add new syscall test setns02 > > Hi! > > +static void setup(void) > > +{ > > + char tmp[PATH_MAX]; > > + > > + tst_require_root(NULL); > > + > > + /* runtime check if syscall is supported */ > > + syscall(__NR_setns, -1, 0); > > + > > What happens when the syscall is not supported? The call should > return > -1 and errno should be set to ENOSYS but the return value is not > checked, I'm puzzled. It's a bit unfortunate name collision with syscall macro defined in linux_syscall_numbers.h. That macro contains check for ENOSYS. Regards, Jan |
From: <ch...@su...> - 2013-02-12 13:08:58
|
Hi! > > > +static void setup(void) > > > +{ > > > + char tmp[PATH_MAX]; > > > + > > > + tst_require_root(NULL); > > > + > > > + /* runtime check if syscall is supported */ > > > + syscall(__NR_setns, -1, 0); > > > + > > > > What happens when the syscall is not supported? The call should > > return > > -1 and errno should be set to ENOSYS but the return value is not > > checked, I'm puzzled. > > It's a bit unfortunate name collision with syscall macro defined > in linux_syscall_numbers.h. That macro contains check for ENOSYS. Ah, now I remeber. We really should change that one. Any volunteers? -- Cyril Hrubis ch...@su... |
From: Jan S. <jst...@re...> - 2013-02-12 13:12:53
|
----- Original Message ----- > From: ch...@su... > To: "Jan Stancek" <jst...@re...> > Cc: ltp...@li... > Sent: Tuesday, 12 February, 2013 2:09:26 PM > Subject: Re: [LTP] [PATCH v2 3/3] setns: add new syscall test setns02 > > Hi! > > > > +static void setup(void) > > > > +{ > > > > + char tmp[PATH_MAX]; > > > > + > > > > + tst_require_root(NULL); > > > > + > > > > + /* runtime check if syscall is supported */ > > > > + syscall(__NR_setns, -1, 0); > > > > + > > > > > > What happens when the syscall is not supported? The call should > > > return > > > -1 and errno should be set to ENOSYS but the return value is not > > > checked, I'm puzzled. > > > > It's a bit unfortunate name collision with syscall macro defined > > in linux_syscall_numbers.h. That macro contains check for ENOSYS. > > Ah, now I remeber. > > We really should change that one. Any volunteers? Sure :-), would "ltp_syscall" as name of that macro work for everyone? Regards, Jan |
From: <ch...@su...> - 2013-02-12 13:16:28
|
Hi! > > > > What happens when the syscall is not supported? The call should > > > > return > > > > -1 and errno should be set to ENOSYS but the return value is not > > > > checked, I'm puzzled. > > > > > > It's a bit unfortunate name collision with syscall macro defined > > > in linux_syscall_numbers.h. That macro contains check for ENOSYS. > > > > Ah, now I remeber. > > > > We really should change that one. Any volunteers? > > Sure :-), would "ltp_syscall" as name of that macro work for everyone? Works for me. -- Cyril Hrubis ch...@su... |
From: Jan S. <jst...@re...> - 2013-02-18 14:05:40
|
changes in v3: - added missing "void" to functions without parameters - INIT_NS_TYPE macro converted to function - use ltp_syscall in setup() Jan Stancek (3): setns: setup directory at kernel/syscalls/setns setns: add new syscall test setns01 setns: add new syscall test setns02 runtest/syscalls | 3 + testcases/kernel/syscalls/.gitignore | 2 + testcases/kernel/syscalls/setns/Makefile | 23 +++ testcases/kernel/syscalls/setns/setns.h | 88 +++++++++++ testcases/kernel/syscalls/setns/setns01.c | 240 +++++++++++++++++++++++++++++ testcases/kernel/syscalls/setns/setns02.c | 231 +++++++++++++++++++++++++++ 6 files changed, 587 insertions(+), 0 deletions(-) create mode 100644 testcases/kernel/syscalls/setns/Makefile create mode 100644 testcases/kernel/syscalls/setns/setns.h create mode 100644 testcases/kernel/syscalls/setns/setns01.c create mode 100644 testcases/kernel/syscalls/setns/setns02.c |
From: Jan S. <jst...@re...> - 2013-02-18 14:05:42
|
errno tests for setns(2) - reassociate thread with a namespace Signed-off-by: Jan Stancek <jst...@re...> --- runtest/syscalls | 2 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/setns/setns.h | 88 +++++++++++ testcases/kernel/syscalls/setns/setns01.c | 240 +++++++++++++++++++++++++++++ 4 files changed, 331 insertions(+), 0 deletions(-) create mode 100644 testcases/kernel/syscalls/setns/setns.h create mode 100644 testcases/kernel/syscalls/setns/setns01.c diff --git a/runtest/syscalls b/runtest/syscalls index db5a075..a881479 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -962,6 +962,8 @@ setitimer01 setitimer01 setitimer02 setitimer02 setitimer03 setitimer03 +setns01 setns01 + setpgid01 setpgid01 setpgid02 setpgid02 setpgid03 setpgid03 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index d661159..4b8bb94 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -764,6 +764,7 @@ /setitimer/setitimer01 /setitimer/setitimer02 /setitimer/setitimer03 +/setns/setns01 /setpgid/setpgid01 /setpgid/setpgid02 /setpgid/setpgid03 diff --git a/testcases/kernel/syscalls/setns/setns.h b/testcases/kernel/syscalls/setns/setns.h new file mode 100644 index 0000000..23bdb2e --- /dev/null +++ b/testcases/kernel/syscalls/setns/setns.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2013 Linux Test Project, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#define NS_MAX 5 +static int ns_types[NS_MAX]; +static int ns_fds[NS_MAX]; +static int ns_total; + +static int get_ns_fd(int pid, const char *ns) +{ + char tmp[PATH_MAX]; + struct stat st; + int fd = -1; + + sprintf(tmp, "/proc/%d/ns/%s", pid, ns); + if (stat(tmp, &st) == 0) { + fd = open(tmp, O_RDONLY); + if (fd == -1) + tst_brkm(TBROK|TERRNO, NULL, "failed to open %s", tmp); + } else { + if (errno != ENOENT) + tst_brkm(TBROK|TERRNO, NULL, "failed to stat %s", tmp); + } + return fd; +} + +static void init_ns_type(int clone_type, const char *proc_name) +{ + int fd; + + fd = get_ns_fd(getpid(), proc_name); + if (fd != -1) { + ns_types[ns_total] = clone_type; + ns_fds[ns_total] = fd; + tst_resm(TINFO, "ns_fds[%d]=%d, ns_types[%d]=0x%x", ns_total, + fd, ns_total, clone_type); + ns_total++; + } +} + +static void init_available_ns(void) +{ +#if defined(CLONE_NEWIPC) + init_ns_type(CLONE_NEWIPC, "ipc"); +#endif +#if defined(CLONE_NEWNS) + init_ns_type(CLONE_NEWNS, "mnt"); +#endif +#if defined(CLONE_NEWNET) + init_ns_type(CLONE_NEWNET, "net"); +#endif +#if defined(CLONE_NEWPID) + init_ns_type(CLONE_NEWPID, "pid"); +#endif +#if defined(CLONE_NEWUTS) + init_ns_type(CLONE_NEWUTS, "uts"); +#endif +} + +static void close_ns_fds(void) +{ + int i; + + for (i = 0; i < ns_total; i++) + if (ns_fds[i] != -1) + close(ns_fds[i]); +} diff --git a/testcases/kernel/syscalls/setns/setns01.c b/testcases/kernel/syscalls/setns/setns01.c new file mode 100644 index 0000000..710ce9b --- /dev/null +++ b/testcases/kernel/syscalls/setns/setns01.c @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2013 Linux Test Project, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +/* + * errno tests for setns(2) - reassociate thread with a namespace + */ +#define _GNU_SOURCE +#include <sys/stat.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <errno.h> +#include <sched.h> +#include <pwd.h> +#include <string.h> +#include "config.h" +#include "test.h" +#include "usctest.h" +#include "linux_syscall_numbers.h" +#include "safe_macros.h" + +char *TCID = "setns01"; + +#if defined(__NR_setns) +#include "setns.h" + +struct testcase_t { + const char *msg; + int fd; + int ns_type; + int exp_ret; + int exp_errno; + int skip; + void (*setup) (struct testcase_t *, int i); + void (*cleanup) (struct testcase_t *); +}; + +static void setup(void); +static void cleanup(void); +static void setup0(struct testcase_t *, int); +static void setup1(struct testcase_t *, int); +static void setup2(struct testcase_t *, int); +static void setup3(struct testcase_t *, int); +static void setup4(struct testcase_t *, int); +static void cleanup1(struct testcase_t *); +static void cleanup4(struct testcase_t *); + +struct testcase_t tdat[] = { + { + .msg = "invalid fd", + .fd = -1, + .exp_ret = -1, + .exp_errno = EBADF, + .setup = setup0, + }, + { + .msg = "regular file fd", + .exp_ret = -1, + .exp_errno = EINVAL, + .setup = setup1, + .cleanup = cleanup1 + }, + { + .msg = "invalid ns_type", + .ns_type = -1, + .exp_ret = -1, + .exp_errno = EINVAL, + .setup = setup2, + }, + { + .msg = "mismatch ns_type/fd", + .exp_ret = -1, + .exp_errno = EINVAL, + .setup = setup3, + }, + { + .msg = "without CAP_SYS_ADMIN", + .exp_ret = -1, + .exp_errno = EPERM, + .setup = setup4, + .cleanup = cleanup4, + } +}; + +static int TST_TOTAL = sizeof(tdat) / sizeof(tdat[0]); +static const char nobody_uid[] = "nobody"; +static struct passwd *ltpuser; + +static void setup0(struct testcase_t *t, int i) +{ + t->ns_type = ns_types[i]; +} + +static void setup1(struct testcase_t *t, int i) +{ + t->ns_type = ns_types[i]; + t->fd = open("dummy", O_CREAT); + if (t->fd == -1) + tst_brkm(TFAIL|TERRNO, cleanup, "setup1:open failed"); + unlink("dummy"); +} + +static void cleanup1(struct testcase_t *t) +{ + close(t->fd); +} + +static void setup2(struct testcase_t *t, int i) +{ + t->fd = ns_fds[i]; +} + +static void setup3(struct testcase_t *t, int i) +{ + if (ns_total < 2) { + t->skip = 1; + return; + } + + t->fd = ns_fds[i]; + t->ns_type = ns_types[(i+1) % ns_total]; +} + +static void setup4(struct testcase_t *t, int i) +{ + if (seteuid(ltpuser->pw_uid) == -1) + tst_brkm(TBROK | TERRNO, NULL, "seteuid failed"); + + t->fd = ns_fds[i]; + t->ns_type = ns_types[i]; +} + +static void cleanup4(struct testcase_t *t) +{ + if (seteuid(0) == -1) + tst_brkm(TBROK | TERRNO, NULL, "seteuid restore failed"); +} + +static void test_setns(struct testcase_t *t) +{ + int ret, i; + + for (i = 0; i < ns_total; i++) { + if (t->setup) + t->setup(t, i); + + if (t->skip) { + tst_resm(TINFO, "skip %s", tdat->msg); + continue; + } + + tst_resm(TINFO, "setns(%d, 0x%x)", t->fd, t->ns_type); + ret = syscall(__NR_setns, t->fd, t->ns_type); + if (ret == t->exp_ret) { + if (ret == -1 && errno == t->exp_errno) + tst_resm(TPASS, "%s exp_errno=%d", t->msg, + t->exp_errno); + else + tst_resm(TFAIL|TERRNO, "%s exp_errno=%d", + t->msg, t->exp_errno); + } else { + tst_resm(TFAIL, "%s ret=%d expected=%d", t->msg, + ret, t->exp_ret); + } + + if (t->cleanup) + t->cleanup(t); + } +} + +int main(int argc, char *argv[]) +{ + int lc, testno; + char *msg; + + msg = parse_opts(argc, argv, NULL, NULL); + if (msg != NULL) + tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg); + + setup(); + for (lc = 0; TEST_LOOPING(lc); lc++) { + for (testno = 0; testno < TST_TOTAL; testno++) + test_setns(&tdat[testno]); + } + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + tst_require_root(NULL); + + /* runtime check if syscall is supported */ + ltp_syscall(__NR_setns, -1, 0); + + init_available_ns(); + if (ns_total == 0) + tst_brkm(TCONF, NULL, "no ns types/proc entries"); + + ltpuser = getpwnam(nobody_uid); + if (ltpuser == NULL) + tst_brkm(TBROK | TERRNO, NULL, "getpwnam failed"); + + + tst_tmpdir(); + TEST_PAUSE; +} + +static void cleanup(void) +{ + close_ns_fds(); + tst_rmdir(); + TEST_CLEANUP; +} +#else +int main(int argc, char *argv[]) +{ + tst_brkm(TCONF, NULL, "__NR_setns is not defined on your system."); + +} +#endif -- 1.7.1 |
From: Jan S. <jst...@re...> - 2013-02-18 14:05:41
|
Signed-off-by: Jan Stancek <jst...@re...> --- testcases/kernel/syscalls/setns/Makefile | 23 +++++++++++++++++++++++ 1 files changed, 23 insertions(+), 0 deletions(-) create mode 100644 testcases/kernel/syscalls/setns/Makefile diff --git a/testcases/kernel/syscalls/setns/Makefile b/testcases/kernel/syscalls/setns/Makefile new file mode 100644 index 0000000..f1b5129 --- /dev/null +++ b/testcases/kernel/syscalls/setns/Makefile @@ -0,0 +1,23 @@ +# +# Copyright (C) 2013 Linux Test Project, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +# the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +top_srcdir ?= ../../../.. + +include $(top_srcdir)/include/mk/testcases.mk +CPPFLAGS += -Wno-unused-function +include $(top_srcdir)/include/mk/generic_leaf_target.mk -- 1.7.1 |
From: Wanlong G. <gao...@cn...> - 2013-02-19 02:15:45
|
On 02/18/2013 10:05 PM, Jan Stancek wrote: > Signed-off-by: Jan Stancek <jst...@re...> > --- > testcases/kernel/syscalls/setns/Makefile | 23 +++++++++++++++++++++++ > 1 files changed, 23 insertions(+), 0 deletions(-) > create mode 100644 testcases/kernel/syscalls/setns/Makefile Applied, thank you. Wanlong Gao |
From: Jan S. <jst...@re...> - 2013-02-18 14:05:46
|
functional test for setns(2) - reassociate thread with a namespace involving CLONE_NEWIPC and CLONE_NEWUTS. Signed-off-by: Jan Stancek <jst...@re...> --- runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/setns/setns02.c | 231 +++++++++++++++++++++++++++++ 3 files changed, 233 insertions(+), 0 deletions(-) create mode 100644 testcases/kernel/syscalls/setns/setns02.c diff --git a/runtest/syscalls b/runtest/syscalls index a881479..c70bcbd 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -963,6 +963,7 @@ setitimer02 setitimer02 setitimer03 setitimer03 setns01 setns01 +setns02 setns02 setpgid01 setpgid01 setpgid02 setpgid02 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index 4b8bb94..ce62f3f 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -765,6 +765,7 @@ /setitimer/setitimer02 /setitimer/setitimer03 /setns/setns01 +/setns/setns02 /setpgid/setpgid01 /setpgid/setpgid02 /setpgid/setpgid03 diff --git a/testcases/kernel/syscalls/setns/setns02.c b/testcases/kernel/syscalls/setns/setns02.c new file mode 100644 index 0000000..2033980 --- /dev/null +++ b/testcases/kernel/syscalls/setns/setns02.c @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2013 Linux Test Project, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ +/* + * functional test for setns(2) - reassociate thread with a namespace + * 1. create child with CLONE_NEWUTS, set different hostname in child, + * set namespace back to parent ns and check that hostname has changed + * 2. create child with CLONE_NEWIPC, set up shared memory in parent + * and verify that child can't shmat it, then set namespace + * back to parent one and verify that child is able to do shmat + */ +#define _GNU_SOURCE +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/stat.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <sys/utsname.h> +#include <sys/wait.h> +#include <errno.h> +#include <sched.h> +#include <string.h> +#include "config.h" +#include "test.h" +#include "usctest.h" +#include "linux_syscall_numbers.h" +#include "safe_macros.h" + +#define CHILD_STACK_SIZE (1024*1024) +#define CP "(child) " +char *TCID = "setns02"; + +#if defined(__NR_setns) && defined(CLONE_NEWIPC) && defined(CLONE_NEWUTS) +#include "setns.h" + +static char *dummy_hostname = "setns_dummy_uts"; +static int ns_ipc_fd; +static int ns_uts_fd; +static key_t ipc_key; +static int shmid; + +static void setup(void); +static void cleanup(void); + +static int do_child_newuts(void *arg) +{ + struct utsname uts, uts_parent; + int ns_flag = *(int *)arg; + + if (uname(&uts_parent) == -1) + tst_resm(TFAIL|TERRNO, CP"uname"); + tst_resm(TINFO, CP"hostname (inherited from parent): %s", + uts_parent.nodename); + + if (sethostname(dummy_hostname, strlen(dummy_hostname)) == -1) + tst_resm(TFAIL|TERRNO, CP"sethostname"); + if (uname(&uts) == -1) + tst_resm(TFAIL|TERRNO, CP"uname"); + + tst_resm(TINFO, CP"hostname changed to: %s", uts.nodename); + if (strcmp(uts_parent.nodename, uts.nodename) == 0) { + tst_resm(TFAIL, CP"expected hostname to be different"); + return 1; + } else { + tst_resm(TPASS, CP"hostname is different in parent/child"); + } + + tst_resm(TINFO, CP"attempting to switch ns back to parent ns"); + if (syscall(__NR_setns, ns_uts_fd, ns_flag) == -1) { + tst_resm(TFAIL|TERRNO, CP"setns"); + return 2; + } + if (uname(&uts) == -1) + tst_resm(TFAIL|TERRNO, CP"uname"); + + tst_resm(TINFO, CP"hostname: %s", uts.nodename); + if (strcmp(uts_parent.nodename, uts.nodename) != 0) { + tst_resm(TFAIL, CP"expected hostname to match parent"); + return 3; + } else { + tst_resm(TPASS, CP"hostname now as expected"); + } + return 0; +} + +static int do_child_newipc(void *arg) +{ + void *p; + int ns_flag = *(int *)arg; + + p = shmat(shmid, NULL, 0); + if (p == (void *) -1) { + tst_resm(TPASS|TERRNO, CP"shmat failed as expected"); + } else { + tst_resm(TFAIL, CP"shmat unexpectedly suceeded"); + shmdt(p); + return 1; + } + + tst_resm(TINFO, CP"attempting to switch ns back to parent ns"); + if (syscall(__NR_setns, ns_ipc_fd, ns_flag) == -1) { + tst_resm(TFAIL|TERRNO, CP"setns"); + return 2; + } + + p = shmat(shmid, NULL, 0); + if (p == (void *) -1) { + tst_resm(TFAIL|TERRNO, CP"shmat failed after setns"); + return 3; + } else { + tst_resm(TPASS, CP"shmat suceeded"); + shmdt(p); + } + + return 0; +} + +static void test_flag(int clone_flag, int ns_flag, int (*fn) (void *arg)) +{ + void *child_stack; + int ret, status; + + child_stack = malloc(CHILD_STACK_SIZE); + if (child_stack == NULL) + tst_brkm(TBROK, cleanup, "Cannot allocate stack for child"); + + tst_resm(TINFO, "creating child with clone_flag=0x%x, ns_flag=0x%x", + clone_flag, ns_flag); + ret = ltp_clone(SIGCHLD|clone_flag, fn, &ns_flag, + CHILD_STACK_SIZE, child_stack); + if (ret == -1) + tst_brkm(TBROK|TERRNO, cleanup, "ltp_clone"); + + if (waitpid(ret, &status, 0) == -1) + tst_brkm(TBROK|TERRNO, cleanup, "waitpid"); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + tst_resm(TFAIL, "child returns %d", status); + else + tst_resm(TPASS, "child finished succesfully"); + free(child_stack); +} + +int main(int argc, char *argv[]) +{ + int lc; + char *msg; + + msg = parse_opts(argc, argv, NULL, NULL); + if (msg != NULL) + tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg); + + setup(); + for (lc = 0; TEST_LOOPING(lc); lc++) { + if (ns_uts_fd != -1) { + tst_resm(TINFO, "test_newuts"); + test_flag(CLONE_NEWUTS, CLONE_NEWUTS, do_child_newuts); + test_flag(CLONE_NEWUTS, 0, do_child_newuts); + } + if (ns_ipc_fd != -1) { + tst_resm(TINFO, "test_newipc"); + test_flag(CLONE_NEWIPC, CLONE_NEWIPC, do_child_newipc); + test_flag(CLONE_NEWIPC, 0, do_child_newipc); + } + } + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + char tmp[PATH_MAX]; + + tst_require_root(NULL); + + /* runtime check if syscall is supported */ + ltp_syscall(__NR_setns, -1, 0); + + /* check if kernel has CONFIG_*_NS set and exports /proc entries */ + ns_ipc_fd = get_ns_fd(getpid(), "ipc"); + ns_uts_fd = get_ns_fd(getpid(), "uts"); + if (ns_ipc_fd == -1 && ns_uts_fd == -1) + tst_brkm(TCONF, NULL, "your kernel has CONFIG_IPC_NS, " + "CONFIG_UTS_NS or CONFIG_PROC disabled"); + + if (getcwd(tmp, PATH_MAX) == NULL) + tst_brkm(TBROK|TERRNO, NULL, "getcwd"); + ipc_key = ftok(tmp, 65); + shmid = shmget(ipc_key, getpagesize(), IPC_CREAT | 0666); + if (shmid == -1) + tst_brkm(TBROK|TERRNO, NULL, "shmget"); + + TEST_PAUSE; +} + +static void cleanup(void) +{ + if (ns_ipc_fd != -1) + close(ns_ipc_fd); + if (ns_uts_fd != -1) + close(ns_uts_fd); + + shmctl(shmid, IPC_RMID, NULL); + TEST_CLEANUP; +} +#else +int main(int argc, char *argv[]) +{ + tst_brkm(TCONF, NULL, "__NR_setns, CLONE_NEWIPC or CLONE_NEWUTS " + " is not defined on your system."); +} +#endif -- 1.7.1 |