busybox and upx on arm
Tito
farmatito at tiscali.it
Sun Jul 19 11:12:37 UTC 2009
On Thursday 09 July 2009 23:21:06 Denys Vlasenko wrote:
> On Tuesday 07 July 2009 21:45, Tito wrote:
> > Hi,
> > I'm experiencing a strange behaviour of busybox.
> > I'm trying to use upx on an android g1 phone.
> > So far I was able to cross-compile a statically linked
> > and working copy of upx
> > upx compresses the executables on the phone just fine,
> > only busybox seems not to work as expected.
> > upx compresses it but when the compressed
> > busybox is launched it runs the command as
> > expected but never returns to the shell unless it is killed.
> > The only suspect log i can see after killing it is:
> >
> > <3>[ 3261.966003] init: untracked pid 5064 exited
> > <3>[ 3290.064056] init: untracked pid 5066 exited
> > <3>[ 3339.908325] init: untracked pid 5069 exited
> >
> > Any hints about what is going wrong here?
> >
> > BTW: busybox packed with upx on x86 works.
> >
> > /system/sd # ./upx busybox
> > Ultimate Packer for eXecutables
> > Copyright (C) 1996 - 2009
> > UPX 3.04 Markus Oberhumer, Laszlo Molnar & John Reiser Apr 27th 2009
> >
> > File size Ratio Format Name
> > -------------------- ------ ----------- -----------
> > 690276 -> 381428 55.26% linux/armel busybox
> >
> > Packed 1 file.
> > /system/sd # ./busybox
> > BusyBox v1.14.2 (2009-07-01 18:27:27 EDT) multi-call binary
> > Copyright (C) 1998-2008 Erik Andersen, Rob Landley, Denys Vlasenko
> > and others. Licensed under GPLv2.
> > See source distribution for full notice.
> >
> > Usage: busybox [function] [arguments]...
> > or: function [arguments]...
> >
> > BusyBox is a multi-call binary that combines many common Unix
> > utilities into a single executable. Most people will create a
> > link to busybox for each function they wish to use and BusyBox
> > will act like whatever it was invoked as!
> >
> > Currently defined functions:
> > [, [[, arping, ash, awk, basename, bbconfig, bunzip2, bzcat,
> > bzip2, cat, catv, chgrp, chmod, chown, chroot, chrt, chvt, cksum,
> > clear, cmp, cp, cpio, crond, crontab, cut, date, dc, dd, deallocvt,
> > depmod, devmem, df, dhcprelay, diff, dirname, dmesg, dnsd, dos2unix,
> > du, dumpkmap, dumpleases, echo, egrep, env, ether-wake, expr,
> > false, fbset, fdisk, fgrep, find, fold, free, freeramdisk, fuser,
> > getopt, grep, gunzip, gzip, head, hexdump, hostname, hwclock,
> > ifconfig, ifdown, ifup, insmod, install, ip, ipaddr, iplink,
> > iproute, iprule, iptunnel, kbd_mode, kill, killall, killall5,
> > last, length, less, ln, loadfont, loadkmap, losetup, ls, lsmod,
> > makedevs, md5sum, mdev, mkdir, mkfifo, mknod, mkswap, mktemp,
> > modprobe, more, mount, mountpoint, mv, nameif, nc, netstat,
> > nice, nohup, nslookup, od, openvt, patch, pidof, ping, pipe_progress,
> > pivot_root, printenv, printf, ps, pwd, rdate, rdev, readlink,
> > readprofile, realpath, renice, reset, rm, rmdir, rmmod, route,
> > run-parts, sed, seq, setconsole, setkeycodes, setlogcons, setsid,
> > sh, sha1sum, showkey, sleep, sort, split, stat, strings, stty,
> > swapoff, swapon, switch_root, sync, sysctl, tac, tail, tar,
> > tcpsvd, tee, telnet, telnetd, test, tftp, time, top, touch,
> > tr, traceroute, true, tty, udhcpd, udpsvd, umount, uname, uniq,
> > unix2dos, unzip, uptime, usleep, uudecode, uuencode, vconfig,
> > vi, watch, wc, wget, which, who, whoami, xargs, yes, zcat
> > Killed
>
> Try in libbb/appletlib.c:
>
>
> void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv)
> {
> int argc = 1;
>
> while (argv[argc])
> argc++;
>
> /* Reinit some shared global data */
> xfunc_error_retval = EXIT_FAILURE;
>
> applet_name = APPLET_NAME(applet_no);
> if (argc == 2 && strcmp(argv[1], "--help") == 0) {
> /* Special case. POSIX says "test --help"
> * should be no different from e.g. "test --foo". */
> //TODO: just compare applet_no with APPLET_NO_test
> if (!ENABLE_TEST || strcmp(applet_name, "test") != 0)
> bb_show_usage();
> }
> if (ENABLE_FEATURE_SUID)
> check_suid(applet_no);
> exit(applet_main[applet_no](argc, argv));
> }
>
> Replace
> exit(applet_main[applet_no](argc, argv));
> with
> printf("Entering applet_main\n");
> n = applet_main[applet_no](argc, argv);
> printf("Exited epplet_main, exiting...\n");
> exit(n);
>
> and let me know hat do you see when you run "busybox true".
> --
> vda
>
Hi,
after doing a little research and asking for advice the author of my phone's ROM
I am now able to reproduce this behaviour consistently.
The busybox binary is built with buildroot-2009.05 (config attached)
The static uclibc binary i obtain is:
debian:~/Desktop/buildroot-2009.05/project_build_arm/uclibc/busybox-1.14.1$ readelf -h busybox
ELF Header:
Magic: 7f 45 4c 46 01 01 01 03 04 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - Linux
ABI Version: 4
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x547cc
Start of program headers: 52 (bytes into file)
Start of section headers: 0 (bytes into file)
Flags: 0x4000002, has entry point, Version4 EABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 2
Size of section headers: 40 (bytes)
Number of section headers: 0
Section header string table index: 0
This can be compressed with the latest upx (needs also libucl):
hg pull from https://www.pysol.org:4443/hg/upx.hg
debian:~/Desktop/buildroot-2009.05/project_build_arm/uclibc/busybox-1.14.1$ ./upx.out busybox
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2009
UPX 3.04 Markus Oberhumer, Laszlo Molnar & John Reiser Apr 27th 2009
File size Ratio Format Name
-------------------- ------ ----------- -----------
588552 -> 315564 53.62% linux/armel busybox
Packed 1 file.
After uploading it to the phone the binary shows the exact behaviour as expected:
the requested command is executed but it never returns to the shell.
The output of your debug code is:
/system/sd/bin # ./busybox true
Entering applet_main
Exited applet_main, exiting... (hangs forever)
I've also tested changing exit to _exit
printf("Entering applet_main\n");
n = applet_main[applet_no](argc, argv);
printf("Exited applet_main, exiting...%d\n", n);
_exit(n);
This seems to fix the bug:
./busybox true
Entering applet_main
Exited applet_main, exiting...0
only if you call ./busybox with no args it hangs, but this is also
fixed by changing:
void FAST_FUNC run_applet_and_exit(const char *name, char **argv)
{
int applet = find_applet_by_name(name);
if (applet >= 0)
run_applet_no_and_exit(applet, argv);
if (!strncmp(name, "busybox", 7))
- exit(busybox_main(argv));
+ _exit(busybox_main(argv));
}
Same for when usage is shown.
So it seems that by changing exit with _exit everything works.
Maybe #define exit _exit ?
Hope this helps you somehow to fix the bug if there is any (maybe it is just a toolchain issue??)
Ciao,
Tito
-------------- next part --------------
A non-text attachment was scrubbed...
Name: buildroot-config.zip
Type: application/x-zip
Size: 4489 bytes
Desc: not available
URL: <http://lists.busybox.net/pipermail/busybox/attachments/20090719/b0766454/attachment.bin>
More information about the busybox
mailing list