SElinux domain transition for non-init process/files ( Android Natvie ) - android

I'm writing Android Native programs and setting their SEPolicy
I want to know how to set the process context for non-init program, it seems that the domain transition doesn't work
I wrote 2 programs and put the built executable in /vendor/bin
One program, my_service is running as init daemon service;
While the other one, my_client is a non-init program, which has to be executed manually
These 2 programs use Binder IPC to communicate.
But I have trouble when trying to set the process context for my_client, which is a non-init program
For my_service, it's selinux context is set in mainly 2 files
my_service.te
file_context
# In file_context
/vendor/bin/my_service u:object_r:my_service_exec:s0
# In my_service.te
type my_service, domain;
type my_service_exec, exec_type, file_type, vendor_file_type;
init_daemon_domain(my_service)
And I also use seclabel in init.rc files
# In init.rc
service my_service /vendor/bin/my_service
class main
console
seclabel u:r:my_service:s0
I checked both file context and process context for my_service, and they're set as what I expected
For the SEPolicy of my_client, everything is similar to my_service except that it is not written in the init.rc file since it's not an init program
# In file_context
/vendor/bin/my_client u:object_r:my_client_exec:s0
# In my_client.te
type my_client, domain;
type my_client_exec, exec_type, file_type, vendor_file_type;
init_daemon_domain(my_client)
For my_client, however, only file context is set to my_client_exec
I tried to run my_client and viewed the process context:
> # Executing my_client manually
> /vendor/bin/my_client
> ps -AZ | grep my_client
> u:r:su:s0 root 5838 5514 5948 1688 0 0 R my_client
The process context is su, while I expected it to be my_client
Furthermore, I get information about init_daemon_domain(XX) in te_macros
I think that It will do domain transition: When init runs file with XX_exec context, it will transit its process context to XX!
So I change the rule to be :
# init_daemon_domain(my_client)
domain_auto_trans(su, my_client_exec, my_client);
But this violate some pre-defined policy.
By the way, the binder IPC between these 2 programs seems working.
What's confusing is that the following rules still works even the process context is not my_client ?
binder_call(my_client, my_service)
binder_call(my_service, my_service)
Is there any way to do domain transition for non-init program ?
Or I misunderstand anything about SEPolicy? Because all the resources I found are about setting SEPolicy for init program

Related

Declare service in AOSP

As part of a training course I need to declare a service in AOSP and call it at boot. The thing is the training is outdated, I'm working on a physical machine and the project is different.
Specs:
Android Version: 12
Android SDK: 31
Anyway I've built a module in C called "exd", it's stored in /system/bin/ and it works properly when called manually. Next I want to declare it as a service.
I've added to init.product.rc file:
service exd /system/bin/exd
oneshot
on boot
start exd
But when I build and download it to the device, service list doesn't display it. And it doesn't start on boot.
Next I've added exd.te file to sepolicy folder:
type exd, domain;
type exd_exec, domain;
init_daemon_domain(exd)
And added this line to file_contexts:
/system/bin/exd u:object_r:exd_exec:s0
When I call build it fails with the following message:
Error while expanding policy
[ 39% 60/151] //system/sepolicy:sepolicy.recovery Compiling cil files for sepolicy.recovery [common]
FAILED: out/soong/.intermediates/system/sepolicy/sepolicy.recovery/android_common/sepolicy
out/host/linux-x86/bin/secilc -m -M true -G -c 30 out/soong/.intermediates/system/sepolicy/recovery_sepolicy.cil/android_common/recovery_sepolicy.cil -o out/soong/.intermediates/system/sepolicy/sepolicy.recovery/android_common/sepolicy_policy -f /dev/null && cp -f out/soong/.intermediates/system/sepolicy/sepolicy.recovery/android_common/sepolicy_policy out/soong/.intermediates/system/sepolicy/sepolicy.recovery/android_common/sepolicy && rm -f out/soong/.intermediates/system/sepolicy/sepolicy.recovery/android_common/sepolicy_policy # hash of input list: 187605db6ee3f7580bafd9adbd0101d2c2a0d02f423bb7efa74ee537c43d35ce
neverallow check failed at out/soong/.intermediates/system/sepolicy/recovery_sepolicy.cil/android_common/recovery_sepolicy.cil:8770 from system/sepolicy/public/domain.te:1240
(neverallow base_typeattr_197 domain (file (execute execute_no_trans entrypoint)))
<root>
allow at out/soong/.intermediates/system/sepolicy/recovery_sepolicy.cil/android_common/recovery_sepolicy.cil:28846
(allow init exd_exec (file (read getattr map execute open)))
<root>
allow at out/soong/.intermediates/system/sepolicy/recovery_sepolicy.cil/android_common/recovery_sepolicy.cil:28848
(allow exd exd_exec (file (read getattr map execute open entrypoint)))
Failed to generate binary
Failed to build policydb
10:35:34 ninja failed with: exit status 1
I've tried everything I've found on the internet to no avail. The weird thing is that there is another service called "bugreport" which is declared almost indetically as mine, but it is listed after "service list" command.
At this point even pointing a good direction would be great for me.
You are getting neverallow, which is basically Android saying you are trying to do something that is not allowed in the SEPolicy definition. You need to create a .te file that consists of SEPolicy rules for your service.
An example SEPolicy file can be as follows:
type myservice_exec, exec_type, file_type, system_file_type;
typeattribute myservice coredomain;
# myservice servicemanager and binder access
allow shell myservice:binder { call transfer };
allow servicemanager myservice:dir search;
allow servicemanager myservice:file { open read };
allow servicemanager myservice:process getattr;
allow myservice servicemanager:binder { call transfer};
allow myservice system_server:binder call;
init_daemon_domain(myservice)
Notice the second line. You are missing that and it is most probably why you are getting a neverallow problem.

Android Init startup - Ueventd and watchdogd

I'm a beginner and I'm trying to understand the Kernel-Android interface.
In the system/core/init/init.c, the initial part has the following code.
if (!strcmp(basename(argv[0]), "ueventd"))
return ueventd_main(argc, argv);
if (!strcmp(basename(argv[0]), "watchdogd"))
return watchdogd_main(argc, argv);
This is followed by the parsing of the board specific init.rc files.
The ueventd_main parses the board specific uevent.rc files.
The watchdogd_main tries to set the timeout & then keeps writing an empty character to the /dev/watchdog in an infinite loop.
In the book 'Embedded Android' by Karim Yaghmour, it is mentioned as,
One of the first things init does is check whether it was invoked as
ueventd. init includes an implementation of the udev hotplug events
handler. Because this code is compiled within init’s own code, init
checks the command-line that was used to invoke it, and if it was
invoked through the /sbin/ueventd symbolic link to /init, then init
immediately runs as ueventd.
My questions are
1) I believe that the arguments to this main function are received from kernel bootcmd parameters "init=". Am I right?
2) Under what scenario one would invoke an init to be run only as ueventd or watchdogd?
3) What do they mean by symbolically linked to /init?
1) I believe that the arguments to this main function are received
from kernel bootcmd parameters "init=". Am I right?
No, not bootcmd arguments. argv[0] is the name of the executable being launched.
If you look at the Android.mk for init, you will see:
# Create symlinks.
LOCAL_POST_INSTALL_CMD := $(hide) mkdir -p $(TARGET_ROOT_OUT)/sbin; \
ln -sf ../init $(TARGET_ROOT_OUT)/sbin/ueventd; \
ln -sf ../init $(TARGET_ROOT_OUT)/sbin/watchdogd
Here you can see that two extra symbolic links are created, both pointing to init. These will be included in the final Android boot image in /sbin/
2) Under what scenario one would invoke an init to be run only as
ueventd or watchdogd?
In init.rc, you can see:
## Daemon processes to be run by init.
##
service ueventd /sbin/ueventd
class core
critical
seclabel u:r:ueventd:s0
shutdown critical
This is declaring the service ueventd and specifying a path to the ueventd path. So when the ueventd service is started, it will the the init executable but the argv[0] argument will be ueventd.
watchdogd is done the same way.
So it is the same executable called with three different names init, ueventd, or watchdogd. Depending on which name it is called with, one of three different code paths are executed (as in the code you referenced).
This is often done when different commands are substantially the same in implementation. On my Ubuntu system:
$ ls -l /usr/bin/unxz
lrwxrwxrwx 1 root root 2 Oct 3 11:04 /usr/bin/unxz -> xz
You can see that unxz is linked to xz
From the man page for xz: unxz is equivalent to xz --decompress.
So here, there was only one executable, but depending on which executable name is used to launch it, the behavior is different.
3) What do they mean by symbolically linked to /init?
Answered in previous two answers.

debug.log for XposedBridge?

I currently work on an application with XposedBridge and I have a lot of questions. I will start with the simple ones.
How can I get the debug.log file?
I cannot find the debug.log file. I have tried the phone shell as well as two adb ways :
A. adb shell data/data/de.robv.android.xposed.installer/log/debug.log
B. adb shell "su -c 'cat data/data/de.robv.android.xposed.installer/log/debug.log'"
C. adb shell cat data/data/de.robv.android.xposed.installer/log/debug.log
adb says : " No such file or directory "
The phone shell can cd to /data and /data/data but not after. Cannot ls neither of the data's. Says access denied. So does adb when I try adb ls.
The phone, Moto E XT1023, is rooted. Despite, shell cannot read some directories. I have posted a question why here but no one seems to care to answer.
I had to go to ES File Explorer. Managed to get to /data. ES says folder empty. Managed to get to Emulator/0/de.robv.android.xposed.installer or something alike. There was a subdirectory called files. Inside was the installer. No debug.log.
Searched all directories with ES for debug.log. Nothing found.
Once I create the XposedBridge class in a separate file of the project and once I do whatever XposedBridge is supposed to do (override methods, insert code before and or after the methods, etcetera) the overridden methods or the methods with code run before and or after or the overridden data will continue to be overridden until the app exits. Is this true?
Is there any simple, yet powerful and comprehensive manual or reference or, the best, a tutorial?
Can I specify another directory for the debug.log.file?
In case I am able to make a directory \data\data manually, would this make the Xposed save debug.log there?
I am so happy I have managed to partially answer the first question which is not only related to XposedBridge but is a global root reach question for rooted phones, so I cannot even think of any other questions for now. I do not have a debug.log but I have error.log and I know how to read these. Here is how in case anyone is interested :
In order to be able to reed XposedBridge log files :
Go to the specialised Moto E adb ( may work with a standard one too ).
Type :
************
* adb root *
************
to ensure root access.
The Dollar Sign $ must appear as the sign before commands. $ means the adb shell environment has been entered.
After $, type :
******
* su *
******
The Sharp Sign # must appear as the sign before commands. # means root has been entered. Once root has been entered, there is a full access to the phone. Thus :
**************************************************
* cd /data/data/de.robv.android.xposed.installer *
**************************************************
can be executed and the directory /data/data/de.robv.android.xposed.installer will be entered.
Type :
******
* ls *
******
to see the contents of this directory.
In case error.log or debug.log files are there, type :
*****************
* cat error.log *
*****************
and or
*****************
* cat debug.log *
*****************
to view these files.
Type :
********
* exit *
********
to return to the safer $ prompt.
Type :
********
* exit *
********
to exit adb.
Note : adb root may not run while a project is developed. The rest works, though.
I still do not have any debug.log. May be the XposedBridge lines do not run. Will check with some simple method from the manual.
Here is what I have found out, though. I have created an empty text file called debug.log on the computer and transferred the file to the main root of the device, the /sdcard directory, themn copied the file to /data/data/de.robv.android.xposed.installer/log just to see what happens. Nothing happens. The file is empty.
Here is what I have found out which may be helpful:
COMMANDS TO READ THE LOG FILES :
adb shell
su
cd /data/data/de.robv.android.xposed.installer/log
cat error.log
USE cp SOURCE DESTINATION after su shell, the # prompt, to copy files from one
directory to another on the device.
IMPORTANT NOTES :
All Xposed classes must be put in xposed_init, otherwise Android Studio 1.2 reports them as never used.
In built.gradle, have :
/* SSB : Added manually so the gradle builds with the
XposedBridgeApi-54.jar which is in the app -> libs
but not to include the jar in the apk. */
dependencies {
provided fileTree(dir: 'libs', include: ['*.jar'])
}
THESE HAVE BEEN PUT MANUALLY.
Update : I have been able to clean the code and have managed to find why I do not have a debug.log. This is because the two XposedBridge classes I have ( one is initialisation of zygote and the other is the work file with hooks and replacements ) are not loaded. The error.log shows : Didn't find class " package ( strts without a com. ) NameOfThePackageWithoutComDot.NameOfTheExposedClass in the NameOfThePackageWithoutComDot-2.apk "
THIS IS SAID FOR THE TWO CLASSES.
Problem partially solved:
I have removed the string " package " from the xposed_init and this solved the problem. Thus, instead of :
package TheNameOfThePackage.TheNameOfTheClass
xposed_init contains :
TheNameOfThePackage.TheNameOfTheClass
without the word " package " in front of the names as Android Studio usually puts and requires.
Now, the custom class seems to load OK and XMain where zygote is init generates a novel.
Regardless, the custom class with the test code works OK. The debug.log file is generated. However, the application does not seem to write in the file and the debug.log only says :
d.xposed.installer/log/debug.log
inside.

How to completely disable SELinux in Android L in the init.rc file?

I want to disable SELinux at boot time for Android L or 5. The reason is because my daemon is not begin executed on boot when it should due to SELinux problems. I have the following in my init.rc file:
su 0 setenforce 0
service my_daemon /system/bin/my_daemon
class main # Also tried: class core (but it didn't make a difference)
user root
group root
However, on boot, I use adb shell to check if SELinux is disabled (using getenforce) and it returns Enforcing. I want SELinux to be completely disabled on boot. If not completely disabled then at least Permissive.
Any suggestions?
Well I guess you could create a new domain policy for your "my_daemon". For example, you can create mydomain.te file at device/manufacturer/device-name/sepolicy/ of your AOSP, with the following contents,
# mydomain policy here
type mydomain, domain;
permissive mydomain;
type mydomain_exec, exec_type, file_type;
init_daemon_domain(mydomain)
Now Add the following line to device/manufacturer/device-name/sepolicy/file_contexts:
/system/bin/my_daemon u:object_r:mydomain_exec:s0
Here is your init.rc file:
service my_daemon /system/bin/my_daemon
class core
So the good thing here is that only mydomain will be permissive and rest of the system will be enforcing, thus you can have your daemon running without any problems and still maintaining the system security.
Instead of putting in init.rc you can make it permissive by adding some parameters to kernel command line (BOARD_KERNEL_CMDLINE)
Ex: Add enforcing=0 androidboot.selinux=permissive in device/<manufacturer>/<target>/BoardConfig.mk
After
setenforce 0
the enforce attribute will be Permissive imeddiately.

Linux Kernel Dynamic Debug settings - persist across a reset

With Dynamic Debugging enabled in the Linux Kernel, I am able to control which prints show up by writing to /sys/kernel/debug/dynamic_debug/control. However, It seems that a reboot resets this file to its default settings (all prints disabled).
Is there a way to make the settings persist across a reset? I have a print which is emitted early in the boot process, and I am not able to get it to print, because the reboot disables this print in /sys/kernel/debug/dynamic_debug/control.
You should be able to add dyndbg='your query here' to the kernel command line using the bootloader configuration or manual options entry feature. This will vary with the bootloader although grub is the most common one
If you are using grub as a bootloader you would have to add it to the kernel command line in /boot/grub/grub.conf for the particular kernel you are launching at bootup.
A blog article about this can be found here. In particular it gives this example:
dyndbg='module xhci_hcd +p'
The article also discusses modifying grub as well.
This kernel howto about dynamic debugging has useful information about dyndbg. This section applies
To activate debug messages for core code and built-in modules during
the boot process, even before userspace and debugfs exists, use
dyndbg="QUERY", module.dyndbg="QUERY", or ddebug_query="QUERY"
(ddebug_query is obsoleted by dyndbg, and deprecated). QUERY follows
the syntax described above, but must not exceed 1023 characters. Your
bootloader may impose lower limits.
These dyndbg params are processed just after the ddebug tables are
processed, as part of the arch_initcall. Thus you can enable debug
messages in all code run after this arch_initcall via this boot
parameter.
On an x86 system for example ACPI enablement is a subsys_initcall and
dyndbg="file ec.c +p"
will show early Embedded Controller transactions during ACPI setup if
your machine (typically a laptop) has an Embedded Controller.
PCI (or other devices) initialization also is a hot candidate for using
this boot parameter for debugging purposes.
If foo module is not built-in, foo.dyndbg will still be processed at
boot time, without effect, but will be reprocessed when module is
loaded later. dyndbg_query= and bare dyndbg= are only processed at
boot.
You can do it as a part of post boot script. Say after Android boots(since i see Android tag added here), it runs certain sh scripts as a part of init procedure. Modify the sh files with the dynamic debug commands added and push it in and reboot .
Refer here for post boot script files info.
https://android.stackexchange.com/questions/6558/how-can-i-run-a-script-on-boot
You can have dynamic_debug for some kernel module foo activated automatically during boot using the /etc/modprobe.d/ directory.
### BEGIN prerequisite
# in case module "foo" is not yet automatically loaded during boot,
# then make it load during boot:
# create a file /etc/modules-load.d/foo.conf with contents "foo"
echo "foo" | sudo tee /etc/modules-load.d/foo.conf
### END prerequisite
# create a configuration file to activate dynamic debug for module "foo"
# at its "module initialization time"
echo "options foo dyndbg=+p" | sudo tee /etc/modprobe.d/foo.conf
Reference: Debug Messages at Module Initialization Time from kernel.org documentation.

Categories

Resources