* [PATCH 1/6][cr-test][v2]: eclone-1: Test basic functionality
@ 2010-02-09 19:33 Sukadev Bhattiprolu
[not found] ` <20100209193331.GB30005-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
0 siblings, 1 reply; 9+ messages in thread
From: Sukadev Bhattiprolu @ 2010-02-09 19:33 UTC (permalink / raw)
To: serue-r/Jw6+rmf7HQT0dZR+AlfA
Cc: Containers, sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8
From: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Date: Sat, 30 Jan 2010 12:49:30 -0800
Subject: [PATCH 1/6] eclone-1: Test basic functionality
Verify that a child process gets the expected pid and arguments on stack
when it is created with eclone() system call.
Changelog[v2]:
- Use libeclone.a from user-cr git tree so tests are portable across
architectures.
- Fix a couple of nits identified by Serge Hallyn
Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
Makefile | 2 +-
eclone/Makefile | 21 +++++++++
eclone/eclone-1.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++
eclone/eclone-tests.h | 66 +++++++++++++++++++++++++++
4 files changed, 207 insertions(+), 1 deletions(-)
create mode 100644 eclone/Makefile
create mode 100644 eclone/eclone-1.c
create mode 100644 eclone/eclone-tests.h
diff --git a/Makefile b/Makefile
index 95f8b6e..1d412b9 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
SUBDIRS = libcrtest counterloop fileio simple userns ipc sleep \
- process-tree futex epoll taskfs
+ process-tree futex epoll taskfs eclone
targets = ns_exec mysu
diff --git a/eclone/Makefile b/eclone/Makefile
new file mode 100644
index 0000000..10b63d3
--- /dev/null
+++ b/eclone/Makefile
@@ -0,0 +1,21 @@
+#
+# libeclone.a is built/installed from user-cr git-tree. Point USER_CR_DIR
+# to the directory containing libeclone.a and genstack.h
+#
+USER_CR_DIR ?= ../../user-cr
+
+CFLAGS = -Wall -I $(USER_CR_DIR)
+
+LDFLAGS =
+
+LIB_ECLONE = $(USER_CR_DIR)/libeclone.a
+
+PROGS = eclone-1
+
+all: $(PROGS)
+
+$(PROGS): %: %.c
+ $(CC) $(CFLAGS) -o $@ $< $(LIB_ECLONE) $(LDFLAGS)
+
+clean:
+ rm -f *.o $(PROGS)
diff --git a/eclone/eclone-1.c b/eclone/eclone-1.c
new file mode 100644
index 0000000..5aa69ed
--- /dev/null
+++ b/eclone/eclone-1.c
@@ -0,0 +1,119 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/syscall.h>
+#include "eclone-tests.h"
+#include "genstack.h"
+
+int verbose = 0;
+int child_tid, parent_tid;
+
+#define CHILD_TID1 377
+#define CHILD_ARG (void *)0x979797
+
+pid_t pids[] = { CHILD_TID1 };
+
+int do_child(void *arg)
+{
+ sleep(3);
+
+ if (arg != CHILD_ARG) {
+ printf("ERROR: Expected arg %p, actual %p\n", CHILD_ARG, arg);
+ exit(1);
+ }
+
+ if (gettid() != CHILD_TID1) {
+ printf("FAIL: Child expected pid %d, actual %d\n", CHILD_TID1,
+ getpid());
+ exit(2);
+ } else {
+ printf("PASS: Child got expected pid %d\n", CHILD_TID1);
+ exit(0);
+ }
+
+}
+
+static int do_eclone(int (*child_fn)(void *), void *child_arg,
+ unsigned int flags_low, int nr_pids, pid_t *pids)
+{
+ int rc;
+ struct clone_args clone_args;
+ genstack stack;
+
+ stack = genstack_alloc(STACKSIZE);
+ if (!stack) {
+ printf("ERROR: genstack_alloc() returns NULL for size %d\n",
+ STACKSIZE);
+ exit(1);
+ }
+
+ memset(&clone_args, 0, sizeof(clone_args));
+ clone_args.child_stack = (u64)(int)genstack_sp(stack);
+ clone_args.child_stack_size = (u64)0;
+ clone_args.parent_tid_ptr = (u64)((int)&parent_tid);
+ clone_args.child_tid_ptr = (u64)((int)&child_tid);
+ clone_args.nr_pids = nr_pids;
+
+ if (verbose) {
+ printf("[%d, %d]: Parent:\n\t child_stack 0x%p, ptidp %llx, "
+ "ctidp %llx, pids %p\n", getpid(), gettid(),
+ stack, clone_args.parent_tid_ptr,
+ clone_args.child_tid_ptr, pids);
+ }
+
+ rc = eclone(child_fn, child_arg, flags_low, &clone_args, pids);
+
+ if (verbose) {
+ printf("[%d, %d]: eclone() returned %d, error %d\n", getpid(),
+ gettid(), rc, errno);
+ fflush(stdout);
+ }
+
+ if (rc < 0) {
+ printf("ERROR: rc %d, errno %d\n", rc, errno);
+ exit(1);
+ }
+
+ return rc;
+}
+
+int main()
+{
+ int rc, pid, status;
+ unsigned long flags;
+ int nr_pids = 1;
+
+ flags = SIGCHLD|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID;
+
+ pid = do_eclone(do_child, CHILD_ARG, flags, nr_pids, pids);
+
+ if (verbose) {
+ printf("[%d, %d]: Parent waiting for %d\n", getpid(),
+ gettid(), pid);
+ }
+
+ rc = waitpid(pid, &status, __WALL);
+ if (rc < 0) {
+ printf("ERROR: ");
+ verbose = 1;
+ }
+
+ if (verbose) {
+ printf("\twaitpid(): child %d, rc %d, error %d, status 0x%x\n",
+ getpid(), rc, errno, status);
+ if (rc >=0) {
+ if (WIFEXITED(status)) {
+ printf("\t EXITED, %d\n", WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+ printf("\t SIGNALED, %d\n", WTERMSIG(status));
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/eclone/eclone-tests.h b/eclone/eclone-tests.h
new file mode 100644
index 0000000..f869f99
--- /dev/null
+++ b/eclone/eclone-tests.h
@@ -0,0 +1,66 @@
+#include <errno.h>
+
+/*
+ * Some of these definitions need to eventually be defined in system files
+ * like <sys/types.h>, <sched.h> etc
+ */
+#ifndef CLONE_NEWPID
+#define CLONE_NEWPID 0x20000000
+#endif
+
+#ifndef CLONE_CHILD_SETTID
+#define CLONE_CHILD_SETTID 0x01000000
+#endif
+
+#ifndef CLONE_PARENT_SETTID
+#define CLONE_PARENT_SETTID 0x00100000
+#endif
+
+#ifndef CLONE_UNUSED
+#define CLONE_UNUSED 0x00001000
+#endif
+
+#define STACKSIZE 8192
+
+typedef unsigned long long u64;
+typedef unsigned int u32;
+typedef int pid_t;
+
+struct clone_args {
+ u64 clone_flags_high;
+ /*
+ * Architectures can use child_stack for either the stack pointer or
+ * the base of of stack. If child_stack is used as the stack pointer,
+ * child_stack_size must be 0. Otherwise child_stack_size must be
+ * set to size of allocated stack.
+ */
+ u64 child_stack;
+ u64 child_stack_size;
+ u64 parent_tid_ptr;
+ u64 child_tid_ptr;
+ u32 nr_pids;
+ u32 reserved0;
+};
+
+int eclone(int (*fn)(void *), void *fn_arg, int clone_flags_low,
+ struct clone_args *clone_args, pid_t *pids);
+
+#if __i386__
+# define __NR_gettid 224
+#elif __x86_64__
+# define __NR_gettid 186
+#elif __ia64__
+# define __NR_gettid 1105
+#elif __s390x__
+# define __NR_gettid 236
+#elif __powerpc__
+# define __NR_gettid 207
+#else
+# error "Architecture not supported for gettid()"
+#endif
+
+/* gettid() is sometimes more useful than getpid() when using clone() */
+static inline int gettid()
+{
+ return syscall(__NR_gettid, 0, 0, 0);
+}
--
1.6.6.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/6][cr-test][v2]: eclone-2: Ensure eclone() fails if selected pid is in use
[not found] ` <20100209193331.GB30005-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
@ 2010-02-09 19:34 ` Sukadev Bhattiprolu
2010-02-09 19:35 ` [PATCH 3/6][cr-test][v2]: Verify eclone() fails if reserved fields are not 0 Sukadev Bhattiprolu
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Sukadev Bhattiprolu @ 2010-02-09 19:34 UTC (permalink / raw)
To: serue-r/Jw6+rmf7HQT0dZR+AlfA; +Cc: Containers
From: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Date: Sat, 30 Jan 2010 12:51:23 -0800
Subject: [PATCH 2/6] eclone-2: Ensure eclone() fails if selected pid is in use
Ensure that eclone() system call fails with -EBUSY if selected pid is in use.
Changelog[v2]:
- Use libeclone.a from user-cr git tree so tests are portable across
architectures.
- Fix a few nits identified by Serge Hallyn
Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
eclone/Makefile | 2 +-
eclone/eclone-2.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 117 insertions(+), 1 deletions(-)
create mode 100644 eclone/eclone-2.c
diff --git a/eclone/Makefile b/eclone/Makefile
index 10b63d3..91aaffc 100644
--- a/eclone/Makefile
+++ b/eclone/Makefile
@@ -10,7 +10,7 @@ LDFLAGS =
LIB_ECLONE = $(USER_CR_DIR)/libeclone.a
-PROGS = eclone-1
+PROGS = eclone-1 eclone-2
all: $(PROGS)
diff --git a/eclone/eclone-2.c b/eclone/eclone-2.c
new file mode 100644
index 0000000..5641247
--- /dev/null
+++ b/eclone/eclone-2.c
@@ -0,0 +1,116 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/syscall.h>
+#include "eclone-tests.h"
+#include "genstack.h"
+
+/*
+ * Verify that eclone() fails if the selected pid is in use.
+ * We try to assign parent's pid which should already be in use.
+ */
+int verbose = 0;
+int child_tid, parent_tid;
+#define CHILD_ARG (void *)0x979797
+
+pid_t pids[2];
+
+int do_child(void *arg)
+{
+ printf("FAIL: Child created with [%d, %d], but we expected child "
+ "creation to fail since pid is in use\n", gettid(),
+ getpid());
+ exit(2);
+}
+
+static int do_eclone(int (*child_fn)(void *), void *child_arg,
+ unsigned int flags_low, int nr_pids, pid_t *pids)
+{
+ int rc;
+ void *stack;
+ struct clone_args clone_args;
+
+ stack = genstack_alloc(STACKSIZE);
+ if (!stack) {
+ printf("ERROR: genstack_alloc() returns NULL for size %d\n",
+ STACKSIZE);
+ exit(1);
+ }
+
+ memset(&clone_args, 0, sizeof(clone_args));
+ clone_args.child_stack = (u64)(int)genstack_sp(stack);
+ clone_args.child_stack_size = (u64)0;
+ clone_args.parent_tid_ptr = (u64)((int)&parent_tid);
+ clone_args.child_tid_ptr = (u64)((int)&child_tid);
+ clone_args.nr_pids = nr_pids;
+
+ if (verbose) {
+ printf("[%d, %d]: Parent:\n\t child_stack 0x%p, ptidp %llx, "
+ "ctidp %llx, pids %p\n", getpid(), gettid(),
+ stack, clone_args.parent_tid_ptr,
+ clone_args.child_tid_ptr, pids);
+ }
+
+ rc = eclone(child_fn, child_arg, flags_low, &clone_args, pids);
+
+ if (verbose) {
+ printf("[%d, %d]: eclone() returned %d, error %d\n", getpid(),
+ gettid(), rc, errno);
+ fflush(stdout);
+ }
+
+ if (rc < 0 && errno == EAGAIN) {
+ printf("PASS: Unable to create a process with a pid that is "
+ "in use\n");
+ exit(0);
+ } else {
+ printf("ERROR: eclone(): rc %d, errno %d\n", rc, errno);
+ return rc;
+ }
+}
+
+int main()
+{
+ int rc, pid, status;
+ unsigned long flags;
+ int nr_pids;
+
+ flags = SIGCHLD;
+
+ /*
+ * Try to create a process with same pid as parent !
+ */
+ pids[0] = getpid();
+ nr_pids = 1;
+
+ pid = do_eclone(do_child, CHILD_ARG, flags, nr_pids, pids);
+
+ if (verbose) {
+ printf("[%d, %d]: Parent waiting for %d\n", getpid(),
+ gettid(), pid);
+ }
+
+ rc = waitpid(pid, &status, __WALL);
+ if (rc < 0) {
+ printf("ERROR: ");
+ verbose = 1;
+ }
+
+ if (verbose) {
+ printf("\twaitpid(): child %d, rc %d, error %d, status 0x%x\n",
+ getpid(), rc, errno, status);
+ if (rc >=0) {
+ if (WIFEXITED(status)) {
+ printf("\t EXITED, %d\n", WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+ printf("\t SIGNALED, %d\n", WTERMSIG(status));
+ }
+ }
+ }
+ return 0;
+}
--
1.6.6.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/6][cr-test][v2]: Verify eclone() fails if reserved fields are not 0.
[not found] ` <20100209193331.GB30005-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-02-09 19:34 ` [PATCH 2/6][cr-test][v2]: eclone-2: Ensure eclone() fails if selected pid is in use Sukadev Bhattiprolu
@ 2010-02-09 19:35 ` Sukadev Bhattiprolu
2010-02-09 19:35 ` [PATCH 4/6][cr-test][v2]: Verify eclone() fails if clone_flags_high is non-zero Sukadev Bhattiprolu
` (2 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Sukadev Bhattiprolu @ 2010-02-09 19:35 UTC (permalink / raw)
To: serue-r/Jw6+rmf7HQT0dZR+AlfA; +Cc: Containers
From: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Date: Sat, 30 Jan 2010 12:53:04 -0800
Subject: [PATCH 3/6] eclone-3: Verify eclone() fails if reserved fields are not 0.
To ensure future extendability, we want the unused fields to be 0.
Ensure eclone() fails if ->reserved0 field is non-0.
Changelog[v2]:
- Use libeclone.a from user-cr git tree so tests are portable across
architectures.
- Fix some nits identified by Serge Hallyn
Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
eclone/Makefile | 2 +-
eclone/eclone-3.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 117 insertions(+), 1 deletions(-)
create mode 100644 eclone/eclone-3.c
diff --git a/eclone/Makefile b/eclone/Makefile
index 91aaffc..ee0471f 100644
--- a/eclone/Makefile
+++ b/eclone/Makefile
@@ -10,7 +10,7 @@ LDFLAGS =
LIB_ECLONE = $(USER_CR_DIR)/libeclone.a
-PROGS = eclone-1 eclone-2
+PROGS = eclone-1 eclone-2 eclone-3
all: $(PROGS)
diff --git a/eclone/eclone-3.c b/eclone/eclone-3.c
new file mode 100644
index 0000000..38ddd7b
--- /dev/null
+++ b/eclone/eclone-3.c
@@ -0,0 +1,116 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/syscall.h>
+#include "eclone-tests.h"
+#include "genstack.h"
+
+/*
+ * Verify that eclone() fails if ->reserved0 field is non-zero.
+ */
+int verbose = 0;
+int child_tid, parent_tid;
+
+#define CHILD_TID1 377
+#define CHILD_ARG (void *)0x979797
+
+pid_t pids[] = { CHILD_TID1 };
+
+int do_child(void *arg)
+{
+ printf("FAIL: Child created with [%d, %d]. We expected eclone() to "
+ "fail with EINVAL since ->reserved0 is non-zero\n",
+ gettid(), getpid());
+ exit(2);
+}
+
+static int do_eclone(int (*child_fn)(void *), void *child_arg,
+ unsigned int flags_low, int nr_pids, pid_t *pids)
+{
+ int rc;
+ void *stack;
+ struct clone_args clone_args;
+ int args_size;
+
+ stack = genstack_alloc(STACKSIZE);
+ if (!stack) {
+ printf("ERROR: genstack_alloc() returns NULL for size %d\n",
+ STACKSIZE);
+ exit(1);
+ }
+
+ memset(&clone_args, 0, sizeof(clone_args));
+ clone_args.child_stack = (u64)(int)genstack_sp(stack);
+ clone_args.child_stack_size = (u64)0;
+ clone_args.parent_tid_ptr = (u64)((int)&parent_tid);
+ clone_args.child_tid_ptr = (u64)((int)&child_tid);
+ clone_args.reserved0 = 0xdeadbeef;
+ clone_args.nr_pids = nr_pids;
+
+ if (verbose) {
+ printf("[%d, %d]: Parent:\n\t child_stack 0x%p, ptidp %llx, "
+ "ctidp %llx, pids %p\n", getpid(), gettid(),
+ stack, clone_args.parent_tid_ptr,
+ clone_args.child_tid_ptr, pids);
+ }
+
+ args_size = sizeof(struct clone_args);
+ rc = eclone(child_fn, child_arg, flags_low, &clone_args, pids);
+
+ if (verbose) {
+ printf("[%d, %d]: eclone() returned %d, error %d\n", getpid(),
+ gettid(), rc, errno);
+ fflush(stdout);
+ }
+
+ if (rc < 0 && errno == EINVAL) {
+ printf("PASS: eclone() failed (->reserved0 is not 0)\n");
+ exit(0);
+ } else {
+ printf("FAIL: Expected eclone() to fail with EINVAL");
+ exit(1);
+ }
+
+ return rc;
+}
+
+int main()
+{
+ int rc, pid, status;
+ unsigned long flags;
+ int nr_pids = 1;
+
+ flags = SIGCHLD;
+
+ pid = do_eclone(do_child, CHILD_ARG, flags, nr_pids, pids);
+
+ if (verbose) {
+ printf("[%d, %d]: Parent waiting for %d\n", getpid(),
+ gettid(), pid);
+ }
+
+ rc = waitpid(pid, &status, __WALL);
+ if (rc < 0) {
+ printf("ERROR: ");
+ verbose = 1;
+ }
+
+ if (verbose) {
+ printf("\twaitpid(): child %d, rc %d, error %d, status 0x%x\n",
+ getpid(), rc, errno, status);
+ if (rc >=0) {
+ if (WIFEXITED(status)) {
+ printf("\t EXITED, %d\n", WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+ printf("\t SIGNALED, %d\n", WTERMSIG(status));
+ }
+ }
+ }
+
+ return 0;
+}
--
1.6.6.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/6][cr-test][v2]: Verify eclone() fails if clone_flags_high is non-zero
[not found] ` <20100209193331.GB30005-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-02-09 19:34 ` [PATCH 2/6][cr-test][v2]: eclone-2: Ensure eclone() fails if selected pid is in use Sukadev Bhattiprolu
2010-02-09 19:35 ` [PATCH 3/6][cr-test][v2]: Verify eclone() fails if reserved fields are not 0 Sukadev Bhattiprolu
@ 2010-02-09 19:35 ` Sukadev Bhattiprolu
2010-02-09 19:36 ` [PATCH 5/6][cr-test][v2]: eclone-5: nr_pids must not exceed nesting level Sukadev Bhattiprolu
2010-02-09 19:37 ` [PATCH 6/6][cr-test][v2]: eclone/runtests.sh: Wrapper script for eclone tests Sukadev Bhattiprolu
4 siblings, 0 replies; 9+ messages in thread
From: Sukadev Bhattiprolu @ 2010-02-09 19:35 UTC (permalink / raw)
To: serue-r/Jw6+rmf7HQT0dZR+AlfA; +Cc: Containers
From: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Date: Mon, 1 Feb 2010 18:10:32 -0800
Subject: [PATCH 4/6] eclone-4: Verify eclone() fails if clone_flags_high is non-zero
To ensure future extendability, we want the unused fields to be 0. Ensure
eclone() fails if ->clone_flags_high field is non-0.
Changelog[v2]:
- Use libeclone.a from user-cr git tree so tests are portable across
architectures.
- Fix some nits identified by Serge Hallyn
Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
eclone/Makefile | 2 +-
eclone/eclone-4.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 116 insertions(+), 1 deletions(-)
create mode 100644 eclone/eclone-4.c
diff --git a/eclone/Makefile b/eclone/Makefile
index ee0471f..ba3d6ac 100644
--- a/eclone/Makefile
+++ b/eclone/Makefile
@@ -10,7 +10,7 @@ LDFLAGS =
LIB_ECLONE = $(USER_CR_DIR)/libeclone.a
-PROGS = eclone-1 eclone-2 eclone-3
+PROGS = eclone-1 eclone-2 eclone-3 eclone-4
all: $(PROGS)
diff --git a/eclone/eclone-4.c b/eclone/eclone-4.c
new file mode 100644
index 0000000..1b6cf86
--- /dev/null
+++ b/eclone/eclone-4.c
@@ -0,0 +1,115 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/syscall.h>
+#include "eclone-tests.h"
+#include "genstack.h"
+
+/*
+ * Verify that eclone() fails if ->clone_flags_high is not 0.
+ */
+int verbose = 0;
+int child_tid, parent_tid;
+
+#define CHILD_TID1 377
+#define CHILD_ARG (void *)0x979797
+
+pid_t pids[] = { CHILD_TID1 };
+
+int do_child(void *arg)
+{
+ printf("FAIL: Child created with [%d, %d]. We expected eclone() to "
+ "fail with EINVAL since clone_flags_high is not 0\n",
+ gettid(), getpid());
+ exit(2);
+}
+
+static int do_eclone(int (*child_fn)(void *), void *child_arg,
+ unsigned int flags_low, int nr_pids, pid_t *pids)
+{
+ int rc;
+ void *stack;
+ struct clone_args clone_args;
+ int args_size;
+
+ stack = genstack_alloc(STACKSIZE);
+ if (!stack) {
+ printf("ERROR: setup_stack returns NULL for size %d\n",
+ STACKSIZE);
+ exit(1);
+ }
+
+ memset(&clone_args, 0, sizeof(clone_args));
+ clone_args.clone_flags_high = (u64)1 << 33;
+ clone_args.child_stack = (u64)(int)genstack_sp(stack);
+ clone_args.child_stack_size = (u64)0;
+ clone_args.parent_tid_ptr = (u64)((int)&parent_tid);
+ clone_args.child_tid_ptr = (u64)((int)&child_tid);
+ clone_args.nr_pids = nr_pids;
+
+ if (verbose) {
+ printf("[%d, %d]: Parent:\n\t child_stack 0x%p, ptidp %llx, "
+ "ctidp %llx, pids %p\n", getpid(), gettid(),
+ stack, clone_args.parent_tid_ptr,
+ clone_args.child_tid_ptr, pids);
+ }
+
+ args_size = sizeof(struct clone_args);
+ rc = eclone(child_fn, child_arg, flags_low, &clone_args, pids);
+
+ if (verbose) {
+ printf("[%d, %d]: eclone() returned %d, error %d\n", getpid(),
+ gettid(), rc, errno);
+ fflush(stdout);
+ }
+
+ if (rc < 0 && errno == EINVAL) {
+ printf("PASS: eclone() failed (clone_flags_high not 0)\n");
+ exit(0);
+ } else {
+ printf("FAIL: Expected eclone() to fail with EINVAL");
+ exit(1);
+ }
+
+ return rc;
+}
+
+int main()
+{
+ int rc, pid, status;
+ unsigned long flags;
+ int nr_pids = 1;
+
+ flags = SIGCHLD;
+
+ pid = do_eclone(do_child, CHILD_ARG, flags, nr_pids, pids);
+
+ if (verbose) {
+ printf("[%d, %d]: Parent waiting for %d\n", getpid(),
+ gettid(), pid);
+ }
+
+ rc = waitpid(pid, &status, __WALL);
+ if (rc < 0) {
+ printf("ERROR: ");
+ verbose = 1;
+ }
+
+ if (verbose) {
+ printf("\twaitpid(): child %d, rc %d, error %d, status 0x%x\n",
+ getpid(), rc, errno, status);
+ if (rc >=0) {
+ if (WIFEXITED(status)) {
+ printf("\t EXITED, %d\n", WEXITSTATUS(status));
+ } else if (WIFSIGNALED(status)) {
+ printf("\t SIGNALED, %d\n", WTERMSIG(status));
+ }
+ }
+ }
+ return 0;
+}
--
1.6.6.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 5/6][cr-test][v2]: eclone-5: nr_pids must not exceed nesting level
[not found] ` <20100209193331.GB30005-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
` (2 preceding siblings ...)
2010-02-09 19:35 ` [PATCH 4/6][cr-test][v2]: Verify eclone() fails if clone_flags_high is non-zero Sukadev Bhattiprolu
@ 2010-02-09 19:36 ` Sukadev Bhattiprolu
[not found] ` <20100209193619.GD32274-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-02-09 19:37 ` [PATCH 6/6][cr-test][v2]: eclone/runtests.sh: Wrapper script for eclone tests Sukadev Bhattiprolu
4 siblings, 1 reply; 9+ messages in thread
From: Sukadev Bhattiprolu @ 2010-02-09 19:36 UTC (permalink / raw)
To: serue-r/Jw6+rmf7HQT0dZR+AlfA; +Cc: Containers
From: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Date: Mon, 1 Feb 2010 18:13:51 -0800
Subject: [PATCH 5/6] eclone-5: nr_pids must not exceed nesting level
Verify that eclone() fails if nr_pids exceeds the current nesting level
of pid namespaces. Also verify that eclone() succeeds in choosing a pid
for a process in a descendant pid namespace.
Changelog[v2]:
- Use libeclone.a from user-cr git tree so tests are portable across
architectures.
- Fix some nits identified by Serge Hallyn
Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
eclone/Makefile | 2 +-
eclone/eclone-5.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 176 insertions(+), 1 deletions(-)
create mode 100644 eclone/eclone-5.c
diff --git a/eclone/Makefile b/eclone/Makefile
index ba3d6ac..7bd5585 100644
--- a/eclone/Makefile
+++ b/eclone/Makefile
@@ -10,7 +10,7 @@ LDFLAGS =
LIB_ECLONE = $(USER_CR_DIR)/libeclone.a
-PROGS = eclone-1 eclone-2 eclone-3 eclone-4
+PROGS = eclone-1 eclone-2 eclone-3 eclone-4 eclone-5
all: $(PROGS)
diff --git a/eclone/eclone-5.c b/eclone/eclone-5.c
new file mode 100644
index 0000000..2d36898
--- /dev/null
+++ b/eclone/eclone-5.c
@@ -0,0 +1,175 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/syscall.h>
+#define _GNU_SOURCE
+#include <sched.h>
+#include "eclone-tests.h"
+#include "genstack.h"
+
+/*
+ * Verify that eclone() fails if nr_pids exceeds the current nesting level
+ * of pid namespaces
+ */
+int verbose = 0;
+
+#define CHILD_TID1 377
+#define CHILD_TID2 399
+#define CHILD_ARG (void *)0x979797
+
+pid_t pids[] = { CHILD_TID1, CHILD_TID2 };
+int parent_tid;
+int child_tid;
+
+int do_child(void *arg)
+{
+ if (verbose)
+ printf("Child created with [%d, %d]\n", gettid(), getpid());
+
+ sleep(2);
+ exit(0);
+}
+
+static int do_eclone(int (*child_fn)(void *), void *child_arg,
+ unsigned int flags_low, int nr_pids, pid_t *pids)
+{
+ int rc;
+ void *stack;
+ struct clone_args clone_args;
+ int args_size;
+
+ stack = genstack_alloc(STACKSIZE);
+ if (!stack) {
+ printf("ERROR: setup_stack returns NULL for size %d\n",
+ STACKSIZE);
+ exit(1);
+ }
+
+ memset(&clone_args, 0, sizeof(clone_args));
+ clone_args.child_stack = (u64)(int)genstack_sp(stack);
+ clone_args.child_stack_size = (u64)0;
+ clone_args.parent_tid_ptr = (u64)((int)&parent_tid);
+ clone_args.child_tid_ptr = (u64)((int)&child_tid);
+ clone_args.nr_pids = nr_pids;
+
+ if (verbose) {
+ printf("[%d, %d]: Parent:\n\t child_stack 0x%p, ptidp %llx, "
+ "ctidp %llx, pids %p\n", getpid(), gettid(),
+ stack, clone_args.parent_tid_ptr,
+ clone_args.child_tid_ptr, pids);
+ }
+
+ errno = 0;
+ args_size = sizeof(struct clone_args);
+ rc = eclone(child_fn, child_arg, flags_low, &clone_args, pids);
+
+ if (verbose) {
+ printf("[%d, %d]: eclone() returned %d, error %d\n", getpid(),
+ gettid(), rc, errno);
+ fflush(stdout);
+ }
+
+ return rc;
+}
+
+int do_test(void *arg)
+{
+ int rc, pid, status;
+ unsigned long flags;
+ int nested_ns;
+ int nr_pids;
+ int error;
+
+ nested_ns = *(int *)arg;
+ nr_pids = 2;
+
+ flags = SIGCHLD|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID;
+
+ pid = do_eclone(do_child, CHILD_ARG, flags, nr_pids, pids);
+
+ error = 0;
+ if (pid < 0)
+ error = errno;
+
+ /* If we did create a child, wait for it to exit */
+ if (pid > 0) {
+ rc = waitpid(pid, &status, __WALL);
+ if (rc < 0) {
+ printf("%d: ERROR: waitpid() rc %d, error %d\n",
+ getpid(), rc, errno);
+ verbose = 1;
+ }
+ }
+
+ if (verbose) {
+ printf("%d: nested_ns %d, pid %d, error %d\n", getpid(),
+ nested_ns, pid, error);
+ }
+
+ /*
+ * We set nr_pids to 2 above. If we cloned from current pid ns,
+ * eclone() must fail with EINVAL. If we eclone() from a nested pid
+ * ns, eclone() must succeed. In all other cases, test has failed.
+ */
+ rc = 0;
+ if (!nested_ns && (pid < 0) && (error == EINVAL)) {
+ printf("%d: PASSED: Got EINVAL when nr_pids > nesting-depth\n",
+ getpid());
+ } else if (nested_ns && (pid > 0)) {
+ printf("%d: PASSED: eclone() succeeded in nested pid-ns, "
+ "pid %d\n", getpid(), pid);
+ } else {
+ printf("%d: FAILED: nested_ns %d, pid %d, error %d\n", getpid(),
+ nested_ns, pid, error);
+ rc = 1;
+ }
+
+ fflush(stdout);
+ return rc;
+}
+
+int main()
+{
+ int rc, pid, status;
+ int nested_ns;
+ unsigned long flags;
+ void *stack;
+
+ /* First test in current pid namespace */
+ nested_ns = 0;
+ rc = do_test(&nested_ns);
+ if (rc)
+ exit(rc);
+
+ /* Then test in a nested pid-namespace - use normal clone() */
+ stack = malloc(STACKSIZE);
+ if (!stack) {
+ printf("ERROR: setup_stack returns NULL for size %d\n",
+ STACKSIZE);
+ exit(1);
+ }
+ stack += (STACKSIZE - 1);
+
+ nested_ns = 1;
+ flags = SIGCHLD|CLONE_NEWPID|CLONE_NEWNS;
+ pid = clone(do_test, stack, flags, (void *)&nested_ns, NULL, NULL, NULL);
+ if (pid < 0) {
+ printf("ERROR: clone() failed, pid %d, error %s\n", pid,
+ strerror(errno));
+ exit(1);
+ }
+
+ rc = waitpid(pid, &status, __WALL);
+ if (rc < 0) {
+ printf("ERROR: waitpid() failed, rc %d, error %s\n", rc,
+ strerror(errno));
+ fflush(stdout);
+ exit(1);
+ }
+ return 0;
+}
--
1.6.6.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 6/6][cr-test][v2]: eclone/runtests.sh: Wrapper script for eclone tests
[not found] ` <20100209193331.GB30005-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
` (3 preceding siblings ...)
2010-02-09 19:36 ` [PATCH 5/6][cr-test][v2]: eclone-5: nr_pids must not exceed nesting level Sukadev Bhattiprolu
@ 2010-02-09 19:37 ` Sukadev Bhattiprolu
4 siblings, 0 replies; 9+ messages in thread
From: Sukadev Bhattiprolu @ 2010-02-09 19:37 UTC (permalink / raw)
To: serue-r/Jw6+rmf7HQT0dZR+AlfA; +Cc: Containers
From: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
Date: Tue, 2 Feb 2010 11:21:07 -0800
Subject: [PATCH 6/6] eclone/runtests.sh: Wrapper script for eclone tests
A simple wrapper script to run all eclone tests in this directory.
Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
eclone/runtests.sh | 23 +++++++++++++++++++++++
1 files changed, 23 insertions(+), 0 deletions(-)
create mode 100755 eclone/runtests.sh
diff --git a/eclone/runtests.sh b/eclone/runtests.sh
new file mode 100755
index 0000000..de3f586
--- /dev/null
+++ b/eclone/runtests.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+TEST_LOG=`mktemp -p . runtests-XXXXXXX`.log
+
+echo Logfile: $TEST_LOG
+
+> $TEST_LOG
+
+TESTS="eclone-1 eclone-2 eclone-3 eclone-4 eclone-5"
+#TESTS="eclone-5"
+
+for t in $TESTS
+do
+ echo "===== Test: $t" >> $TEST_LOG
+ ./$t >> $TEST_LOG 2>&1
+ if [ $? -eq 0 ]; then
+ echo "Test '$t' PASSED" >> $TEST_LOG
+ else
+ echo "Test '$t' FAILED" >> $TEST_LOG
+ fi
+done
+
+cat $TEST_LOG
--
1.6.6.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 5/6][cr-test][v2]: eclone-5: nr_pids must not exceed nesting level
[not found] ` <20100209193619.GD32274-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
@ 2010-02-09 21:17 ` Serge E. Hallyn
[not found] ` <20100209211705.GA32631-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
0 siblings, 1 reply; 9+ messages in thread
From: Serge E. Hallyn @ 2010-02-09 21:17 UTC (permalink / raw)
To: Sukadev Bhattiprolu; +Cc: Containers
Quoting Sukadev Bhattiprolu (sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org):
>
> From: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
> Date: Mon, 1 Feb 2010 18:13:51 -0800
> Subject: [PATCH 5/6] eclone-5: nr_pids must not exceed nesting level
>
> Verify that eclone() fails if nr_pids exceeds the current nesting level
> of pid namespaces. Also verify that eclone() succeeds in choosing a pid
> for a process in a descendant pid namespace.
This is a bit of a shame - it failed for me at first because I was
running it inside a container. But there is no way for a task to
know it's own nsdepth right?
So I went ahead and pushed these tests (plus a few changes).
thanks,
-serge
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 5/6][cr-test][v2]: eclone-5: nr_pids must not exceed nesting level
[not found] ` <20100209211705.GA32631-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
@ 2010-02-10 1:28 ` Sukadev Bhattiprolu
[not found] ` <20100210012831.GA20795-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
0 siblings, 1 reply; 9+ messages in thread
From: Sukadev Bhattiprolu @ 2010-02-10 1:28 UTC (permalink / raw)
To: Serge E. Hallyn; +Cc: Containers
Serge E. Hallyn [serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org] wrote:
| Quoting Sukadev Bhattiprolu (sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org):
| >
| > From: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
| > Date: Mon, 1 Feb 2010 18:13:51 -0800
| > Subject: [PATCH 5/6] eclone-5: nr_pids must not exceed nesting level
| >
| > Verify that eclone() fails if nr_pids exceeds the current nesting level
| > of pid namespaces. Also verify that eclone() succeeds in choosing a pid
| > for a process in a descendant pid namespace.
|
| This is a bit of a shame - it failed for me at first because I was
| running it inside a container. But there is no way for a task to
| know it's own nsdepth right?
Nope - or at least I don't know of any way.
We could modify the test to set nr_pids to a ridiculously large value
just to test that eclone() fails when nr_pids exceeds nesting level.
|
| So I went ahead and pushed these tests (plus a few changes).
Thanks,
Sukadev
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 5/6][cr-test][v2]: eclone-5: nr_pids must not exceed nesting level
[not found] ` <20100210012831.GA20795-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
@ 2010-02-10 15:47 ` Serge E. Hallyn
0 siblings, 0 replies; 9+ messages in thread
From: Serge E. Hallyn @ 2010-02-10 15:47 UTC (permalink / raw)
To: Sukadev Bhattiprolu; +Cc: Containers
Quoting Sukadev Bhattiprolu (sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org):
> Serge E. Hallyn [serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org] wrote:
> | Quoting Sukadev Bhattiprolu (sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org):
> | >
> | > From: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
> | > Date: Mon, 1 Feb 2010 18:13:51 -0800
> | > Subject: [PATCH 5/6] eclone-5: nr_pids must not exceed nesting level
> | >
> | > Verify that eclone() fails if nr_pids exceeds the current nesting level
> | > of pid namespaces. Also verify that eclone() succeeds in choosing a pid
> | > for a process in a descendant pid namespace.
> |
> | This is a bit of a shame - it failed for me at first because I was
> | running it inside a container. But there is no way for a task to
> | know it's own nsdepth right?
>
> Nope - or at least I don't know of any way.
>
> We could modify the test to set nr_pids to a ridiculously large value
> just to test that eclone() fails when nr_pids exceeds nesting level.
Yeah though it's nice to be able to test the boundary conditions.
I suppose it could take an optional nesting level argument - if not
specified use 20. Then in documentation recommend that people run
eclone-5 2
from init_pid_ns. The motivation would be to have the automated testing
not return false positives!
> | So I went ahead and pushed these tests (plus a few changes).
>
> Thanks,
>
> Sukadev
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2010-02-10 15:47 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-02-09 19:33 [PATCH 1/6][cr-test][v2]: eclone-1: Test basic functionality Sukadev Bhattiprolu
[not found] ` <20100209193331.GB30005-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-02-09 19:34 ` [PATCH 2/6][cr-test][v2]: eclone-2: Ensure eclone() fails if selected pid is in use Sukadev Bhattiprolu
2010-02-09 19:35 ` [PATCH 3/6][cr-test][v2]: Verify eclone() fails if reserved fields are not 0 Sukadev Bhattiprolu
2010-02-09 19:35 ` [PATCH 4/6][cr-test][v2]: Verify eclone() fails if clone_flags_high is non-zero Sukadev Bhattiprolu
2010-02-09 19:36 ` [PATCH 5/6][cr-test][v2]: eclone-5: nr_pids must not exceed nesting level Sukadev Bhattiprolu
[not found] ` <20100209193619.GD32274-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-02-09 21:17 ` Serge E. Hallyn
[not found] ` <20100209211705.GA32631-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-02-10 1:28 ` Sukadev Bhattiprolu
[not found] ` <20100210012831.GA20795-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-02-10 15:47 ` Serge E. Hallyn
2010-02-09 19:37 ` [PATCH 6/6][cr-test][v2]: eclone/runtests.sh: Wrapper script for eclone tests Sukadev Bhattiprolu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox