Linux Container Development
 help / color / mirror / Atom feed
* [PATCH][cr-tests]: eclone-1: Test basic functionality
@ 2010-02-02 19:35 Sukadev Bhattiprolu
       [not found] ` <20100202193508.GA8542-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 11+ messages in thread
From: Sukadev Bhattiprolu @ 2010-02-02 19:35 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.

NOTE:	The myclone() function in eclone-lib.c supports just x86 for now.
	Needs to be ported to other architectures.

Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
 Makefile            |    2 +-
 eclone/Makefile     |   16 +++++++
 eclone/clone_args.h |   37 ++++++++++++++++
 eclone/eclone-1.c   |  121 +++++++++++++++++++++++++++++++++++++++++++++++++++
 eclone/eclone-lib.c |   85 ++++++++++++++++++++++++++++++++++++
 5 files changed, 260 insertions(+), 1 deletions(-)
 create mode 100644 eclone/Makefile
 create mode 100644 eclone/clone_args.h
 create mode 100644 eclone/eclone-1.c
 create mode 100644 eclone/eclone-lib.c

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..43cef65
--- /dev/null
+++ b/eclone/Makefile
@@ -0,0 +1,16 @@
+
+CFLAGS = -Wall
+
+LDFLAGS = 
+
+PROGS = eclone-1
+
+all: $(PROGS)
+
+eclone-lib.o: eclone-lib.c clone_args.h
+
+$(PROGS): %: %.c eclone-lib.o
+	$(CC) $(CFLAGS) -o $@ $< eclone-lib.o $(LDFLAGS)
+
+clean:
+	rm -f $(PROGS) eclone-lib.o
diff --git a/eclone/clone_args.h b/eclone/clone_args.h
new file mode 100644
index 0000000..393f139
--- /dev/null
+++ b/eclone/clone_args.h
@@ -0,0 +1,37 @@
+#include <errno.h>
+
+#define __NR_clone_with_pids 	337
+#define __NR_clone3		337
+#define __NR_eclone		337
+#define __NR_clone 		120
+#define __NR_exit 		1
+#define __NR_getpid 		20
+
+#define CLONE_NEWPID            0x20000000
+#define CLONE_CHILD_SETTID      0x01000000
+#define CLONE_PARENT_SETTID     0x00100000
+#define CLONE_UNUSED		0x00001000
+
+#define STACKSIZE	8192
+
+typedef unsigned long long u64;
+typedef unsigned int u32;
+typedef int pid_t;
+struct clone_args {
+        u64 clone_flags_high;
+
+        u64 child_stack_base;
+        u64 child_stack_size;
+
+        u64 parent_tid_ptr;
+        u64 child_tid_ptr;
+
+        u32 nr_pids;
+
+        u32 reserved0;
+};
+
+void *setup_stack(int (*child_fn)(void *), void *child_arg, int stack_size);
+int eclone(int flags_low, struct clone_args *clone_args, int args_size,
+		int *pids);
+int gettid();
diff --git a/eclone/eclone-1.c b/eclone/eclone-1.c
new file mode 100644
index 0000000..06a10f9
--- /dev/null
+++ b/eclone/eclone-1.c
@@ -0,0 +1,121 @@
+#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 "clone_args.h"
+
+int verbose = 0;
+int child_tid, parent_tid;
+
+#define CHILD_TID1	377
+#define	CHILD_TID2	399
+#define	CHILD_ARG	(void *)0x979797
+
+pid_t pids_list[] = { CHILD_TID1, CHILD_TID2 };
+
+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 myclone(int (*child_fn)(void *), void *child_arg, 
+		unsigned int flags_low, int nr_pids, pid_t *pids_list)
+{
+	int rc;
+	void *stack;
+	struct clone_args ca;
+	int args_size;
+
+	stack = setup_stack(child_fn, child_arg, STACKSIZE);
+	if (!stack) {
+		printf("ERROR: setup_stack returns NULL for size %d\n",
+				STACKSIZE);
+		exit(1);
+	}
+
+	memset(&ca, 0, sizeof(ca));
+	ca.child_stack_base = (u64)(int)stack;
+	ca.child_stack_size = (u64)0;
+	ca.parent_tid_ptr = (u64)((int)&parent_tid);
+	ca.child_tid_ptr = (u64)((int)&child_tid);
+	ca.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, ca.parent_tid_ptr, ca.child_tid_ptr,
+				pids_list);
+	}
+
+	args_size = sizeof(struct clone_args);
+	rc = eclone(flags_low, &ca, args_size, pids_list);
+
+	if (verbose) {
+		printf("[%d, %d]: eclone() returned %d, error %d\n", getpid(),
+				gettid(), rc, errno);
+		fflush(stdout);
+	}
+
+	if (rc < 0) {
+		printf("ERROR: ");
+		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 = myclone(do_child, (void *)CHILD_ARG, flags, nr_pids, pids_list);
+
+	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-lib.c b/eclone/eclone-lib.c
new file mode 100644
index 0000000..f547945
--- /dev/null
+++ b/eclone/eclone-lib.c
@@ -0,0 +1,85 @@
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include "clone_args.h"
+
+/* From Oren Laadan */
+
+#if defined(__i386__) && defined(__NR_eclone)
+/*
+ * libc doesn't support eclone() yet...
+ * (see: http://lkml.indiana.edu/hypermail/linux/kernel/9604.3/0204.html)
+ */
+
+int eclone(int flags_low, struct clone_args *clone_args, int args_size,
+		int *pids)
+{
+	long retval;
+
+	__asm__ __volatile__(
+		 "movl %3, %%ebx\n\t"	/* flags_low -> 1st (ebx)  */
+		 "movl %4, %%ecx\n\t"	/* clone_args -> 2nd (ecx) */
+		 "movl %5, %%edx\n\t"	/* args_size -> 3rd (edx) */
+		 "movl %6, %%esi\n\t"	/* pids -> 4th (esi) */
+
+		 "pushl %%ebp\n\t"	/* save value of ebp */
+		 "int $0x80\n\t"	/* Linux/i386 system call */
+		 "testl %0,%0\n\t"	/* check return value */
+		 "jne 1f\n\t"		/* jump if parent */
+		 "popl %%esi\n\t"	/* get subthread function */
+		 "call *%%esi\n\t"	/* start subthread function */
+		 "movl %2,%0\n\t"
+		 "int $0x80\n"		/* exit system call: exit subthread */
+		 "1:\n\t"
+		 "popl %%ebp\t"		/* restore parent's ebp */
+
+		:"=a" (retval)
+
+		:"0" (__NR_clone3),
+		 "i" (__NR_exit),
+		 "b" (flags_low),
+		 "c" (clone_args),
+		 "d" (args_size),
+		 "D" (pids)
+	);
+
+	if (retval < 0) {
+		errno = -retval;
+		retval = -1;
+	}
+	return retval;
+}
+
+void *setup_stack(int (*child_fn)(void *), void *child_arg, int size)
+{
+	void *stack_base;
+	void **stack_top;
+	
+	stack_base = malloc(size);
+	if (!stack_base)
+		return NULL;
+
+	stack_top = (void **)((char *)stack_base + (size - 4));
+	*--stack_top = child_arg;
+	*--stack_top = child_fn;
+
+	return stack_top;
+}
+
+#endif
+
+/* gettid() is a bit more useful than getpid() when messing with clone() */
+int gettid()
+{
+	int rc;
+
+	rc = syscall(__NR_gettid, 0, 0, 0);
+	if (rc < 0) {
+		printf("rc %d, errno %d\n", rc, errno);
+		exit(1);
+	}
+	return rc;
+}
-- 
1.6.6.1

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/6][cr-tests]: eclone-2: Fail if selected pid is in use
       [not found] ` <20100202193508.GA8542-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
@ 2010-02-02 19:37   ` Sukadev Bhattiprolu
       [not found]     ` <20100202193720.GA8793-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  2010-02-02 19:38   ` [PATCH 3/6][cr-tests]: eclone-3: Fail if reserved fields are not 0 Sukadev Bhattiprolu
                     ` (4 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Sukadev Bhattiprolu @ 2010-02-02 19:37 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: Fail if selected pid is in use

Ensure that eclone() system call fails with -EBUSY if selected pid is
in use.

Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
 eclone/Makefile   |    2 +-
 eclone/eclone-2.c |  117 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 118 insertions(+), 1 deletions(-)
 create mode 100644 eclone/eclone-2.c

diff --git a/eclone/Makefile b/eclone/Makefile
index 43cef65..95633d1 100644
--- a/eclone/Makefile
+++ b/eclone/Makefile
@@ -3,7 +3,7 @@ CFLAGS = -Wall
 
 LDFLAGS = 
 
-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..a52bb5e
--- /dev/null
+++ b/eclone/eclone-2.c
@@ -0,0 +1,117 @@
+#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 "clone_args.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_list[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 myclone(int (*child_fn)(void *), void *child_arg, 
+		unsigned int flags_low, int nr_pids, pid_t *pids_list)
+{
+	int rc;
+	void *stack;
+	struct clone_args ca;
+	int args_size;
+
+	stack = setup_stack(child_fn, child_arg, STACKSIZE);
+	if (!stack) {
+		printf("ERROR: setup_stack returns NULL for size %d\n",
+				STACKSIZE);
+		exit(1);
+	}
+
+	memset(&ca, 0, sizeof(ca));
+	ca.child_stack_base = (u64)(int)stack;
+	ca.child_stack_size = (u64)0;
+	ca.parent_tid_ptr = (u64)((int)&parent_tid);
+	ca.child_tid_ptr = (u64)((int)&child_tid);
+	ca.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, ca.parent_tid_ptr, ca.child_tid_ptr,
+				pids_list);
+	}
+
+	args_size = sizeof(struct clone_args);
+	rc = eclone(flags_low, &ca, args_size, pids_list);
+
+	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: ");
+		return rc;
+	}
+}
+
+int main()
+{
+	int rc, pid, status;
+	unsigned long flags; 
+	int nr_pids = 1;
+
+	flags = SIGCHLD|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID;
+	flags = SIGCHLD;
+
+	/*
+	 * Try to create a process with same pid as parent !
+	 */
+	pids_list[0] = pids_list[1] = getpid();
+
+	pid = myclone(do_child, (void *)CHILD_ARG, flags, nr_pids, pids_list);
+
+	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] 11+ messages in thread

* [PATCH 3/6][cr-tests]: eclone-3: Fail if reserved fields are not 0
       [not found] ` <20100202193508.GA8542-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  2010-02-02 19:37   ` [PATCH 2/6][cr-tests]: eclone-2: Fail if selected pid is in use Sukadev Bhattiprolu
@ 2010-02-02 19:38   ` Sukadev Bhattiprolu
       [not found]     ` <20100202193822.GB8793-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  2010-02-02 19:39   ` [PATCH 4/6][cr-tests]: eclone-4: Fail if clone_flags_high is non-zero Sukadev Bhattiprolu
                     ` (3 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Sukadev Bhattiprolu @ 2010-02-02 19:38 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][cr-tests]: eclone-3: Fail 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.

Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
 eclone/Makefile   |    2 +-
 eclone/eclone-3.c |  117 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 118 insertions(+), 1 deletions(-)
 create mode 100644 eclone/eclone-3.c

diff --git a/eclone/Makefile b/eclone/Makefile
index 95633d1..ebe508d 100644
--- a/eclone/Makefile
+++ b/eclone/Makefile
@@ -3,7 +3,7 @@ CFLAGS = -Wall
 
 LDFLAGS = 
 
-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..5a972ce
--- /dev/null
+++ b/eclone/eclone-3.c
@@ -0,0 +1,117 @@
+#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 "clone_args.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_TID2	399
+#define	CHILD_ARG	(void *)0x979797
+
+pid_t pids_list[] = { CHILD_TID1, CHILD_TID2 };
+
+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 myclone(int (*child_fn)(void *), void *child_arg, 
+		unsigned int flags_low, int nr_pids, pid_t *pids_list)
+{
+	int rc;
+	void *stack;
+	struct clone_args ca;
+	int args_size;
+
+	stack = setup_stack(child_fn, child_arg, STACKSIZE);
+	if (!stack) {
+		printf("ERROR: setup_stack returns NULL for size %d\n",
+				STACKSIZE);
+		exit(1);
+	}
+
+	memset(&ca, 0, sizeof(ca));
+	ca.child_stack_base = (u64)(int)stack;
+	ca.child_stack_size = (u64)0;
+	ca.parent_tid_ptr = (u64)((int)&parent_tid);
+	ca.child_tid_ptr = (u64)((int)&child_tid);
+	ca.reserved0 = 0xdeadbeef;
+	ca.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, ca.parent_tid_ptr, ca.child_tid_ptr,
+				pids_list);
+	}
+
+	args_size = sizeof(struct clone_args);
+	rc = eclone(flags_low, &ca, args_size, pids_list);
+
+	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|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID;
+	flags = SIGCHLD;
+
+	pid = myclone(do_child, (void *)CHILD_ARG, flags, nr_pids, pids_list);
+
+	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] 11+ messages in thread

* [PATCH 4/6][cr-tests]: eclone-4: Fail if clone_flags_high is non-zero
       [not found] ` <20100202193508.GA8542-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  2010-02-02 19:37   ` [PATCH 2/6][cr-tests]: eclone-2: Fail if selected pid is in use Sukadev Bhattiprolu
  2010-02-02 19:38   ` [PATCH 3/6][cr-tests]: eclone-3: Fail if reserved fields are not 0 Sukadev Bhattiprolu
@ 2010-02-02 19:39   ` Sukadev Bhattiprolu
       [not found]     ` <20100202193931.GC8793-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  2010-02-02 19:41   ` [PATCH 5/6][cr-tests]: eclone-5: nr_pids must not exceed nesting level Sukadev Bhattiprolu
                     ` (2 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Sukadev Bhattiprolu @ 2010-02-02 19:39 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][cr-tests]: eclone-4: Fail 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.

Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
 eclone/Makefile   |    2 +-
 eclone/eclone-4.c |  116 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+), 1 deletions(-)
 create mode 100644 eclone/eclone-4.c

diff --git a/eclone/Makefile b/eclone/Makefile
index ebe508d..86ca859 100644
--- a/eclone/Makefile
+++ b/eclone/Makefile
@@ -3,7 +3,7 @@ CFLAGS = -Wall
 
 LDFLAGS = 
 
-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..33a28ef
--- /dev/null
+++ b/eclone/eclone-4.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 "clone_args.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_TID2	399
+#define	CHILD_ARG	(void *)0x979797
+
+pid_t pids_list[] = { CHILD_TID1, CHILD_TID2 };
+
+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 myclone(int (*child_fn)(void *), void *child_arg, 
+		unsigned int flags_low, int nr_pids, pid_t *pids_list)
+{
+	int rc;
+	void *stack;
+	struct clone_args ca;
+	int args_size;
+
+	stack = setup_stack(child_fn, child_arg, STACKSIZE);
+	if (!stack) {
+		printf("ERROR: setup_stack returns NULL for size %d\n",
+				STACKSIZE);
+		exit(1);
+	}
+
+	memset(&ca, 0, sizeof(ca));
+	ca.clone_flags_high = (u64)1 << 33;
+	ca.child_stack_base = (u64)(int)stack;
+	ca.child_stack_size = (u64)0;
+	ca.parent_tid_ptr = (u64)((int)&parent_tid);
+	ca.child_tid_ptr = (u64)((int)&child_tid);
+	ca.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, ca.parent_tid_ptr, ca.child_tid_ptr,
+				pids_list);
+	}
+
+	args_size = sizeof(struct clone_args);
+	rc = eclone(flags_low, &ca, args_size, pids_list);
+
+	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|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID;
+	flags = SIGCHLD;
+
+	pid = myclone(do_child, (void *)CHILD_ARG, flags, nr_pids, pids_list);
+
+	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] 11+ messages in thread

* [PATCH 5/6][cr-tests]: eclone-5: nr_pids must not exceed nesting level
       [not found] ` <20100202193508.GA8542-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (2 preceding siblings ...)
  2010-02-02 19:39   ` [PATCH 4/6][cr-tests]: eclone-4: Fail if clone_flags_high is non-zero Sukadev Bhattiprolu
@ 2010-02-02 19:41   ` Sukadev Bhattiprolu
       [not found]     ` <20100202194106.GD8793-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
  2010-02-02 19:43   ` [PATCH 6/6][cr-tests]: eclone/runtests.sh: Wrapper script for eclone tests Sukadev Bhattiprolu
  2010-02-02 20:07   ` [PATCH][cr-tests]: eclone-1: Test basic functionality Serge E. Hallyn
  5 siblings, 1 reply; 11+ messages in thread
From: Sukadev Bhattiprolu @ 2010-02-02 19:41 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][cr-tests]: 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.

Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
---
 eclone/Makefile   |    2 +-
 eclone/eclone-5.c |  174 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 175 insertions(+), 1 deletions(-)
 create mode 100644 eclone/eclone-5.c

diff --git a/eclone/Makefile b/eclone/Makefile
index 86ca859..5777643 100644
--- a/eclone/Makefile
+++ b/eclone/Makefile
@@ -3,7 +3,7 @@ CFLAGS = -Wall
 
 LDFLAGS = 
 
-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..ceaef02
--- /dev/null
+++ b/eclone/eclone-5.c
@@ -0,0 +1,174 @@
+#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 "clone_args.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_list[] = { 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 myclone(int (*child_fn)(void *), void *child_arg, 
+		unsigned int flags_low, int nr_pids, pid_t *pids_list)
+{
+	int rc;
+	void *stack;
+	struct clone_args ca;
+	int args_size;
+
+	stack = setup_stack(child_fn, child_arg, STACKSIZE);
+	if (!stack) {
+		printf("ERROR: setup_stack returns NULL for size %d\n",
+				STACKSIZE);
+		exit(1);
+	}
+
+	memset(&ca, 0, sizeof(ca));
+	ca.child_stack_base = (u64)(int)stack;
+	ca.child_stack_size = (u64)0;
+	ca.parent_tid_ptr = (u64)((int)&parent_tid);
+	ca.child_tid_ptr = (u64)((int)&child_tid);
+	ca.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, ca.parent_tid_ptr, ca.child_tid_ptr,
+				pids_list);
+	}
+
+	errno = 0;
+	args_size = sizeof(struct clone_args);
+	rc = eclone(flags_low, &ca, args_size, pids_list);
+
+	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 = myclone(do_child, (void *)CHILD_ARG, flags, nr_pids, pids_list);
+
+	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\n",
+				getpid());
+	} 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] 11+ messages in thread

* [PATCH 6/6][cr-tests]: eclone/runtests.sh: Wrapper script for eclone tests
       [not found] ` <20100202193508.GA8542-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (3 preceding siblings ...)
  2010-02-02 19:41   ` [PATCH 5/6][cr-tests]: eclone-5: nr_pids must not exceed nesting level Sukadev Bhattiprolu
@ 2010-02-02 19:43   ` Sukadev Bhattiprolu
  2010-02-02 20:07   ` [PATCH][cr-tests]: eclone-1: Test basic functionality Serge E. Hallyn
  5 siblings, 0 replies; 11+ messages in thread
From: Sukadev Bhattiprolu @ 2010-02-02 19:43 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][cr-tests]: 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] 11+ messages in thread

* Re: [PATCH][cr-tests]: eclone-1: Test basic functionality
       [not found] ` <20100202193508.GA8542-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
                     ` (4 preceding siblings ...)
  2010-02-02 19:43   ` [PATCH 6/6][cr-tests]: eclone/runtests.sh: Wrapper script for eclone tests Sukadev Bhattiprolu
@ 2010-02-02 20:07   ` Serge E. Hallyn
  5 siblings, 0 replies; 11+ messages in thread
From: Serge E. Hallyn @ 2010-02-02 20:07 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: 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.
> 
> NOTE:	The myclone() function in eclone-lib.c supports just x86 for now.
> 	Needs to be ported to other architectures.

Thanks, but

I'd prefer to see a libeclone patch for user-cr, and cr_tests programs
compiled against that.  user-cr already has done the ugliness required
to do eclone per-arch right now.

Would it be a lot of work to do so?  (I shouldn't think so)

thanks,
-serge

> Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
> ---
>  Makefile            |    2 +-
>  eclone/Makefile     |   16 +++++++
>  eclone/clone_args.h |   37 ++++++++++++++++
>  eclone/eclone-1.c   |  121 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  eclone/eclone-lib.c |   85 ++++++++++++++++++++++++++++++++++++
>  5 files changed, 260 insertions(+), 1 deletions(-)
>  create mode 100644 eclone/Makefile
>  create mode 100644 eclone/clone_args.h
>  create mode 100644 eclone/eclone-1.c
>  create mode 100644 eclone/eclone-lib.c
> 
> 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..43cef65
> --- /dev/null
> +++ b/eclone/Makefile
> @@ -0,0 +1,16 @@
> +
> +CFLAGS = -Wall
> +
> +LDFLAGS = 
> +
> +PROGS = eclone-1
> +
> +all: $(PROGS)
> +
> +eclone-lib.o: eclone-lib.c clone_args.h
> +
> +$(PROGS): %: %.c eclone-lib.o
> +	$(CC) $(CFLAGS) -o $@ $< eclone-lib.o $(LDFLAGS)
> +
> +clean:
> +	rm -f $(PROGS) eclone-lib.o
> diff --git a/eclone/clone_args.h b/eclone/clone_args.h
> new file mode 100644
> index 0000000..393f139
> --- /dev/null
> +++ b/eclone/clone_args.h
> @@ -0,0 +1,37 @@
> +#include <errno.h>
> +
> +#define __NR_clone_with_pids 	337
> +#define __NR_clone3		337
> +#define __NR_eclone		337
> +#define __NR_clone 		120
> +#define __NR_exit 		1
> +#define __NR_getpid 		20
> +
> +#define CLONE_NEWPID            0x20000000
> +#define CLONE_CHILD_SETTID      0x01000000
> +#define CLONE_PARENT_SETTID     0x00100000
> +#define CLONE_UNUSED		0x00001000
> +
> +#define STACKSIZE	8192
> +
> +typedef unsigned long long u64;
> +typedef unsigned int u32;
> +typedef int pid_t;
> +struct clone_args {
> +        u64 clone_flags_high;
> +
> +        u64 child_stack_base;
> +        u64 child_stack_size;
> +
> +        u64 parent_tid_ptr;
> +        u64 child_tid_ptr;
> +
> +        u32 nr_pids;
> +
> +        u32 reserved0;
> +};
> +
> +void *setup_stack(int (*child_fn)(void *), void *child_arg, int stack_size);
> +int eclone(int flags_low, struct clone_args *clone_args, int args_size,
> +		int *pids);
> +int gettid();
> diff --git a/eclone/eclone-1.c b/eclone/eclone-1.c
> new file mode 100644
> index 0000000..06a10f9
> --- /dev/null
> +++ b/eclone/eclone-1.c
> @@ -0,0 +1,121 @@
> +#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 "clone_args.h"
> +
> +int verbose = 0;
> +int child_tid, parent_tid;
> +
> +#define CHILD_TID1	377
> +#define	CHILD_TID2	399
> +#define	CHILD_ARG	(void *)0x979797
> +
> +pid_t pids_list[] = { CHILD_TID1, CHILD_TID2 };
> +
> +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 myclone(int (*child_fn)(void *), void *child_arg, 
> +		unsigned int flags_low, int nr_pids, pid_t *pids_list)
> +{
> +	int rc;
> +	void *stack;
> +	struct clone_args ca;
> +	int args_size;
> +
> +	stack = setup_stack(child_fn, child_arg, STACKSIZE);
> +	if (!stack) {
> +		printf("ERROR: setup_stack returns NULL for size %d\n",
> +				STACKSIZE);
> +		exit(1);
> +	}
> +
> +	memset(&ca, 0, sizeof(ca));
> +	ca.child_stack_base = (u64)(int)stack;
> +	ca.child_stack_size = (u64)0;
> +	ca.parent_tid_ptr = (u64)((int)&parent_tid);
> +	ca.child_tid_ptr = (u64)((int)&child_tid);
> +	ca.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, ca.parent_tid_ptr, ca.child_tid_ptr,
> +				pids_list);
> +	}
> +
> +	args_size = sizeof(struct clone_args);
> +	rc = eclone(flags_low, &ca, args_size, pids_list);
> +
> +	if (verbose) {
> +		printf("[%d, %d]: eclone() returned %d, error %d\n", getpid(),
> +				gettid(), rc, errno);
> +		fflush(stdout);
> +	}
> +
> +	if (rc < 0) {
> +		printf("ERROR: ");
> +		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 = myclone(do_child, (void *)CHILD_ARG, flags, nr_pids, pids_list);
> +
> +	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-lib.c b/eclone/eclone-lib.c
> new file mode 100644
> index 0000000..f547945
> --- /dev/null
> +++ b/eclone/eclone-lib.c
> @@ -0,0 +1,85 @@
> +#define _GNU_SOURCE
> +#include <stdio.h>
> +#include <errno.h>
> +#include <stdlib.h>
> +#include <unistd.h>
> +#include <sys/syscall.h>
> +#include "clone_args.h"
> +
> +/* From Oren Laadan */
> +
> +#if defined(__i386__) && defined(__NR_eclone)
> +/*
> + * libc doesn't support eclone() yet...
> + * (see: http://lkml.indiana.edu/hypermail/linux/kernel/9604.3/0204.html)
> + */
> +
> +int eclone(int flags_low, struct clone_args *clone_args, int args_size,
> +		int *pids)
> +{
> +	long retval;
> +
> +	__asm__ __volatile__(
> +		 "movl %3, %%ebx\n\t"	/* flags_low -> 1st (ebx)  */
> +		 "movl %4, %%ecx\n\t"	/* clone_args -> 2nd (ecx) */
> +		 "movl %5, %%edx\n\t"	/* args_size -> 3rd (edx) */
> +		 "movl %6, %%esi\n\t"	/* pids -> 4th (esi) */
> +
> +		 "pushl %%ebp\n\t"	/* save value of ebp */
> +		 "int $0x80\n\t"	/* Linux/i386 system call */
> +		 "testl %0,%0\n\t"	/* check return value */
> +		 "jne 1f\n\t"		/* jump if parent */
> +		 "popl %%esi\n\t"	/* get subthread function */
> +		 "call *%%esi\n\t"	/* start subthread function */
> +		 "movl %2,%0\n\t"
> +		 "int $0x80\n"		/* exit system call: exit subthread */
> +		 "1:\n\t"
> +		 "popl %%ebp\t"		/* restore parent's ebp */
> +
> +		:"=a" (retval)
> +
> +		:"0" (__NR_clone3),
> +		 "i" (__NR_exit),
> +		 "b" (flags_low),
> +		 "c" (clone_args),
> +		 "d" (args_size),
> +		 "D" (pids)
> +	);
> +
> +	if (retval < 0) {
> +		errno = -retval;
> +		retval = -1;
> +	}
> +	return retval;
> +}
> +
> +void *setup_stack(int (*child_fn)(void *), void *child_arg, int size)
> +{
> +	void *stack_base;
> +	void **stack_top;
> +	
> +	stack_base = malloc(size);
> +	if (!stack_base)
> +		return NULL;
> +
> +	stack_top = (void **)((char *)stack_base + (size - 4));
> +	*--stack_top = child_arg;
> +	*--stack_top = child_fn;
> +
> +	return stack_top;
> +}
> +
> +#endif
> +
> +/* gettid() is a bit more useful than getpid() when messing with clone() */
> +int gettid()
> +{
> +	int rc;
> +
> +	rc = syscall(__NR_gettid, 0, 0, 0);
> +	if (rc < 0) {
> +		printf("rc %d, errno %d\n", rc, errno);
> +		exit(1);
> +	}
> +	return rc;
> +}
> -- 
> 1.6.6.1

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/6][cr-tests]: eclone-2: Fail if selected pid is in use
       [not found]     ` <20100202193720.GA8793-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
@ 2010-02-02 20:20       ` Serge E. Hallyn
  0 siblings, 0 replies; 11+ messages in thread
From: Serge E. Hallyn @ 2010-02-02 20:20 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: Sat, 30 Jan 2010 12:51:23 -0800
> Subject: [PATCH 2/6]: eclone-2: Fail if selected pid is in use
> 
> Ensure that eclone() system call fails with -EBUSY if selected pid is
> in use.
> 
> Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>
> ---
>  eclone/Makefile   |    2 +-
>  eclone/eclone-2.c |  117 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 118 insertions(+), 1 deletions(-)
>  create mode 100644 eclone/eclone-2.c
> 
> diff --git a/eclone/Makefile b/eclone/Makefile
> index 43cef65..95633d1 100644
> --- a/eclone/Makefile
> +++ b/eclone/Makefile
> @@ -3,7 +3,7 @@ CFLAGS = -Wall
> 
>  LDFLAGS = 
> 
> -PROGS = eclone-1
> +PROGS = eclone-1 eclone-2

Just a few nits.  I don't see any real problems with this, but like
I said I'd like the whole set re-sent along with a user-cr patch to
make a libeclone.a or .so that these tests can link against.

>  all: $(PROGS)
> 
> diff --git a/eclone/eclone-2.c b/eclone/eclone-2.c
> new file mode 100644
> index 0000000..a52bb5e
> --- /dev/null
> +++ b/eclone/eclone-2.c
> @@ -0,0 +1,117 @@
> +#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 "clone_args.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_list[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 myclone(int (*child_fn)(void *), void *child_arg, 
> +		unsigned int flags_low, int nr_pids, pid_t *pids_list)
> +{
> +	int rc;
> +	void *stack;
> +	struct clone_args ca;
> +	int args_size;
> +
> +	stack = setup_stack(child_fn, child_arg, STACKSIZE);
> +	if (!stack) {
> +		printf("ERROR: setup_stack returns NULL for size %d\n",
> +				STACKSIZE);
> +		exit(1);
> +	}
> +
> +	memset(&ca, 0, sizeof(ca));
> +	ca.child_stack_base = (u64)(int)stack;
> +	ca.child_stack_size = (u64)0;
> +	ca.parent_tid_ptr = (u64)((int)&parent_tid);
> +	ca.child_tid_ptr = (u64)((int)&child_tid);
> +	ca.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, ca.parent_tid_ptr, ca.child_tid_ptr,
> +				pids_list);
> +	}
> +
> +	args_size = sizeof(struct clone_args);
> +	rc = eclone(flags_low, &ca, args_size, pids_list);
> +
> +	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: ");
> +		return rc;
> +	}
> +}
> +
> +int main()
> +{
> +	int rc, pid, status;
> +	unsigned long flags; 
> +	int nr_pids = 1;
> +
> +	flags = SIGCHLD|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID;
> +	flags = SIGCHLD;

Did you want to delete that first line?

> +
> +	/*
> +	 * Try to create a process with same pid as parent !
> +	 */
> +	pids_list[0] = pids_list[1] = getpid();

Any reason you're setting pids_list[1]?  Shouldn't be used, right?

> +	pid = myclone(do_child, (void *)CHILD_ARG, flags, nr_pids, pids_list);

CHILD_ARG is already cast btw

> +
> +	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	[flat|nested] 11+ messages in thread

* Re: [PATCH 4/6][cr-tests]: eclone-4: Fail if clone_flags_high is non-zero
       [not found]     ` <20100202193931.GC8793-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
@ 2010-02-02 21:05       ` Serge E. Hallyn
  0 siblings, 0 replies; 11+ messages in thread
From: Serge E. Hallyn @ 2010-02-02 21:05 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:10:32 -0800
> Subject: [PATCH 4/6][cr-tests]: eclone-4: Fail 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.
> 
> Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>

> +	ca.clone_flags_high = (u64)1 << 33;

So have you tested this on x86-32?  does it pass?

-serge

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 5/6][cr-tests]: eclone-5: nr_pids must not exceed nesting level
       [not found]     ` <20100202194106.GD8793-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
@ 2010-02-02 21:09       ` Serge E. Hallyn
  0 siblings, 0 replies; 11+ messages in thread
From: Serge E. Hallyn @ 2010-02-02 21:09 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][cr-tests]: 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.
> 
> Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>

Acked-by: Serge Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

> ---
>  eclone/Makefile   |    2 +-
>  eclone/eclone-5.c |  174 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 175 insertions(+), 1 deletions(-)
>  create mode 100644 eclone/eclone-5.c
> 
> diff --git a/eclone/Makefile b/eclone/Makefile
> index 86ca859..5777643 100644
> --- a/eclone/Makefile
> +++ b/eclone/Makefile
> @@ -3,7 +3,7 @@ CFLAGS = -Wall
> 
>  LDFLAGS = 
> 
> -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..ceaef02
> --- /dev/null
> +++ b/eclone/eclone-5.c
> @@ -0,0 +1,174 @@
> +#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 "clone_args.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_list[] = { 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 myclone(int (*child_fn)(void *), void *child_arg, 
> +		unsigned int flags_low, int nr_pids, pid_t *pids_list)
> +{
> +	int rc;
> +	void *stack;
> +	struct clone_args ca;
> +	int args_size;
> +
> +	stack = setup_stack(child_fn, child_arg, STACKSIZE);
> +	if (!stack) {
> +		printf("ERROR: setup_stack returns NULL for size %d\n",
> +				STACKSIZE);
> +		exit(1);
> +	}
> +
> +	memset(&ca, 0, sizeof(ca));
> +	ca.child_stack_base = (u64)(int)stack;
> +	ca.child_stack_size = (u64)0;
> +	ca.parent_tid_ptr = (u64)((int)&parent_tid);
> +	ca.child_tid_ptr = (u64)((int)&child_tid);
> +	ca.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, ca.parent_tid_ptr, ca.child_tid_ptr,
> +				pids_list);
> +	}
> +
> +	errno = 0;
> +	args_size = sizeof(struct clone_args);
> +	rc = eclone(flags_low, &ca, args_size, pids_list);
> +
> +	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 = myclone(do_child, (void *)CHILD_ARG, flags, nr_pids, pids_list);
> +
> +	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\n",
> +				getpid());
> +	} 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	[flat|nested] 11+ messages in thread

* Re: [PATCH 3/6][cr-tests]: eclone-3: Fail if reserved fields are not 0
       [not found]     ` <20100202193822.GB8793-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
@ 2010-02-02 21:09       ` Serge E. Hallyn
  0 siblings, 0 replies; 11+ messages in thread
From: Serge E. Hallyn @ 2010-02-02 21:09 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: Sat, 30 Jan 2010 12:53:04 -0800
> Subject: [PATCH 3/6][cr-tests]: eclone-3: Fail 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.
> 
> Signed-off-by: Sukadev Bhattiprolu <sukadev-23VcF4HTsmIX0ybBhKVfKdBPR1lH4CV8@public.gmane.org>

Acked-by: Serge Hallyn <serue-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>

> ---
>  eclone/Makefile   |    2 +-
>  eclone/eclone-3.c |  117 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 118 insertions(+), 1 deletions(-)
>  create mode 100644 eclone/eclone-3.c
> 
> diff --git a/eclone/Makefile b/eclone/Makefile
> index 95633d1..ebe508d 100644
> --- a/eclone/Makefile
> +++ b/eclone/Makefile
> @@ -3,7 +3,7 @@ CFLAGS = -Wall
> 
>  LDFLAGS = 
> 
> -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..5a972ce
> --- /dev/null
> +++ b/eclone/eclone-3.c
> @@ -0,0 +1,117 @@
> +#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 "clone_args.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_TID2	399
> +#define	CHILD_ARG	(void *)0x979797
> +
> +pid_t pids_list[] = { CHILD_TID1, CHILD_TID2 };
> +
> +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 myclone(int (*child_fn)(void *), void *child_arg, 
> +		unsigned int flags_low, int nr_pids, pid_t *pids_list)
> +{
> +	int rc;
> +	void *stack;
> +	struct clone_args ca;
> +	int args_size;
> +
> +	stack = setup_stack(child_fn, child_arg, STACKSIZE);
> +	if (!stack) {
> +		printf("ERROR: setup_stack returns NULL for size %d\n",
> +				STACKSIZE);
> +		exit(1);
> +	}
> +
> +	memset(&ca, 0, sizeof(ca));
> +	ca.child_stack_base = (u64)(int)stack;
> +	ca.child_stack_size = (u64)0;
> +	ca.parent_tid_ptr = (u64)((int)&parent_tid);
> +	ca.child_tid_ptr = (u64)((int)&child_tid);
> +	ca.reserved0 = 0xdeadbeef;
> +	ca.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, ca.parent_tid_ptr, ca.child_tid_ptr,
> +				pids_list);
> +	}
> +
> +	args_size = sizeof(struct clone_args);
> +	rc = eclone(flags_low, &ca, args_size, pids_list);
> +
> +	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|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID;
> +	flags = SIGCHLD;
> +
> +	pid = myclone(do_child, (void *)CHILD_ARG, flags, nr_pids, pids_list);
> +
> +	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	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2010-02-02 21:09 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-02-02 19:35 [PATCH][cr-tests]: eclone-1: Test basic functionality Sukadev Bhattiprolu
     [not found] ` <20100202193508.GA8542-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-02-02 19:37   ` [PATCH 2/6][cr-tests]: eclone-2: Fail if selected pid is in use Sukadev Bhattiprolu
     [not found]     ` <20100202193720.GA8793-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-02-02 20:20       ` Serge E. Hallyn
2010-02-02 19:38   ` [PATCH 3/6][cr-tests]: eclone-3: Fail if reserved fields are not 0 Sukadev Bhattiprolu
     [not found]     ` <20100202193822.GB8793-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-02-02 21:09       ` Serge E. Hallyn
2010-02-02 19:39   ` [PATCH 4/6][cr-tests]: eclone-4: Fail if clone_flags_high is non-zero Sukadev Bhattiprolu
     [not found]     ` <20100202193931.GC8793-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-02-02 21:05       ` Serge E. Hallyn
2010-02-02 19:41   ` [PATCH 5/6][cr-tests]: eclone-5: nr_pids must not exceed nesting level Sukadev Bhattiprolu
     [not found]     ` <20100202194106.GD8793-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2010-02-02 21:09       ` Serge E. Hallyn
2010-02-02 19:43   ` [PATCH 6/6][cr-tests]: eclone/runtests.sh: Wrapper script for eclone tests Sukadev Bhattiprolu
2010-02-02 20:07   ` [PATCH][cr-tests]: eclone-1: Test basic functionality Serge E. Hallyn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox