Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 1 Nov 1998 23:12:38 -0500 (EST)
From:      Brian Feldman <green@zone.syracuse.net>
To:        current@FreeBSD.ORG
Subject:   Linux clone()
Message-ID:  <Pine.BSF.4.05.9811012304170.5699-100000@zone.syracuse.net>

next in thread | raw e-mail | index | archive | help
Okay, guys, I think I've gotten a linux clone() syscall implemented... As
of now, I have nothing to test it with :( The only thing I have to try it
with is MpegTV, and for some really crazy reason:
linux_clone()->(1569, 1570); child eip=0xf00, esp=0x80ed0b4
Now come on, passing 0xf00 as the void *fn (really int (*fn)(void *)) is
pretty damned bogus (but hey, it's not zero, so it turns into the child's
instruction pointer...) If anyone has any REALY examples of programs to
test with this, let me know.... This is a pretty important thing to have,
when lots more apps use linuxthreads (i.e. StarOffice 5.0). Oh, BTW,
someone tell me if this would be something really terrible to accidentally
do in kernel space:
printf("%d %d %#x %#x");
note no arguments... so far I don't notice any destabilization but I sure
hope I didn't fudge up the kernel stack!

Cheers,
Brian Feldman

---patch follows---
diff -ur /usr/src/sys/i386/linux/linux_dummy.c
usr/src/sys/i386/linux/linux_dummy.c
--- /usr/src/sys/i386/linux/linux_dummy.c	Thu Nov  6 14:28:52 1997
+++ usr/src/sys/i386/linux/linux_dummy.c	Sun Nov  1 17:07:31 1998
@@ -212,13 +212,6 @@
 }
 
 int
-linux_clone(struct proc *p, struct linux_clone_args *args)
-{
-    printf("Linux-emul(%d): clone() not supported\n", p->p_pid);
-    return ENOSYS;
-}
-
-int
 linux_uname(struct proc *p, struct linux_uname_args *args)
 {
     printf("Linux-emul(%d): uname() not supported\n", p->p_pid);
diff -ur /usr/src/sys/i386/linux/linux_misc.c
usr/src/sys/i386/linux/linux_misc.c
--- /usr/src/sys/i386/linux/linux_misc.c	Mon Oct  5 08:40:42 1998
+++ usr/src/sys/i386/linux/linux_misc.c	Sun Nov  1 23:06:00 1998
@@ -41,6 +41,7 @@
 #include <sys/resourcevar.h>
 #include <sys/stat.h>
 #include <sys/sysctl.h>
+#include <sys/unistd.h>
 #include <sys/vnode.h>
 #include <sys/wait.h>
 #include <sys/time.h>
@@ -557,6 +558,31 @@
 	return error;
     if (p->p_retval[1] == 1)
 	p->p_retval[0] = 0;
+    return 0;
+}
+
+int
+linux_clone(struct proc *p, struct linux_clone_args *args)
+{
+    int error;
+    struct proc *p2;
+
+    if (error = fork1(p, RFPROC | RFMEM))
+	return error;
+    p2 = pfind(p->p_retval[0]);
+    if (p2 == 0)
+	return ESRCH;
+    if (args->stack)
+	p2->p_md.md_regs->tf_esp = (int)args->stack;
+    if (args->fn) {
+	p2->p_md.md_regs->tf_eip = (int)args->fn;
+	copyout(&args->arg, (void *)p2->p_md.md_regs->tf_esp, sizeof(void
*));
+	p2->p_md.md_regs->tf_esp -= sizeof(void *);
+    }
+#ifdef DEBUG_CLONE
+    printf("linux_clone()->(%d, %d); child eip=%#x, esp=%#x\n", p->p_pid,
+	p2->p_pid, p2->p_md.md_regs->tf_eip, p2->p_md.md_regs->tf_esp);
+#endif
     return 0;
 }
 
diff -ur /usr/src/sys/i386/linux/linux_proto.h
usr/src/sys/i386/linux/linux_proto.h
--- /usr/src/sys/i386/linux/linux_proto.h	Fri Jul 10 18:30:04 1998
+++ usr/src/sys/i386/linux/linux_proto.h	Sun Nov  1 17:07:31 1998
@@ -2,7 +2,7 @@
  * System call prototypes.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * created from	Id: syscalls.master,v 1.11 1998/06/09 03:28:14 bde
Exp 
+ * created from	Id: syscalls.master,v 1.12 1998/07/10 22:30:08 jkh
Exp 
  */
 
 #ifndef _LINUX_SYSPROTO_H_
@@ -301,7 +301,10 @@
 	struct linux_sigcontext *	scp;	char scp_[PAD_(struct
linux_sigcontext *)];
 };
 struct	linux_clone_args {
-	register_t dummy;
+	void *	fn;	char fn_[PAD_(void *)];
+	void *	stack;	char stack_[PAD_(void *)];
+	int	flags;	char flags_[PAD_(int)];
+	void *	arg;	char arg_[PAD_(void *)];
 };
 struct	linux_newuname_args {
 	struct linux_newuname_t *	buf;	char buf_[PAD_(struct
linux_newuname_t *)];
Only in usr/src/sys/i386/linux/: linux_proto.h.bak
diff -ur /usr/src/sys/i386/linux/linux_syscall.h
usr/src/sys/i386/linux/linux_syscall.h
--- /usr/src/sys/i386/linux/linux_syscall.h	Fri Jul 10 18:30:06 1998
+++ usr/src/sys/i386/linux/linux_syscall.h	Sun Nov  1 17:07:31 1998
@@ -2,7 +2,7 @@
  * System call numbers.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * created from	Id: syscalls.master,v 1.11 1998/06/09 03:28:14 bde
Exp 
+ * created from	Id: syscalls.master,v 1.12 1998/07/10 22:30:08 jkh
Exp 
  */
 
 #define	LINUX_SYS_linux_setup	0
Only in usr/src/sys/i386/linux/: linux_syscall.h.bak
diff -ur /usr/src/sys/i386/linux/linux_sysent.c
usr/src/sys/i386/linux/linux_sysent.c
--- /usr/src/sys/i386/linux/linux_sysent.c	Fri Jul 10 18:30:07 1998
+++ usr/src/sys/i386/linux/linux_sysent.c	Sun Nov  1 17:07:31 1998
@@ -2,7 +2,7 @@
  * System call switch table.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * created from	Id: syscalls.master,v 1.11 1998/06/09 03:28:14 bde
Exp 
+ * created from	Id: syscalls.master,v 1.12 1998/07/10 22:30:08 jkh
Exp 
  */
 
 #include "opt_compat.h"
@@ -134,7 +134,7 @@
 	{ 5, (sy_call_t *)linux_ipc },			/* 117 = linux_ipc
*/
 	{ 1, (sy_call_t *)fsync },			/* 118 = fsync */
 	{ 1, (sy_call_t *)linux_sigreturn },		/* 119 =
linux_sigreturn */
-	{ 0, (sy_call_t *)linux_clone },		/* 120 =
linux_clone */
+	{ 4, (sy_call_t *)linux_clone },		/* 120 =
linux_clone */
 	{ 2, (sy_call_t *)setdomainname },		/* 121 =
setdomainname */
 	{ 1, (sy_call_t *)linux_newuname },		/* 122 =
linux_newuname */
 	{ 3, (sy_call_t *)linux_modify_ldt },		/* 123 =
linux_modify_ldt */
Only in usr/src/sys/i386/linux/: linux_sysent.c.bak
diff -ur /usr/src/sys/i386/linux/syscalls.master
usr/src/sys/i386/linux/syscalls.master
--- /usr/src/sys/i386/linux/syscalls.master	Fri Jul 10 18:30:08 1998
+++ usr/src/sys/i386/linux/syscalls.master	Sun Nov  1 17:07:31 1998
@@ -171,7 +171,8 @@
 			    caddr_t ptr); }
 118	NOPROTO	LINUX	{ int fsync(int fd); }
 119	STD	LINUX	{ int linux_sigreturn(struct linux_sigcontext
*scp); }
-120	STD	LINUX	{ int linux_clone(void); }
+120	STD	LINUX	{ int linux_clone(void *fn, void *stack,\
+			  int flags, void *arg); }
 121	NOPROTO	LINUX	{ int setdomainname(char *name, \
 			    int len); }
 122	STD	LINUX	{ int linux_newuname(struct linux_newuname_t
*buf); }



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.05.9811012304170.5699-100000>