Re: interesting segfault when running awk as pid==1
On 07.07.2012 23:33, Denys Vlasenko wrote: [] The debian-specific patch in question is this (one-liner): shell/ash.c: - { VSTRFIXED|VTEXTFIXED , bb_PATH_root_path, changepath }, + { VSTRFIXED|VTEXTFIXED|VEXPORT, bb_PATH_root_path, changepath }, so it merely exports PATH variable, and should not affect the behavour in question, but I'm not sure anymore about this. It looks rather innocent. Apparently, it makes it so that ash exports $PATH. If $PATH was in the set of inherited variables, then it is reused, and this apparently works. But in init, $PATH may be _not_ inherited. So ash sets its own $PATH (I just tested it): PATH=/sbin:/usr/sbin:/bin:/usr/bin Basically, these two scenarios are not exactly the same. Try reproducing segfault by running ahs with empty environment: env - /path/to/busybox ash Does it segfault if you run awk from it? Reproduced. if (environ) for (envp = environ; *envp; envp++) { /* environ is writable, thus we don't strdup it needlessly */ char *s = *envp; char *s1 = strchr(s, '='); if (s1) { *s1 = '\0'; It happens in the above line. Caused by: ash.c: static void tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp) { #if ENABLE_FEATURE_SH_STANDALONE if (applet_no = 0) { if (APPLET_IS_NOEXEC(applet_no)) { clearenv(); while (*envp) putenv(*envp++); ^^ run_applet_no_and_exit(applet_no, argv); } /* re-exec ourselves with the new arguments */ execve(bb_busybox_exec_path, argv, envp); /* If they called chroot or otherwise made the binary no longer * executable, fall through */ } #endif Basically, we putenv() a string which is constant, and when we try to modify it, we segfault. Thank you Denys, thank you very much for figuring it out. I was about to add printfs here and there, planned to do that today evening. I think Debian's patch does something which is not supported. Funny you mention it. The thing is: with the patch, there's just ONE variable marked as VEXPORT, and no variable is marked as such without the patch. So I'm not surprized it doesn't work. Looking at the other places, everywhere where VEXPORT flag is used, the variable in question is dynamically allocated. So setting this flag for initial value is indeed not supported -- maybe it is a good idea to document this fact in the code. Now, for the root issue -- exporting $PATH from [a]sh -- I inherited this patch together with busybox debian package, and am now trying to understand where it comes from and for what. I'll drop it from the next Debian release (wheezy+1), since neither bash nor dash exports $PATH by default. But for now, I'll have to change the way stdpath is set up, to allow VEXPORT to work correctly. Thank you very much for finding the root of the issue! /mjt ___ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox
Re: interesting segfault when running awk as pid==1
On 06.07.2012 04:10, ra...@gmx.de wrote: Hi Michael ! I've an interesting case here, when busybox (in debian) segfaults when run in initramfs as pid == 1, when invoking awk applet (PREFER_APPLETS is set to yes). I can't trigger it with pid != 1, and since pid=1 is special in linux, I can't really debug it too. I hit this problem some years ago. May be same reason. Try running awk via env command and setup some environment variables. pid 1 is special as environment on invocation may be empty (or something missing, most likely SHELL or PATH). As I stated in my initial email, when running awk from a subshell it works. I know PID=1 is special, and for one, it can't be straced or debugged. PATH isn't empty since busybox ash sets it to some value, but PATH at least _should_ be irrelevant, since awk is NOEXEC applet. And finally, it isn't a solution to run it from a subshell, since running awk from within /init in initramfs is a valid usage case. Thanks for trying, /mjt ___ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox
Re: interesting segfault when running awk as pid==1
As I stated in my initial email, when running awk from a subshell it works. I know PID=1 is special, and for one, it can't be straced or debugged. Actually, on some Linux versions (I'm not certain which ones though, but it should work on modern kernels), process 1 *can* be straced: somehow get a shell running and do strace -p 1. If you're not afraid of dirty hacks, you could even run that from your /init, if everything is properly mounted: ( strace -p 1 /dev/null /dev/null 2/tmp/strace-file ) or even replace /tmp/strace-file with /dev/tty for a live performance. And finally, it isn't a solution to run it from a subshell, since running awk from within /init in initramfs is a valid usage case. But are you really running awk as process 1 ? I doubt your /init script is *executing* awk. If it was, then after performing its work, awk would die, and your kernel would panic. I suspect that instead, your /init script looks like #!/bin/sh ... awk something ... exec chroot foobar /sbin/init in which case you are *not* running awk as process 1: your shell is forking first, then executing awk as a child. The question then becomes, why is there a problem when awk is run directly as process 1's child. -- Laurent ___ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox
Re: interesting segfault when running awk as pid==1
On 06.07.2012 15:03, Laurent Bercot wrote: As I stated in my initial email, when running awk from a subshell it works. I know PID=1 is special, and for one, it can't be straced or debugged. Actually, on some Linux versions (I'm not certain which ones though, but it should work on modern kernels), process 1 *can* be straced: somehow get a shell running and do strace -p 1. If you're not afraid of dirty hacks, you could even run that from your /init, if everything is properly mounted: ( strace -p 1 /dev/null /dev/null 2/tmp/strace-file ) or even replace /tmp/strace-file with /dev/tty for a live performance. I tried this right away, but failed: strace does not show anything at all in that case, even if the process 1 actually does something. No, I'm not afraid at all, since it is trivial to experiment in a virtual machine. And I don't think strace will do anything interesting here: I looked at what happens when busybox ash spawns awk in a regular case, there, it just forks (with a pipe open) and does one or two read/writes -- it is ofcourse not enough information to understand what's going on. It may help a bit ofcourse, if I'll add a few debug printfs here and there. Ideally it'd be nice to get a coredump, but for some reason the process being fork'ed in this context isn't dumpable. And finally, it isn't a solution to run it from a subshell, since running awk from within /init in initramfs is a valid usage case. But are you really running awk as process 1 ? I doubt your /init script is *executing* awk. If it was, then after performing its work, awk would die, and your kernel would panic. I suspect that instead, your /init script looks like #!/bin/sh ... awk something ... exec chroot foobar /sbin/init in which case you are *not* running awk as process 1: your shell is forking first, then executing awk as a child. The question then becomes, why is there a problem when awk is run directly as process 1's child. Well. My $subject is inaccurate. I meant to say when awk is spawned from pid=1 as NOEXEC applet. The code like rootfs=`awk '$2==/{print $1}` or anything of this theme. This works: rootfs=`/bin/awk '$2==/{print $1}` rootfs=`busybox awk '$2==/{print $1}` and this rootfs=`awk '$2==/{print $1}` segfaults, just like a bare 'awk' call: awk (in normal case it produces an error message about invalid usage). Thank you! /mjt ___ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox
Re: interesting segfault when running awk as pid==1
Hi Michael, I'm still mentioning to look in detail on the content of the environment. I know awk itself shell not need PATH etc., but Busybox does. As Busybox is a multi call binary it contains common code. First to invoke the applet and second for internal library functions. Some of those code need environment information or other information possibly not required by a bare awk. Running awk from a shell script which is run as /bin/init differs in environment from running a second shell and invoking awk from there. As soon as an interactive shell is invoked the shell startup code set several environment defaults in case there are needed. This may indeed fix your segfault problem. I know I had trouble for weeks as I stumbled on this. And came of a so simple solution ... it was just to invoke awk via env that is: env - awk AWKARGS This sometimes solved my segfaulting start problem with awk. In othe cases I needed to manually set some environment values. It is good practice to set some environment variables right at the start of the script running as init: export TERM=linux export USER=root export HOME=/root export SHELL=/bin/sh export PATH=/bin:/sbin:/usr/bin:/usr/sbin This shall give you a sane environment where most commands work as expected. Without this the contents of the environment is purely random (system/kernel version depended), as Busybox does not setup a full initial environment, if invoked as init script (default behavior of POSIX sh for non interactive invocation). Harald ___ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox
Re: interesting segfault when running awk as pid==1
Hi Michael ! I've an interesting case here, when busybox (in debian) segfaults when run in initramfs as pid == 1, when invoking awk applet (PREFER_APPLETS is set to yes). I can't trigger it with pid != 1, and since pid=1 is special in linux, I can't really debug it too. I hit this problem some years ago. May be same reason. Try running awk via env command and setup some environment variables. pid 1 is special as environment on invocation may be empty (or something missing, most likely SHELL or PATH). Harald ___ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox