Quantcast
Channel: MobileRead Forums - Kobo Developer's Corner
Viewing all articles
Browse latest Browse all 1561

Kobo's busybox, setuid and mystery about /bin/busybox ?!

$
0
0
Hi,

I'm working on a KoboAuraHD and Glo, and of course -- for an embedded system the Kobo uses busybox (likey to save memory) and busybox has some peculiar problems.

I'm needing to create user accounts that are not super-user based, and which allow users to add their own temporary libraries (LD_LIBRARY_PATH), but still allow users to login as superuser, or execute scripts with a command like sudo.

That way games can be installed relatively safely on the kobo.

But -- the kobo won't allow a user to do that. eg: Busybox in the Kobo isn't installed as set user id enabled, and also linux on the Kobo prevents plain scripts from running set user id for good security reasons.

So -- I thought, no problem -- turn on suid root on busybox and configure it like a normal linux system. But then things got *really* strange.....

For a configured busybox doesn't work quite right. eg: And I mean even if /bin/busybox is owned by root, and chmod u+s /bin/busybox is done -- and busybox is configured so that ONLY two busybox applets are allowed to actually run suid, the rest being demoted to normal user -- it STILL doesn't work right.

I did in fact install this config as root:root @ chmod 600 /etc/busybox.config
Code:

[SUID]
su = ssx root.root
login = ssx root.root


When a normal user tries to run su or login, busybox is SUPPOED to erase the shell variable LD_LIBRARY_PATH, and several others during busybox operation so that no one can use a hacked library to crack into the system. But busybox has no reason to keep the variables cleared, unless the user is running a dangerous applet as root.

Normally busybox doesn't cause problems...

However, on the Kobo, busybox's modified code strangely doesn't appear smart enough to tell the difference, and it clears the variables regardless of whether they are dangerous or not; and never restores them. ( Hence it causes bugs in innocent programs. )

For example if I want to use a python script requiring an interpreter stored on extenal SD card, which is plugged in temporarily; then there are no superuser priveleges involved, desired, or needed -- and no reason to clear LD_LIBRARY_PATH after busybox terminates suid mode.

Yet, if I export LD_LIRBARY_PATH=/mnt/sd/libs and then create a python script with the standard opening line:
Code:

#!/usr/bin/env python
#test.py -- this file is a script to test python.
print "ran a python 2.7.10 script"

The following happens when you try to use it from a login shell (but not a root shell).

Code:

$ EXPORT LD_LIBRARY_PATH=/mnt/sd/libs
$ ./test.py
python: error while loading shared libraries: libpython2.7.so.1.0: cannot open shared object file: No such file or directory
$ python test.py
ran a python 2.7.10 script
[18366 refs]

And the reason is simple, because env is a busybox command -- and it's erasing LD_LIBRARY_PATH and forgetting to restore it once it realizes that 'env' is not supposed to be run as superuser. The erasure never happens except when a busybox command is run.

I tried to download busybox source code to figure out how add code to solve the problem.
But what I'm reading in the source code, and what is happening with busybox don't match.

I even asked George.talusan which version of busybox the Kobo used a while back to make sure I'm not insane, and was told after much ambiguous dialog that the version *in* the repository is in fact up to date. (http://www.mobileread.com/forums/sho...0&postcount=26 )

OK. Fine. So I'll assume the *unlabeled* version of busybox on the kobo git repository is in fact up to date. ( https://github.com/kobolabs/busybox ).

Now, here's where it gets really weird -- see if you can explain what I discovered...:
Busybox runs a subroutine that sanitizes several variables, the routine is the ONLY place that the word LD_LIBRARY_PATH shows up in the whole KoboLabs busybox repository:

https://github.com/kobolabs/busybox/.../libbb/login.c

When I do strings /bin/busybox on the Kobo, sure enough there is only ONE instance of that string in the whole busybox binary. And it should NOT clear shell variables once busybox decides to de-escalate from superuser setuid mode to normal mode... but apparently it still does...

So -- I thought I'd be smart, and used a hex editor to do an experiment -- and searched the /bin/busybox binary, and found the table of strings. I changed only LD_LIBRARY_PATH, to LE_LIBRARY_PATH, and re-saved the binary with the change. I then re-installed it on my kobo as /bin/busybox.
This version of busybox is the one found on my AuraHD after installing KoboUpdate version 3.15.0, which I downloaded manually from MR forums link, and the hexeditor dump of the part I changed follows:

Quote:

0081660: 484f 4d45 0049 4653 0053 4845 4c4c 004c HOME.IFS.SHELL.L
0081670: 455f 4c49 4252 4152 595f 5041 5448 004c E_LIBRARY_PATH.L
0081680: 445f 5052 454c 4f41 4400 4c44 5f54 5241 D_PRELOAD.LD_TRA
0081690: 4345 5f4c 4f41 4445 445f 4f42 4a45 4354 CE_LOADED_OBJECT
NOTE: You can find the original and edited files, as I got them off my AuraHD in the system.tar.gz archive at the end of this post; along with a utility program called 'system'.

So, in theory -- if /bin/busybox is being run, is must change LE_LIBRARY_PATH, instead of LD_LIBRARY_PATH. But that doesn't happen.... So I began thinking maybe a binary in memory was running and the one on disk was not because it was running when I changed it; so I even rebooted, and it still doesn't work. I checked the md5sum -- and my binary is installed at /bin/busybox.

WTFoobar?!

Busybox magically still erases LD_LIBRARY_PATH and does NOT erase LE_LIBRARY_PATH even though LD_LIBRARY_PATH does not exist anywhere in the binary.. How is this possible ??! :chinscratch:

Is the kobo really running /bin/busybox ? or is there a trick making it run a different version of it in spite of the applets specifically pointint at /bin/busybox ?

--------- In the meantime I made a hacky fix that is pretty unix flavor independent -------

I made a second program which allows me to work around the problem and takes up very little memory. Eg: it lets me implement sudo capability on scripts without recompiling busybox, so I can run some of busybox's commands by replacing their soft links in /bin/busybox with a suid script (which doesn't run as suid in linux), that calls a suid program (which does run suid in linux), to decide whether or not to run busybox as a different uid or NOT. This both fixes the problem -- indirectly -- and lets me test busybox out to see if the suid vs. real uid is causing the erasure or not -- result -- the difference in uid and euid is what triggers busybox to erase variables.

Since my only other choice is to recompile busybox so that I have two versions of it, one of which runs as suid -- and one which does not. And this solution wastes less memory.... I thought I would share it as a useful system tool.

I can now make what are reasonably secure one liner scripts like this one for /bin/su:
Code:

#!/bin/system \slogin root
The \s makes the script line following it run as superuser, but only if the shell script and the /bin/system program are both owned by root, and only if both are setuid.

Read the comments in the attached source code to how it works, as it's very short -- and I believe it still keeps the system secure. Comments welcome; Busybox no longer needs to be setuid, ever; though I would like to fix it properly.

Now I've tested this weird behavior out, and none of the explanations I come up with make sense.
Any geniuses out there, who can explain how a hex edited version of Busybox is still erasing LD_LIBRARY_PATH? (It's attached so you can check how I edited it.)

ffa324c328fdc4c168433337d4c58c7f busybox.old (Unedited MD5 sum)
0b17487b53dd95a306d834bb8a7ebd79 busybox (Edited busbox's MD5 sum)
e009836ddb97f0f9d01e854f20e2b249 system.tar.gz

Attached Files
File Type: gz system.tar.gz (786.5 KB)

Viewing all articles
Browse latest Browse all 1561

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>