linux-ppp.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH] support no-mmu systems that lack fork()
@ 2010-07-24  1:03 sezginmurat
  0 siblings, 0 replies; 2+ messages in thread
From: sezginmurat @ 2010-07-24  1:03 UTC (permalink / raw)
  To: linux-ppp


Hi Mike,

For which version of ppp package did you do this patch? Is it for 2.4.4 or
it is for the mainline source?
I am using a ppp package (2.4.4) from uClinux distribution, but I just
wondered the difference of your patch.

Regards,
Murat





Mike Frysinger wrote:
> 
> Running Linux on a no-mmu processor requires a few considerations.  In the
> case of ppp, we cannot fork(), nor can the child return from the function
> it forks, nor can the child free up shared memory.
> 
> This patch boils down to:
>  - a new -DNOMMU flag
>  - do not free memory in child
>  - do not return from forked function ... pass in function and its
>    arguments for the child to call itself
>  - call _exit() rather than exit()
> 
> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
> ---
>  pppd/main.c |  110
> +++++++++++++++++++++++++++++++++++++++-------------------
>  pppd/tdb.c  |    4 ++
>  2 files changed, 78 insertions(+), 36 deletions(-)
> 
> diff --git a/pppd/main.c b/pppd/main.c
> index 4e1952b..565acb2 100644
> --- a/pppd/main.c
> +++ b/pppd/main.c
> @@ -1537,8 +1537,12 @@ bad_signal(sig)
>   * This also arranges for the specified fds to be dup'd to
>   * fds 0, 1, 2 in the child.
>   */
> +struct child_tail {
> +	void (*followup)(void *args);
> +	void *args;
> +};
>  pid_t
> -safe_fork(int infd, int outfd, int errfd)
> +safe_fork_tail(int infd, int outfd, int errfd, struct child_tail *tail)
>  {
>  	pid_t pid;
>  	int fd, pipefd[2];
> @@ -1554,7 +1558,11 @@ safe_fork(int infd, int outfd, int errfd)
>  
>  	if (pipe(pipefd) = -1)
>  		pipefd[0] = pipefd[1] = -1;
> +#ifdef NOMMU
> +	pid = vfork();
> +#else
>  	pid = fork();
> +#endif
>  	if (pid < 0) {
>  		error("fork failed: %m");
>  		return -1;
> @@ -1612,14 +1620,36 @@ safe_fork(int infd, int outfd, int errfd)
>  	/* this close unblocks the read() call above in the parent */
>  	close(pipefd[1]);
>  
> +	if (tail)
> +		tail->followup(tail->args);
>  	return 0;
>  }
> +pid_t
> +safe_fork(int infd, int outfd, int errfd)
> +{
> +	return safe_fork_tail(infd, outfd, errfd, NULL);
> +}
>  
>  /*
>   * device_script - run a program to talk to the specified fds
>   * (e.g. to run the connector or disconnector script).
>   * stderr gets connected to the log fd or to the _PATH_CONNERRS file.
>   */
> +void device_script_tail(void *args)
> +{
> +    char *program = args;
> +    /* here we are executing in the child */
> +
> +    setgid(getgid());
> +    setuid(uid);
> +    if (getuid() != uid) {
> +	fprintf(stderr, "pppd: setuid failed\n");
> +	_exit(1);
> +    }
> +    execl("/bin/sh", "sh", "-c", program, (char *)0);
> +    perror("pppd: could not exec /bin/sh");
> +    _exit(99);
> +}
>  int
>  device_script(program, in, out, dont_wait)
>      char *program;
> @@ -1629,6 +1659,7 @@ device_script(program, in, out, dont_wait)
>      int pid;
>      int status = -1;
>      int errfd;
> +    struct child_tail tail = { device_script_tail, program };
>  
>      if (log_to_fd >= 0)
>  	errfd = log_to_fd;
> @@ -1636,7 +1667,7 @@ device_script(program, in, out, dont_wait)
>  	errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0600);
>  
>      ++conn_running;
> -    pid = safe_fork(in, out, errfd);
> +    pid = safe_fork_tail(in, out, errfd, &tail);
>  
>      if (pid != 0 && log_to_fd < 0)
>  	close(errfd);
> @@ -1662,17 +1693,7 @@ device_script(program, in, out, dont_wait)
>  	return (status = 0 ? 0 : -1);
>      }
>  
> -    /* here we are executing in the child */
> -
> -    setgid(getgid());
> -    setuid(uid);
> -    if (getuid() != uid) {
> -	fprintf(stderr, "pppd: setuid failed\n");
> -	exit(1);
> -    }
> -    execl("/bin/sh", "sh", "-c", program, (char *)0);
> -    perror("pppd: could not exec /bin/sh");
> -    exit(99);
> +    _exit(99);
>      /* NOTREACHED */
>  }
>  
> @@ -1687,6 +1708,43 @@ device_script(program, in, out, dont_wait)
>   * If done != NULL, (*done)(arg) will be called later (within
>   * reap_kids) iff the return value is > 0.
>   */
> +struct run_program_args {
> +    char *prog;
> +    char **args;
> +    int must_exist;
> +};
> +void
> +run_program_tail(void *vargs)
> +{
> +    struct run_program_args *rpargs = vargs;
> +    char *prog = rpargs->prog;
> +    char **args = rpargs->args;
> +    int must_exist = rpargs->must_exist;
> +
> +    /* Leave the current location */
> +    (void) setsid();	/* No controlling tty. */
> +    (void) umask (S_IRWXG|S_IRWXO);
> +    (void) chdir ("/");	/* no current directory. */
> +    setuid(0);		/* set real UID = root */
> +    setgid(getegid());
> +
> +#ifdef BSD
> +    /* Force the priority back to zero if pppd is running higher. */
> +    if (setpriority (PRIO_PROCESS, 0, 0) < 0)
> +	warn("can't reset priority to 0: %m");
> +#endif
> +
> +    /* run the program */
> +    execve(prog, args, script_env);
> +    if (must_exist || errno != ENOENT) {
> +	/* have to reopen the log, there's nowhere else
> +	   for the message to go. */
> +	reopen_log();
> +	syslog(LOG_ERR, "Can't execute %s: %m", prog);
> +	closelog();
> +    }
> +    _exit(-1);
> +}
>  pid_t
>  run_program(prog, args, must_exist, done, arg, wait)
>      char *prog;
> @@ -1698,6 +1756,8 @@ run_program(prog, args, must_exist, done, arg, wait)
>  {
>      int pid, status;
>      struct stat sbuf;
> +    struct run_program_args vargs = { prog, args, must_exist };
> +    struct child_tail tail = { run_program_tail, &vargs };
>  
>      /*
>       * First check if the file exists and is executable.
> @@ -1713,7 +1773,7 @@ run_program(prog, args, must_exist, done, arg, wait)
>  	return 0;
>      }
>  
> -    pid = safe_fork(fd_devnull, fd_devnull, fd_devnull);
> +    pid = safe_fork_tail(fd_devnull, fd_devnull, fd_devnull, &tail);
>      if (pid = -1) {
>  	error("Failed to create child process for %s: %m", prog);
>  	return -1;
> @@ -1733,28 +1793,6 @@ run_program(prog, args, must_exist, done, arg,
> wait)
>  	return pid;
>      }
>  
> -    /* Leave the current location */
> -    (void) setsid();	/* No controlling tty. */
> -    (void) umask (S_IRWXG|S_IRWXO);
> -    (void) chdir ("/");	/* no current directory. */
> -    setuid(0);		/* set real UID = root */
> -    setgid(getegid());
> -
> -#ifdef BSD
> -    /* Force the priority back to zero if pppd is running higher. */
> -    if (setpriority (PRIO_PROCESS, 0, 0) < 0)
> -	warn("can't reset priority to 0: %m");
> -#endif
> -
> -    /* run the program */
> -    execve(prog, args, script_env);
> -    if (must_exist || errno != ENOENT) {
> -	/* have to reopen the log, there's nowhere else
> -	   for the message to go. */
> -	reopen_log();
> -	syslog(LOG_ERR, "Can't execute %s: %m", prog);
> -	closelog();
> -    }
>      _exit(-1);
>  }
>  
> diff --git a/pppd/tdb.c b/pppd/tdb.c
> index bdc5828..7ff431e 100644
> --- a/pppd/tdb.c
> +++ b/pppd/tdb.c
> @@ -1866,6 +1866,9 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int
> hash_size, int tdb_flags,
>   **/
>  int tdb_close(TDB_CONTEXT *tdb)
>  {
> +#ifdef NOMMU
> +	return close(tdb->fd);
> +#else
>  	TDB_CONTEXT **i;
>  	int ret = 0;
>  
> @@ -1892,6 +1895,7 @@ int tdb_close(TDB_CONTEXT *tdb)
>  	SAFE_FREE(tdb);
>  
>  	return ret;
> +#endif
>  }
>  
>  /* lock/unlock entire database */
> -- 
> 1.6.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-ppp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

-- 
View this message in context: http://old.nabble.com/-PATCH--support-no-mmu-systems-that-lack-fork%28%29-tp25012646p29252560.html
Sent from the linux-ppp mailing list archive at Nabble.com.


^ permalink raw reply	[flat|nested] 2+ messages in thread
* [PATCH] support no-mmu systems that lack fork()
@ 2009-08-17 19:23 Mike Frysinger
  0 siblings, 0 replies; 2+ messages in thread
From: Mike Frysinger @ 2009-08-17 19:23 UTC (permalink / raw)
  To: linux-ppp

Running Linux on a no-mmu processor requires a few considerations.  In the
case of ppp, we cannot fork(), nor can the child return from the function
it forks, nor can the child free up shared memory.

This patch boils down to:
 - a new -DNOMMU flag
 - do not free memory in child
 - do not return from forked function ... pass in function and its
   arguments for the child to call itself
 - call _exit() rather than exit()

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
---
 pppd/main.c |  110 +++++++++++++++++++++++++++++++++++++++-------------------
 pppd/tdb.c  |    4 ++
 2 files changed, 78 insertions(+), 36 deletions(-)

diff --git a/pppd/main.c b/pppd/main.c
index 4e1952b..565acb2 100644
--- a/pppd/main.c
+++ b/pppd/main.c
@@ -1537,8 +1537,12 @@ bad_signal(sig)
  * This also arranges for the specified fds to be dup'd to
  * fds 0, 1, 2 in the child.
  */
+struct child_tail {
+	void (*followup)(void *args);
+	void *args;
+};
 pid_t
-safe_fork(int infd, int outfd, int errfd)
+safe_fork_tail(int infd, int outfd, int errfd, struct child_tail *tail)
 {
 	pid_t pid;
 	int fd, pipefd[2];
@@ -1554,7 +1558,11 @@ safe_fork(int infd, int outfd, int errfd)
 
 	if (pipe(pipefd) = -1)
 		pipefd[0] = pipefd[1] = -1;
+#ifdef NOMMU
+	pid = vfork();
+#else
 	pid = fork();
+#endif
 	if (pid < 0) {
 		error("fork failed: %m");
 		return -1;
@@ -1612,14 +1620,36 @@ safe_fork(int infd, int outfd, int errfd)
 	/* this close unblocks the read() call above in the parent */
 	close(pipefd[1]);
 
+	if (tail)
+		tail->followup(tail->args);
 	return 0;
 }
+pid_t
+safe_fork(int infd, int outfd, int errfd)
+{
+	return safe_fork_tail(infd, outfd, errfd, NULL);
+}
 
 /*
  * device_script - run a program to talk to the specified fds
  * (e.g. to run the connector or disconnector script).
  * stderr gets connected to the log fd or to the _PATH_CONNERRS file.
  */
+void device_script_tail(void *args)
+{
+    char *program = args;
+    /* here we are executing in the child */
+
+    setgid(getgid());
+    setuid(uid);
+    if (getuid() != uid) {
+	fprintf(stderr, "pppd: setuid failed\n");
+	_exit(1);
+    }
+    execl("/bin/sh", "sh", "-c", program, (char *)0);
+    perror("pppd: could not exec /bin/sh");
+    _exit(99);
+}
 int
 device_script(program, in, out, dont_wait)
     char *program;
@@ -1629,6 +1659,7 @@ device_script(program, in, out, dont_wait)
     int pid;
     int status = -1;
     int errfd;
+    struct child_tail tail = { device_script_tail, program };
 
     if (log_to_fd >= 0)
 	errfd = log_to_fd;
@@ -1636,7 +1667,7 @@ device_script(program, in, out, dont_wait)
 	errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0600);
 
     ++conn_running;
-    pid = safe_fork(in, out, errfd);
+    pid = safe_fork_tail(in, out, errfd, &tail);
 
     if (pid != 0 && log_to_fd < 0)
 	close(errfd);
@@ -1662,17 +1693,7 @@ device_script(program, in, out, dont_wait)
 	return (status = 0 ? 0 : -1);
     }
 
-    /* here we are executing in the child */
-
-    setgid(getgid());
-    setuid(uid);
-    if (getuid() != uid) {
-	fprintf(stderr, "pppd: setuid failed\n");
-	exit(1);
-    }
-    execl("/bin/sh", "sh", "-c", program, (char *)0);
-    perror("pppd: could not exec /bin/sh");
-    exit(99);
+    _exit(99);
     /* NOTREACHED */
 }
 
@@ -1687,6 +1708,43 @@ device_script(program, in, out, dont_wait)
  * If done != NULL, (*done)(arg) will be called later (within
  * reap_kids) iff the return value is > 0.
  */
+struct run_program_args {
+    char *prog;
+    char **args;
+    int must_exist;
+};
+void
+run_program_tail(void *vargs)
+{
+    struct run_program_args *rpargs = vargs;
+    char *prog = rpargs->prog;
+    char **args = rpargs->args;
+    int must_exist = rpargs->must_exist;
+
+    /* Leave the current location */
+    (void) setsid();	/* No controlling tty. */
+    (void) umask (S_IRWXG|S_IRWXO);
+    (void) chdir ("/");	/* no current directory. */
+    setuid(0);		/* set real UID = root */
+    setgid(getegid());
+
+#ifdef BSD
+    /* Force the priority back to zero if pppd is running higher. */
+    if (setpriority (PRIO_PROCESS, 0, 0) < 0)
+	warn("can't reset priority to 0: %m");
+#endif
+
+    /* run the program */
+    execve(prog, args, script_env);
+    if (must_exist || errno != ENOENT) {
+	/* have to reopen the log, there's nowhere else
+	   for the message to go. */
+	reopen_log();
+	syslog(LOG_ERR, "Can't execute %s: %m", prog);
+	closelog();
+    }
+    _exit(-1);
+}
 pid_t
 run_program(prog, args, must_exist, done, arg, wait)
     char *prog;
@@ -1698,6 +1756,8 @@ run_program(prog, args, must_exist, done, arg, wait)
 {
     int pid, status;
     struct stat sbuf;
+    struct run_program_args vargs = { prog, args, must_exist };
+    struct child_tail tail = { run_program_tail, &vargs };
 
     /*
      * First check if the file exists and is executable.
@@ -1713,7 +1773,7 @@ run_program(prog, args, must_exist, done, arg, wait)
 	return 0;
     }
 
-    pid = safe_fork(fd_devnull, fd_devnull, fd_devnull);
+    pid = safe_fork_tail(fd_devnull, fd_devnull, fd_devnull, &tail);
     if (pid = -1) {
 	error("Failed to create child process for %s: %m", prog);
 	return -1;
@@ -1733,28 +1793,6 @@ run_program(prog, args, must_exist, done, arg, wait)
 	return pid;
     }
 
-    /* Leave the current location */
-    (void) setsid();	/* No controlling tty. */
-    (void) umask (S_IRWXG|S_IRWXO);
-    (void) chdir ("/");	/* no current directory. */
-    setuid(0);		/* set real UID = root */
-    setgid(getegid());
-
-#ifdef BSD
-    /* Force the priority back to zero if pppd is running higher. */
-    if (setpriority (PRIO_PROCESS, 0, 0) < 0)
-	warn("can't reset priority to 0: %m");
-#endif
-
-    /* run the program */
-    execve(prog, args, script_env);
-    if (must_exist || errno != ENOENT) {
-	/* have to reopen the log, there's nowhere else
-	   for the message to go. */
-	reopen_log();
-	syslog(LOG_ERR, "Can't execute %s: %m", prog);
-	closelog();
-    }
     _exit(-1);
 }
 
diff --git a/pppd/tdb.c b/pppd/tdb.c
index bdc5828..7ff431e 100644
--- a/pppd/tdb.c
+++ b/pppd/tdb.c
@@ -1866,6 +1866,9 @@ TDB_CONTEXT *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
  **/
 int tdb_close(TDB_CONTEXT *tdb)
 {
+#ifdef NOMMU
+	return close(tdb->fd);
+#else
 	TDB_CONTEXT **i;
 	int ret = 0;
 
@@ -1892,6 +1895,7 @@ int tdb_close(TDB_CONTEXT *tdb)
 	SAFE_FREE(tdb);
 
 	return ret;
+#endif
 }
 
 /* lock/unlock entire database */
-- 
1.6.4


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

end of thread, other threads:[~2010-07-24  1:03 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-24  1:03 [PATCH] support no-mmu systems that lack fork() sezginmurat
  -- strict thread matches above, loose matches on Subject: below --
2009-08-17 19:23 Mike Frysinger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).