* 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