* strace.c (USE_VFORK): New macro, use instead of strace_vforked.
* strace.c (USE_VFORK): Check for uClinux flavours with stub fork
which returns ENOSYS, is found by ./configure, but can't be used.
* strace.c (strace_vforked): Removed.
* strace.c (main): Change strace_vforked reference to USE_VFORK.
It's a bit uglier but as this was the only place where strace_vforked
was notably prettier I decided to remove it.

* strace.c (startup_child): Change error message to say vfork
failed, not fork.
* strace.c (startup_child): Don't call initgroups in a vfork child.
We have to make do without supplementary groups.

* strace.c (daemonized_tracer): Make this constant 0 when using
vfork, and remove it from the options processing and help text.
This makes the help text depend on C89 string concatenation, but
as we dropped non-C89 support some time ago, this should be ok.

Signed-off-by: Jamie Lokier <ja...@shareable.org>
---
 strace.c |   75 ++++++++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 54 insertions(+), 21 deletions(-)

diff --git a/strace.c b/strace.c
index 8b7434f..5b44f1c 100644
--- a/strace.c
+++ b/strace.c
@@ -86,6 +86,21 @@ int debug = 0, followfork = 0;
 int dtime = 0, xflag = 0, qflag = 0;
 cflag_t cflag = CFLAG_NONE;
 static int iflag = 0, interactive = 0, pflag_seen = 0, rflag = 0, tflag = 0;
+
+/* Glue for systems without a MMU that cannot provide fork() */
+#ifdef LINUX
+/* Some uClinux versions have fork() as a stub returning ENOSYS. */
+# if defined __UCLIBC__
+#  if !defined __UCLIBC_HAS_MMU__ && !defined __ARCH_HAS_MMU__
+#   undef HAVE_FORK
+#  endif
+# endif
+#endif
+#ifndef HAVE_FORK
+# define USE_VFORK
+# define fork()         vfork()
+#endif
+
 /*
  * daemonized_tracer supports -D option.
  * With this option, strace forks twice.
@@ -98,7 +113,11 @@ static int iflag = 0, interactive = 0, pflag_seen = 0, 
rflag = 0, tflag = 0;
  * wait() etc. Without -D, strace process gets lodged in between,
  * disrupting parent<->child link.
  */
+#ifndef USE_VFORK /* Does not work with vfork. */
 static bool daemonized_tracer = 0;
+#else
+# define daemonized_tracer 0
+#endif
 
 /* Sometimes we want to print only succeeding syscalls. */
 int not_failing_only = 0;
@@ -187,9 +206,11 @@ usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... 
[-o file]\n\
    options: trace, abbrev, verbose, raw, signal, read, or write\n\
 -o file -- send trace output to FILE instead of stderr\n\
 -O overhead -- set overhead for tracing syscalls to OVERHEAD usecs\n\
--p pid -- trace process with process id PID, may be repeated\n\
--D -- run tracer process as a detached grandchild, not as parent\n\
--s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
+-p pid -- trace process with process id PID, may be repeated\n"
+#if !defined USE_PROCFS && !defined USE_VFORK
+"-D -- run tracer process as a detached grandchild, not as parent\n"
+#endif
+"-s strsize -- limit length of print strings to STRSIZE chars (default %d)\n\
 -S sortby -- sort syscall counts by: time, calls, name, nothing (default %s)\n\
 -u username -- run command as username handling setuid and/or setgid\n\
 -E var=val -- put var=val in the environment for command\n\
@@ -210,14 +231,6 @@ foobar()
 #endif /* MIPS */
 #endif /* SVR4 */
 
-/* Glue for systems without a MMU that cannot provide fork() */
-#ifdef HAVE_FORK
-# define strace_vforked 0
-#else
-# define strace_vforked 1
-# define fork()         vfork()
-#endif
-
 static int
 set_cloexec_flag(int fd)
 {
@@ -571,7 +584,11 @@ startup_child (char **argv)
        }
        strace_child = pid = fork();
        if (pid < 0) {
-               perror(strace_vforked ? "strace: vfork" : "strace: fork");
+#ifdef USE_VFORK
+               perror("strace: vfork");
+#else
+               perror("strace: fork");
+#endif
                cleanup();
                exit(1);
        }
@@ -602,8 +619,10 @@ startup_child (char **argv)
                                perror("strace: ptrace(PTRACE_TRACEME, ...)");
                                exit(1);
                        }
+#ifndef USE_VFORK
                        if (debug)
                                kill(pid, SIGSTOP);
+#endif
                }
 
                if (username != NULL || geteuid() == 0) {
@@ -620,12 +639,22 @@ startup_child (char **argv)
                         * lose privileges on setuid.
                         */
                        if (username != NULL) {
-                               /* initgroups is not safe in a vfork child. */
-                               if (!strace_vforked
-                                   && initgroups(username, run_gid) < 0) {
+#ifndef USE_VFORK
+                               if (initgroups(username, run_gid) < 0) {
                                        perror("initgroups");
                                        exit(1);
                                }
+#else /* vfork */
+                               /*
+                                * initgroups is not safe in a vfork child
+                                * because it parses /etc/group.
+                                */
+                               if (setgroups(0, (const gid_t *)NULL) < 0) {
+                                       perror("setgroups");
+                                       exit(1);
+                               }
+#endif /* vfork */
+
                                if (setregid(run_gid, run_egid) < 0) {
                                        perror("setregid");
                                        exit(1);
@@ -647,8 +676,9 @@ startup_child (char **argv)
                         * Unless of course we're on a no-MMU system where
                         * we vfork()-ed, so we cannot stop the child.
                         */
-                       if (!strace_vforked)
-                               kill(getpid(), SIGSTOP);
+#ifndef USE_VFORK
+                       kill(getpid(), SIGSTOP);
+#endif
                } else {
                        struct sigaction sv_sigchld;
                        sigaction(SIGCHLD, NULL, &sv_sigchld);
@@ -723,7 +753,7 @@ main(int argc, char *argv[])
        qualify("signal=all");
        while ((c = getopt(argc, argv,
                "+cCdfFhiqrtTvVxz"
-#ifndef USE_PROCFS
+#if !defined USE_PROCFS && !defined USE_VFORK
                "D"
 #endif
                "a:e:o:O:p:s:S:u:E:")) != EOF) {
@@ -747,7 +777,7 @@ main(int argc, char *argv[])
                case 'd':
                        debug++;
                        break;
-#ifndef USE_PROCFS
+#if !defined USE_PROCFS && !defined USE_VFORK
                /* Experimental, not documented in manpage yet. */
                case 'D':
                        daemonized_tracer = 1;
@@ -2463,8 +2493,11 @@ Process %d attached (waiting for parent)\n",
                 * A no-MMU vforked child won't send up a signal,
                 * so skip the first (lost) execve notification.
                 */
-               if ((tcp->flags & TCB_STARTUP) &&
-                   (WSTOPSIG(status) == SIGSTOP || strace_vforked)) {
+               if ((tcp->flags & TCB_STARTUP)
+#ifndef USE_VFORK
+                   && WSTOPSIG(status) == SIGSTOP
+#endif
+                       ) {
                        /*
                         * This flag is there to keep us in sync.
                         * Next time this process stops it should
-- 
1.7.0.4

_______________________________________________
uClinux-dev mailing list
uClinux-dev@uclinux.org
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by uclinux-dev@uclinux.org
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev

Reply via email to