Attend XDA's Second Annual Developer Conference, XDA:DevCon 2014!
5,808,174 Members 36,026 Now Online
XDA Developers Android and Mobile Development Forum

Permission denied though uid=root

Tip us?
 
t0kt0ckus
Old
(Last edited by t0kt0ckus; 14th July 2014 at 06:15 PM.)
#1  
Junior Member - OP
Thanks Meter 1
Posts: 7
Join Date: Jul 2014
Default Permission denied though uid=root

I'm trying to understand why I still get such "Permission denied" errors though I'm UID root.

I will describe my setup and particular error, but I think a proper explanation of what's happening may interest others.

I just need occasional root shell for reverse engineering sessions, and from what I know, a simple way to achieve this is to boot a modified initial ramdisk that contains a properly modified /default.prop, and/or a setuid shell, and/or some kind of su command.

I managed to successfully boot the device (Moto G) with my custom modified image using "fastboot boot custom_boot.img".

First I can verify it's actually "my initrd.img" that's in use:
Code:
shell@falcon_umts:/ $ cat /default.prop                                        
#
# ADDITIONAL_DEFAULT_PROPERTIES
#
ro.secure=0
ro.allow.mock.location=0
ro.debuggable=1
This does _not_ allow me to get root shell (with "adb shell"):
Code:
shell@falcon_umts:/ $ id                                                       
uid=2000(shell) gid=2000(shell) groups=1003(graphics),1004(input),1007(log),1009(mount),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) context=u:r:shell:s0
So, I added a setuid copy of /system/bin/sh to the initial ramdisk, at "/sbin/shell0".
Code:
shell@falcon_umts:/ $ ls /sbin/shell0 -l                                       
-rwsr-xr-- root     shell      157424 2014-07-14 16:08 shell0
shell@falcon_umts:/ $ /sbin/shell0                                             
# id
uid=2000(shell) gid=2000(shell) groups=1003(graphics),1004(input),1007(log),1009(mount),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) context=u:r:shell:s0
# exit
shell@falcon_umts:/ $ /sbin/shell0 +p                                                
shell@falcon_umts:/ # id
uid=0(root) gid=2000(shell) groups=2000(shell) context=u:r:shell:s0
shell@falcon_umts:/ # ls /data/                                                
opendir failed, Permission denied
Here, it appears that I have to use the "+p" flag to prevent the shell to immediately get back to the real user id (2000), despite the suid bit is set on /sbin/shell0.
But I don't understand I don't have the permission neither to open simple directories as /data, nor to read the interesting stuff in the /proc subsystem, though I'm uid=0 (root).

I've also tried adding to the initial ramdisk a simple su command, at /sbin/test_su, that does the setuid(0)/setgid(0)/execve(...) thing (snippets available at android.googlesource.com).

But though this properly keep the supplementary groups I had lost within the previous try above, I still can't read into /data:
Code:
shell@falcon_umts:/ $ ls -l /sbin/test_su                                      
-rwsr-xr-- root     shell        6316 2014-07-14 17:12 test_su
shell@falcon_umts:/ $ test_su                                                  
root@falcon_umts:/ # id
uid=0(root) gid=0(root) groups=1003(graphics),1004(input),1007(log),1009(mount),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) context=u:r:shell:s0
root@falcon_umts:/ # ls /data/                                                 
opendir failed, Permission denied
From a un*x point of view, it seems weird to me that the shell still answers "opendir failed, Permission denied" while I'm uid/gid 0 (root).
I will continue to investigate, notably regarding SELinux which may enforce rules I'm not aware of, but would also greatly appreciate anyone who could put some light on this issue. At least for me it's an issue, as I don't understand what's happening.

Thanks.
 
cernekee
Old
#2  
Senior Member
Thanks Meter 364
Posts: 182
Join Date: Jun 2013
Quote:
Originally Posted by t0kt0ckus View Post
So, I added a setuid copy of /system/bin/sh to the initial ramdisk, at "/sbin/shell0".
Note that making a setuid shell executable might not be 100% reliable. When I've tried this with bash, it quickly realizes that getuid() != geteuid(), and drops the root permission.

I don't see this happening in your logs, but it's something to watch out for. Typically I've just used simple wrapper programs like the attached file to guarantee that the real/effective/saved UIDs are 0/0/0.

Quote:
From a un*x point of view, it seems weird to me that the shell still answers "opendir failed, Permission denied" while I'm uid/gid 0 (root).
I will continue to investigate, notably regarding SELinux which may enforce rules I'm not aware of, but would also greatly appreciate anyone who could put some light on this issue. At least for me it's an issue, as I don't understand what's happening.
Chainfire is probably the best person to comment on Android SELinux matters. If you look through his old G+ posts you may be able to determine which restrictions apply to your security context.

Do you see any denials logged in dmesg? (Or is that inaccessible too?)

If there is a /selinux/enforce file, does it read back '0' or '1'?
Attached Files
File Type: c run-suid.c - [Click for QR Code] (1.9 KB, 9 views)
OpenConnect for Android - a FOSS AnyConnect/ocserv VPN client with advanced features
Easy Token - RSA SecurID token with widgets
AFWall+ - the successor to DroidWall
 
t0kt0ckus
Old
(Last edited by t0kt0ckus; 19th July 2014 at 01:21 PM.)
#3  
Junior Member - OP
Thanks Meter 1
Posts: 7
Join Date: Jul 2014
Thank you for your answer.

Quote:
Originally Posted by cernekee View Post
Note that making a setuid shell executable might not be 100% reliable. When I've tried this with bash, it quickly realizes that getuid() != geteuid(), and drops the root permission.
I don't see this happening in your logs, but it's something to watch out for. Typically I've just used simple wrapper programs like the attached file to guarantee that the real/effective/saved UIDs are 0/0/0.
I've looked at your attached source, the main difference with my own wrapper is that you fork the process, I've tried also, behavior is the same. But, after reading your comment, I've modified my setuid/execve code, to make it more verbose about the real/effective/saved UIDs (using getresuid()).

Code:
shell@falcon_umts:/ $ test_su                                                  
Initial UIDs
ruid: 2000
euid: 0
suid: 0
Setting UIDs ...
New UIDs
ruid: 0
euid: 0
suid: 0
root@falcon_umts:/ # ls /data/                                                 
opendir failed, Permission denied
1|root@falcon_umts:/ #
It clearly appears that, POSIX speaking, all go fine until the "Permission denied" error:
  1. the effective uid is already 0 (just after the "adb shell" command), which is expected and documented, as the content of my /default.prop prevents the shell to revert its effective uid to its real one, which would then be 2000 (shell)
  2. after the setuid(0) call, the real uid is successfully set to 0, as expected, because the suid bit is set AND we were already privileged (if not privileged, setuid() should only change the effective uid, as for "man 2 setuid")
  3. after execve(..), the whole prompt, "root@falcon_umts:/ #", again confirms the real uid is 0 (root)

Quote:
Chainfire is probably the best person to comment on Android SELinux matters. If you look through his old G+ posts you may be able to determine which restrictions apply to your security context.
Yes, I definitely need to dig into the SELinux/Android stuff (see bellow), and will try to find the Chainfire posts you propose.

Quote:
Do you see any denials logged in dmesg? (Or is that inaccessible too?)
If there is a /selinux/enforce file, does it read back '0' or '1'?
Neither dmseg (which is accessible) nor logcat shows any related error or warning.
I haven't any /selinux/enforce file, but it clearly appears from information bellow that SELinux is activated and enforced:

Code:
 
shell@falcon_umts:/ $ getenforce                                               
Enforcing
root@falcon_umts:/ # setenforce 0                                              
setenforce:  Could not set enforcing status:  Permission denied
shell@falcon_umts:/ $ cat seapp_contexts                                       
isSystemServer=true domain=system
user=system domain=system_app type=system_data_file
user=bluetooth domain=bluetooth type=bluetooth_data_file
user=nfc domain=nfc type=nfc_data_file
user=radio domain=radio type=radio_data_file
user=_app domain=untrusted_app type=app_data_file levelFrom=none
user=_app seinfo=platform domain=platform_app type=platform_app_data_file
user=_app seinfo=shared domain=shared_app type=platform_app_data_file
user=_app seinfo=media domain=media_app type=platform_app_data_file
user=_app seinfo=release domain=release_app type=platform_app_data_file
user=_isolated domain=isolated_app
user=shell domain=shell type=shell_data_file
user=log domain=log_app type=system_data_file
user=sprint_extension domain=carrier_ext type=platform_app_data_file
user=smartcard domain=smartcard type=smartcard_data_file
I'm a noob at SELinux, and I may be wrong, but I think a rule policy could prevent a user, being it root, to achieve certain actions. I need to read stuff about this.

The initial boot image that I modify (just add my suid shell /sbin/test_su) is the 4.4.2 one from sbf, and I expand/repack it using standard un*x tools (gunzip,cpio,...) and abootimg. Anything wrong with that ?

I build the C files using:
Code:
$ echo $CC
<android-ndk>/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc --sysroot=<android-ndk>/platforms/android-19/arch-arm
$ $CC -o test_su test_su.c
Should I use particular flags for gcc, to make it produce SELinux aware object files ?
[EDIT: stupid question, answer is no]

Again, thanks for your help and ideas.
 
t0kt0ckus
Old
#4  
Junior Member - OP
Thanks Meter 1
Posts: 7
Join Date: Jul 2014
Just for information (for thus who are as dumb as I am): acquiring uid=(euid=suid=)0 is of little or no help within a user application, you're (obviously) still constrained by capabilities you can't acquire unless involving some kind of exploit.
To get a shell that's not restricted by the SE policies (on the 4.4 branch), the main way seems to have somewhat a system daemon capable to spawn /system/bin/sh with appropriate privileges/capabilities upon su client requests: so you again need an exploit.
So, for my understanding, starting with KitKat you can't anymore get a useful adb root shell through the uid=0 thing (traditional su), you have either to flash a custom rom or involve an exploit.
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes