Open lbdroid opened 9 years ago
Oops, you're right, thanks. Now, it's not the app who calls app_process, I guess it's system_server who does it, so it would still work (unless it explicitly forgets LD_PRELOAD)
Changing file_contexts should be enough to change context of /sbin/su, no?
No, the ramdisk doesn't store the extended attributes, which means that it has to be restored after selinux is initialized. I spent about 3 hours bashing my head against a wall last night figuring this out.
In fact, I'm targeting init.c specifically because that is where google does precisely this. Line 1048 they restore the context on /init itself and cause it to self-re-exec with the new context.
Yes, but file_contexts is the file read at run-time to apply context
Right, but to make it apply, you still need to run restorecon, which it does NOT do automatically.
http://blog.gmane.org/gmane.comp.security.seandroid/month=20150601 http://comments.gmane.org/gmane.comp.security.seandroid/2301
The first link is a discussion about adding built-in file context support to the rootfs, the second is discussing adding a restorecon_recursive("/sbin") to init.c.
You should recognize the name Nick Kralevich from both of those threads.
Actually may not have to go to that extreme, since with daemon mode the application doesn't need to make the transition, just the daemon, and that can be transitioned using seclabel from the init.zygote
Thanks for all your research, nice to know. Having a transition when calling /sbin/su would be great to have better protection on the su socket/pts, and I don't see a problem in doing remount rw/restorecon/remount ro. I don't think manufacturer would break that.
But I agree that for first steps seclabel is enough.
Good point!
I've managed to get su working through adb (shell context), having selinux enforcing.
Nice :-) Next step is from untrusted_app
Correction: I actually have it working also from untrusted_app, there are just some context screwups that limit what I can do with it.
If I try using the --context option, it gives a hard time connecting to the daemon.
Like this: (--context u:r:system_app:s0)
[ 508.008088] type=1400 audit(1445529993.672:76): avc: denied { getattr } for pid=5394 comm="sh" path="/dev/pts/5" dev="devpts" ino=8 scontext=u:r:system_app:s0 tcontext=u:object_r:untrusted_app_devpts:s0:c512,c768 tclass=chr_file permissive=0
[ 508.008677] type=1400 audit(1445529993.672:77): avc: denied { ioctl } for pid=5394 comm="sh" path="/dev/pts/5" dev="devpts" ino=8 ioctlcmd=5401 scontext=u:r:system_app:s0 tcontext=u:object_r:untrusted_app_devpts:s0:c512,c768 tclass=chr_file permissive=0
[ 508.008922] type=1400 audit(1445529993.672:78): avc: denied { getattr } for pid=5394 comm="sh" path="/dev/pts/5" dev="devpts" ino=8 scontext=u:r:system_app:s0 tcontext=u:object_r:untrusted_app_devpts:s0:c512,c768 tclass=chr_file permissive=0
[ 508.009156] type=1400 audit(1445529993.672:79): avc: denied { read } for pid=5394 comm="sh" path="/dev/pts/5" dev="devpts" ino=8 scontext=u:r:system_app:s0 tcontext=u:object_r:untrusted_app_devpts:s0:c512,c768 tclass=chr_file permissive=0
I guess it's acceptable to whitelist all contexts access to untrusted_app_devpts, since we still have unix permissions... ? (only problem would be with dac_override)
Or su daemon could whitelist on-the-fly, when su --context XXXX is called.
This is an interesting one, running --context u:r:su:s0 yields root, then running "dumpsys power" it spits out this;
[ 690.664395] type=1400 audit(1445530176.322:80): avc: denied { read write } for pid=5679 comm="dumpsys" path="/dev/pts/5" dev="devpts" ino=8 scontext=u:r:system_server:s0 tcontext=u:object_r:untrusted_app_devpts:s0:c512,c768 tclass=chr_file permissive=0
Note that that is from system_server, which I wasn't expecting to see.
Can it be whitelisted on the fly without reloading the policy? If possible, it would be nice to be able to block policy reloads like google has it, since one bad application could, in theory, completely destroy the security of the device if it is able to obtain that kind of access.
Hmm, looks like the auto transition isn't happening from untrusted_app.
u:r:untrusted_app:s0:c512,c768 u0_a124 6773 6083 su
May have something to do with the categories?
Edit: note that I am actually using a restorecon on the su binary and auto transitions.
No, you obviously need to reload policy to whitelist, that's the problem. My guess is google no longer has the ability to reload policy, since they removed load_policy from every context.
What do you get in audit log?
Nothing at all in the audit log regarding the transition.
Do you have any dontaudit in your policy?
Default policy is loaded with dontaudit's. I'm looking at them right now.
May not actually be correct that the auto transition isn't working. Looks like some of these things aren't actually reported from ps -Z.
For instance, from adb, I ran "su --context u:r:system_app:s0", yet from a different adb, it still shows as u:r:su:s0, but when I run things from the one on system_app, it appears to be restricted to system_app anway.
# ps -Z
LABEL USER PID PPID NAME
u:r:system_app:s0 system 1651 320 com.quicinc.cne.CNEService
u:r:system_app:s0 system 2716 320 com.qualcomm.telephony
u:r:system_app:s0 root 6997 6992 sh
u:r:system_app:s0 root 7110 6997 ps
Mind you, the su daemon does appear to be reported normally after the auto transition.
Can you check you can read /proc/
No such file or directory. Remember that I'm running factory nexus 6 kernel.
Ah, interesting.
su --context u:r:system_server:s0
Cannot execute /system/bin/sh: Permission denied
Which is good. It means that I have, indeed, entered the system_server domain.
sorry I meant /proc/ PID /attr/current
It matches ps -Z
$ grep -rn untrusted_app_devpts *
grep: Android.bp: No such file or directory
grep: bootstrap.bash: No such file or directory
Binary file out/target/product/shamu/root/sepolicy matches
Binary file out/target/product/shamu/obj/ETC/sepolicy_intermediates/sepolicy matches
out/target/product/shamu/obj/ETC/sepolicy_intermediates/policy.conf:3843:type untrusted_app_devpts, fs_type;
out/target/product/shamu/obj/ETC/sepolicy_intermediates/policy.conf:3847:type_transition untrusted_app devpts:chr_file untrusted_app_devpts;
out/target/product/shamu/obj/ETC/sepolicy_intermediates/policy.conf:3851:allow untrusted_app untrusted_app_devpts:chr_file { open getattr read write ioctl };
out/target/product/shamu/obj/ETC/sepolicy_intermediates/policy.conf.dontaudit:3843:type untrusted_app_devpts, fs_type;
out/target/product/shamu/obj/ETC/sepolicy_intermediates/policy.conf.dontaudit:3847:type_transition untrusted_app devpts:chr_file untrusted_app_devpts;
out/target/product/shamu/obj/ETC/sepolicy_intermediates/policy.conf.dontaudit:3851:allow untrusted_app untrusted_app_devpts:chr_file { open getattr read write ioctl };
Binary file out/target/product/shamu/obj/ETC/sepolicy_intermediates/sepolicy.dontaudit matches
I'm inclined to open that up to everything. Its already opened up to the least trustworthy domain in existence, untrusted_app...
Which actually makes sense, since it's the app who creates it -_-'
Right.
allow domain untrusted_app_devpts:chr_file { open getattr read write ioctl };
Probably can narrow that down at some point.
Hmm, well closer now... If I don't set the context, or leave the context alone, I can now successfully run "dumpsys power" from terminal emulator. If I set the context to system_app, it dies with this;
<36>[ 126.161802] type=1400 audit(1445535147.549:72): avc: denied { getattr } for pid=4741 comm="sh" path="/dev/pts/3" dev="devpts" ino=6 scontext=u:r:system_app:s0 tcontext=u:object_r:untrusted_app_devpts:s0:c512,c768 tclass=chr_file permissive=0
<36>[ 126.162859] type=1400 audit(1445535147.549:73): avc: denied { getattr } for pid=4741 comm="sh" path="/dev/pts/3" dev="devpts" ino=6 scontext=u:r:system_app:s0 tcontext=u:object_r:untrusted_app_devpts:s0:c512,c768 tclass=chr_file permissive=0
<36>[ 126.178793] type=1400 audit(1445535147.569:74): avc: denied { dac_override } for pid=4741 comm="sh" capability=1 scontext=u:r:system_app:s0 tcontext=u:r:system_app:s0 tclass=capability permissive=0
<36>[ 126.194515] type=1400 audit(1445535147.579:75): avc: denied { write } for pid=4741 comm="sh" path="/dev/pts/3" dev="devpts" ino=6 scontext=u:r:system_app:s0 tcontext=u:object_r:untrusted_app_devpts:s0:c512,c768 tclass=chr_file permissive=0
<36>[ 126.194667] type=1400 audit(1445535147.579:76): avc: denied { read } for pid=4741 comm="sh" path="/dev/pts/3" dev="devpts" ino=6 scontext=u:r:system_app:s0 tcontext=u:object_r:untrusted_app_devpts:s0:c512,c768 tclass=chr_file permissive=0
I'm thinking that system_app may not be a member of domain... if that makes any sense...
Yep, appdomain. Still not working though.
Its the category.
I don't know why it works with system_server and not system_app, but when I use --context "u:r:system_app:s0:c512,c768" it works beautifully -- except for dac_override, for which I don't see any pressing need to permit.
I'm pretty sure that the auto transition is failing on the same category issue.
Ok thanks. I know pretty much nothing about categories, I'll try to understand what those are. (I guess that here it's used to separate apps from others?)
From what I can tell, they seem to, at least on Android, be set universally to c512,c768. As I understand it, this actually implies c0,c512,c768
That is, when they are set to anything besides nothing at all. Nothing at all implies c0.
Ok, from what I'm reading ( https://wiki.gentoo.org/wiki/SELinux/Tutorials/SELinux_Multi-Level_Security ), categories are totally orthogonal to other parts of SELinux, and if two systems doesn't share a common category, they can't communicate. So I guess just setting c512 would be enough? (or 768)
Should be. Or a range c0.cwhatever.
Heh, sit here bashing my head against a wall for an hour trying to figure out why something isn't working and there's no audit message... two lines up an execv. Duh.
Yeah, there we are. Now I have it starting in enforcing, rather than switching there after booting.
FYI: I tried out the categories a bit, and turns out they work on an AND basis.
So if the resource you want to access has c512,c768, you need to match them both. Looks like it has to match precisely also, so throwing in a c123 along with the other two doesn't work.
I think that the category problem might be with just terminal emulator. Reason it seems that way is that I have another program I wrote that disables and kills some services on bootup, which has to use the same system_app context (well maybe it doesn't have to any more...) but doesn't have the problem with the pts. It just works without complaint.
I've updated my patch here: https://github.com/lbdroid/AOSP-SU-PATCH
There is one additional change that will be necessary for running restorecon from a script, if you notice line 104 of the patch, it is necessary to authorize init for relabelto su_exec.
Current state is: enforcing, with policy reload disabled.
The policy patches, FOR USERDEBUG are pretty straightforward. I'll have a look at user build policies tomorrow.
This is the actual request window;
[ 4208.208968] type=1400 audit(1445560975.200:36): avc: denied { write } for pid=15987 comm="Thread-745" name=".socket15976" dev="tmpfs" ino=107615 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:device:s0 tclass=sock_file permissive=0
[ 4215.717367] type=1400 audit(1445560982.710:37): avc: denied { getattr } for pid=14729 comm="ruser:superuser" path="/dev/com.koushikdutta.superuser/.socket15976" dev="tmpfs" ino=107615 scontext=u:r:untrusted_app:s0:c512,c768 tcontext=u:object_r:device:s0 tclass=sock_file permissive=0
This appears to be an instance of creating a socket, which inherits its parent's context, and then being locked out as a result.
# Sockets under /dev/socket that are not specifically typed.
neverallow appdomain socket_device:sock_file write;
This might be a good application for a filetrans_pattern rule.
Edit... no, that wouldn't do it, would it... I mean that neverallow rule doesn't really have the implication that it prevents device:sock_file
Its another problem with these stupid categories. u:r:untrusted_app:s0:c512,c768 u:r:foo:s0 Even when there is an allow rule for untrusted_app --> foo, foo is category c0 u:r:foo:s0 == u:r:foo:s0:c0 But because u:r:untrusted_app:s0:c512,c768 explicitely does NOT include c0, it therefore can't access the resource with label foo.
Also unfortunate thing... categories don't appear to inherit from their parent.
There might be a better way to do this; have an android/java service listening for connections from the su client binary, rather than the su binary waiting on the application to call it back. It can still be launched with an am start.
Or an easier way...
mlstrustedobject = ignore category when dealing with this object. mlstrustedsubject = ignore this process's category always.
I added to the sepolicy as follows;
type su_device, dev_type, mlstrustedobject; allow untrusted_app su_device:sock_file rw_file_perms; allow untrusted_app su_device:dir rw_file_perms; allow untrusted_app su_device:dir r_dir_perms; (I think the dir rw_file_perms is probably unnecessary)
And then chcon u:object_r:su_device:s0 on /dev/{the su client's path}
Then the auth window started working.
filetrans_pattern(unconfined_t, admin_home_t, dir, ssh_home_t, “.ssh”)
first param: calling process context (should be untrusted_app), second param: parent directory context (/dev is u:object_r:device:s0), third param: type of object being created (dir is correct), fourth param: new context to apply to the directory (u:object_r:su_device:s0), fifth param: the name of the what is being created, which seems to come from the package name.
I'm having no luck with the auto transitions. I'm thinking that I may have the calling process context wrong.
Ah, I get it... its not untrusted_app, its actually making the transition as su...
Working, and its actually better not to use a name pattern in this case, since we can transition using file_type_auto_trans(su, device, su_device)
From what I can tell, the difference between 5.x and 6.0 basically involve a tightened up sepolicy. Specifically (and most likely), things like https://android.googlesource.com/platform/external/sepolicy/+/356df32778732aa576e15071bf2736fbbd778b77%5E!/#F0
The evil closed source supersu has implemented a sepolicy patcher in their "supolicy" command. It takes the factory sepolicy file and generates a "patched" sepolicy that works with the rest of their code. HOWEVER, they refuse to even document the changes they are making to the sepolicy, which makes it impossible to trust them.
It is likely that a similar policy patch will be required. It should be possible to build it into an update zip that can repack the boot.img similar to things like http://forum.xda-developers.com/nexus-6/development/fix-fed-patcher-forceencrypt-disable-t3203867
I also suggest that consideration should be made to having the entire su system (save for the android apk) made part of the boot.img rather than breaking dmverity on the system partition. Since the boot.img will require modification either way, it is trivial to add the rest in there. Possibly even simplifies the process, since there are other hijacks made available for obtaining the init context from the boot.img.