Stack!
This my first question on this, so don't be too hard with me.
I want to run my own .sh script file on boot my android. To get this I rebuild kernel image and before that I add to init.rc file my own service which start after boot complete trigger:
on property:dev.bootcomplete=1
start fota-snoop
start fota-trigger
start startup-prober
start fairnet
the service itself:
service fairnet /system/bin/sh /system/etc/init.fairnet.sh
user root
group root
disabled
oneshot
permissions of /system/etc/init.fairnet.sh is set 644 like others init .sh scripts, and owner is root:root :
-rw-r--r-- root root 280 2018-01-09 01:03 init.fairnet.sh
init.fairnet.sh:
#!/system/bin/sh
insmod /system/lib/modules/xt_HL.ko
lsmod > /system/etc/curlsmod
/system/bin/iptables -t mangle -L > /system/etc/preiptables
/system/bin/iptables -t mangle -A POSTROUTING -o rmnet+ -j TTL --ttl-set 64
/system/bin/iptables -t mangle -L > /system/etc/postiptables
the most funny thing is command of load kernel module works fine, on boot too, but the other strings don't works: output files didn't exist, rule for iptables didn't add. I can't understand why insmod works and other commands don't.
Thanks for reading and sorry for my terrible English.
Problem solved!
SELinux blocked iptables in boot.
dmesg | grep iptables
gives me
<36>[ 39.819005] type=1400 audit(1516096993.541:9): avc: denied { create } for pid=2652 comm="iptables" lport=255 scontext=u:r:init_shell:s0 tcontext=u:r:init_shell:s0 tclass=rawip_socket op_res=-13 ppid=2640 pcomm="sh" tgid=2640 tgcomm="sh"
that means in current /sepolicy don't have rule i need.
For adding that rule i use sepolicy-inject, for build it need /usr/lib/libsepol.a, libsepol1-dev contains it. Also may use builded binaries for all archs (don't work for me, I build my own).
./sepolicy-inject -s init_shell -t init_shell -c rawip_socket -p getopt,create,setopt -P sepolicy -o sepolicy_new
add needed rule and make new sepolicy_new from old sepolicy from device.
Flash device with new sepolicy with new boot.img, I use AIK for Win.
Done! Now after boot my .sh script automatically runs and fully.
Thanks for reading and again sorry for my terrible English.
P.S. My own service I replaced from init.sony.rc to init.qcom.rc, also removed group root and disabled, but I done it only for ideological reasons and that not solve problem.
P.P.S. Change mode from Enforced to Permissive may do the thing, but I don't want to lost SELinux.
Related
At my first thought, I should know how to check the permissions of a folder in the Linux system(since the kernel of Android is linux) by C or C++.
Since C++17 is not available for me, so std::filesystem could not be used. And I searched on SO, I found access may be a solution. So I wrote the code snippet below:
if (access(folder_path, W_OK | X_OK) == 0) {
SDK_LOG_ERROR("folder is not writable");
}
But it seems not work as expected, I can manually create new files in a specific folder:
C:\tools>adb root
adbd is already running as root
C:\tools>adb remount
remount succeeded
C:\tools>adb shell
promotion:/system/etc/some_folder/.../config # ls -lhd .
drwxrwxrwx 2 root root 4.0K 2022-05-31 21:14 .
promotion:/system/etc/some_folder/.../config # touch a
promotion:/system/etc/some_folder/.../config # touch b
promotion:/system/etc/some_folder/.../config # ls -lh
total 14K
-rw-rw-rw- 1 root root 0 2022-05-31 21:14 a
-rw-rw-rw- 1 root root 0 2022-05-31 21:14 b
Before running the said code snippet, I call adb root; adb remount first, and then I call whoami in the terminal, the output is root.
But when I run the aforementioned code snippet on Android, the program tells me folder is not writable". What a surprise!
I am facing troubles for creating the SELinux policies for a sh script (init.myservice.sh) with the following content:
#!/system/bin/sh
/system/bin/am force-stop 'com.myapp.apptest'
/system/bin/tinymix 'Headphone Volume' 35;tinymix 'Capture Input' ADC;tinymix 'DMIC Mux' DMIC2;
/system/bin/am start -n ' com.myapp.apptest/ com.myapp.apptest.MainActivity' -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
/system/bin/my_board_service &
As you can see, this script does the following things:
Stops (and starts) a APK application
Sets few mic and audio settings with tinymix
Starts a binary (my_board_service) which is a C++ compiled program which interacts with the custom board peripherals (GPIOs, I2C, etc...)
I've added into my "init.rc" file the following lines:
on property:sys.boot_completed=1
start init-myservice
service init-myservice /system/bin/sh /system/bin/init.myservice.sh
class main
user root
group root system
disabled
oneshot
I can see the script in the built system under the path "/system/bin" and the binary with the correct permissions (755) and if I launch it manually it works well. But I'm unable to launch it at system boot because (without any policies set) I get this error on the shell:
Command 'start init-myservice' action=sys.boot_completed=1
(/vendor/etc/init/hw/init.freescale.rc:334) took 5ms and failed: Could
not start service: File /system/bin/init.myservice.sh(labeled
"u:object_r:system_file:s0") has incorrect label or no domain
transition from u:r:init:s0 to another SELinux domain defined. Have
you configured your service correctly?
https://source.android.com/security/selinux/device-policy#label_new_services_and_address_denials
So I'm trying to generate service policies without any luck. I've tried the following:
The content of my .te file is the following:
# foo service
type foo, domain;
type foo_exec, exec_type, file_type;
init_daemon_domain(foo)
I've added the following line in the "file_contexts" file under this location: "android_build/device/variscite/imx8m/dart_mx8mm/sepolicy/"
/system/bin/init\.myscript\.sh u:object_r:foo_exec:s0
When I build my AOSP project I get few errors like this one:
FAILED:
out/target/product/dart_mx8mm/obj/ETC/treble_sepolicy_tests_28.0_intermediates/treble_sepolicy_tests_28.0
/bin/bash -c "(out/host/linux-x86/bin/treble_sepolicy_tests -l
out/host/linux-x86/lib64/libsepolwrap.so -f
out/target/product/dart_mx8mm/obj/ETC/plat_file_contexts_intermediates/plat_file_contexts
-f out/target/product/dart_mx8mm/obj/ETC/vendor_file_contexts_intermediates/vendor_file_contexts -b out/target/product/dart_mx8mm/obj/ETC/built_plat_sepolicy_intermediates/built_plat_sepolicy
-m out/target/product/dart_mx8mm/obj/ETC/treble_sepolicy_tests_28.0_intermediates/28.0_mapping.combined.cil
-o out/target/product/dart_mx8mm/obj/ETC/treble_sepolicy_tests_28.0_intermediates/built_28.0_plat_sepolicy
-p out/target/product/dart_mx8mm/obj/ETC/sepolicy_intermediates/sepolicy
-u out/target/product/dart_mx8mm/obj/ETC/built_plat_sepolicy_intermediates/base_plat_pub_policy.cil
--fake-treble ) && (touch out/target/product/dart_mx8mm/obj/ETC/treble_sepolicy_tests_28.0_intermediates/treble_sepolicy_tests_28.0
)" The following domain(s) must be associated with the "coredomain"
attribute because they are executed off of /system: foo
I recently was able to get what you are describing to work, but there were some differences in our approaches. All of my changes were in "/vendor" on the target. I'm not sure where your init.rc changes were going, but you described your script as being installed in "/system".
Otherwise most of what you are describing is familiar including having issues compiling the SELinux policy. In the end the policy that worked for me looked something like this:
# foo service
type foo, domain;
type foo_exec, exec_type, vendor_file_type, file_type;
init_daemon_domain(foo)
# followed by all the particulars of my service.
If you are set on installing your service in "system" instead of "vendor", the wording of the error message seems to be telling you to associate your domain with the "coredomain". I think that means your policy should include the following line somewhere before "init_daemon_domain":
typeattribute foo coredomain;
You should also be aware that I've seen it said that there is a SELinux policy that prohibits mixing "vendor" with "system". I'm not sure, but I think it means that if you modified an init.rc in the /vendor file system to run your script, you are limited to using "stuff" found in the /vendor file system. Your example above shows your script using /system/bin/sh, so if you modified an init.rc in the /vendor file system to start that script, I think that would be a violation.
I want to run a service on few tablets (VONINO NAVO P) that they will serve as a photo frame for digital ads.
What i'm trying to achieve is to run some commands at boot and i'm stuck.
I have created digitalads.rc in system/etc/init which will execute /system/bin/digitalads.sh from where i need to run some commands like:
svc power stayon true
settings put system screen_brightness 255
pm disable com.android.systemui
settings put system screen_off_timeout 999999999
settings put system accelerometer_rotation 0
settings put global airplane_mode_on 0
svc bluetooth disable
monkey -p my.app -c android.intent.category.LAUNCHER 1
and some other custom commands that they will update the contents of media files
my .rc file:
tulip-f708:/ # cat /system/etc/init/digitalads.rc
service digitalads /system/bin/digitalads.sh
disabled
user root
group root
u:object_r:system_file:s0
on property:sys.boot_completed=1
start digitalads
dmesg output
tulip-f708:/ # dmesg | grep digitalads
[ 6.512868] init: /system/etc/init/digitalads.rc: 5: invalid keyword 'u:object_r:system_file:s0'
[ 6.522694] init: (Parsing /system/etc/init/digitalads.rc took 0.01s.)
[ 44.546434] init: Service digitalads does not have a SELinux domain defined.
SElinux output
tulip-f708:/ # getenforce
Enforcing
tulip-f708:/ # setenforce 0
tulip-f708:/ # getenforce
Permissive
other services run under u:object_r:system_file:s0
tulip-f708:/ # ls -Z /system/bin/
u:object_r:system_file:s0 4d78d2ea-a631-70fb-aaa787c2b5773052.ta
u:object_r:system_file:s0 a98befed-d679-ce4a-a3c827dcd51d21ed.ta
u:object_r:system_file:s0 acpi
u:object_r:system_file:s0 am
u:object_r:system_file:s0 app_process
u:object_r:zygote_exec:s0 app_process32
u:object_r:zygote_exec:s0 app_process64
u:object_r:system_file:s0 applypatch
u:object_r:system_file:s0 appops
u:object_r:system_file:s0 appwidget
u:object_r:system_file:s0 arping
.............................
I also tried to unpack boot.img to modify init.rc but failed when put it back (bricked two of them). Not mention that to root them i had to contact the manufacturer directly...
Some hints would help me! Thx
It seems your .rc files misses the seclabel keyword. Your service declaration should look like this:
service digitalads /system/bin/digitalads.sh
disabled
user root
group root
seclabel u:object_r:system_file:s0
Edit regarding your SE Linux violation: The message says that init cannot start a program labelled with system_file. That means you have to modify the SE Linux rules. The best approach would be to add a new label specific to your service:
Identify the folder where you want to add your policy. This is somewhat specific to your setup, so I cannot give you a definite answer. Check for .te files in your source code. The core Android policies are in system/sepolicy/, but if your setup has special SE policies somewhere in devices/ or vendor/, these location would be better suited for your customization (because it makes it easier for your to update to a new Android version when your customizations are as isolated as possible).
In that folder, create a new policy file, e.g. digitalads.te. Add the following rules:
type digitalads_exec, system_file_type, exec_type, file_type;
type digitalads domain;
init_daemon_domain(digitalads)
In the same folder, there should be a file file_contexts: Add a line like
/system/bin/digitalads u:object_r:digitalads_exec:s0
(When you boot with this change, ls -Z /system/bin/digitalads should show this label.)
For the seclabel in your .rc file, replace system_file with digitalads.
(Check dmesg output and also ps -Z to verify your service has been labelled correctly.)
I am trying to log to a file from custom shell script started as service using init.project.rc. On using below lines in the script(ethmon.sh), i am unable to log it to file test.txt. It is not even creating the file. Any hints on this?
ethmon.sh
mkdir /data/local/tmp/test 2>/dev/null
echo "Issue Observed with IP at `date`" >> /data/local/tmp/test/test.txt
dmesg >> /data/local/tmp/test/test.txt
timeout -t 10 logcat -v time -f /data/local/tmp/test/logcat.txt
init.project.rc
service ethmon /system/xbin/ethmon
class main
user root
group root
oneshot
on property:dev.bootcomplete=1
start ethmon
preload_script.sh
cp -f $SOURCE_FOLDER/ethmon.sh $OUT/system/xbin/ethmon
I am new to aosp, am i missing some permissions to be added for this.
NOTE: Other lines of code(ifconfig eth0 down/up, netcfg) is working fine in the same script.
Finally i added selinux permissions and created .te file for my service to get the log thing working. Thanks https://stackoverflow.com/users/12098405/dash-o for the help. People with same issue can comment for any further information.
I want to create a encrypting filesystem by encfs(Android's FDE or FBE can't encrypt single directory),but it doesn't work well when I execute the command by local shell(JuiceSSH):
encfs --no-default-flags --public --stdinpass /data/home/MediaStore-e /data/media/0/MediaStore -- -o uid=1023,gid=1023,umask=002 #1023 is media_rw's ID
Only JuiceSSH can access the /data/media/0/MediaStore what I want instead of the old directory(in other words,the true MediaStore).And the other applications(not only Java applications,and also adb etc.) don't think it is a mountpoint:
adb shell
shell#oneplus3:/ $ su
shell#oneplus3:/ # mountpoint /data/media/0/MediaStore
shell#oneplus3:/ # /data/media/0/MediaStore is not a mountpoint
In local shell(JuiceSSH):
oneplus3 ~ # mountpoint /data/media/0/MediaStore
oneplus3 ~ # /data/media/0/MediaStore is a mountpoint
And /system/bin/sdcard(the application which provides /storage/emulated/) can't access it,so I can't read my data from /storage/emulated/0/MediaStore.
But If I execute the command above by adb,it will work well.
I use this script to find the processes which know the directory is a mountpoint:
for dir in /proc/*;do
if [ -e $dir/mounts ];then
if grep -q MediaStore $dir/mounts;then
cat $dir/cmdline
echo
fi
fi
done
When I run encfs --no-default-flags --public --stdinpass /data/home/MediaStore-e /data/media/0/MediaStore -- -o uid=1023,gid=1023,umask=002 by local shell,the script print this:
com.sonelli.juicessh
/data/user/0/com.sonelli.juicessh/files/bin/arm/pie/bash--rcfile/data/user/0/com.sonelli.juicessh/files/share/bashrc
su0-c/data/data/com.sonelli.juicessh/files/bin/arm/pie/bash--rcfile/data/home/.bashrc
/data/data/com.sonelli.juicessh/files/bin/arm/pie/bash--rcfile/data/home/.bashrc
/data/bin/encfs--no-default-flags--public--stdinpass/data/home/MediaStore-e/data/media/0/MediaStore---ouid=1023,gid=1023,umask=002
When I do that by adb,it prints so many lines that I can't put them here,but almost all processes are in them.And other applications (such as music player)can access the data what I want.
The adb shell and local shell run as the same user and group,and own the same secure context(u:r:su:s0),I even tried to clear environment variables,and setenforce 0,I got the same result as before.How can I fix it?I can't use adb to do it every time I reboot.
I have solved this problem by myself,so I answer myself question to share my solution.
This reason why other processes can't access the mount tree what I want is than they are in different mount namespace.ADB's name space is same as /sbin/init,but JuiceSSH(or other terminal application created by zygote64) is in another mount namespace create by clone(2),so you can't access the mount tree by other application even as root.
Solution:
1.
If your su supports --mount-master option,just use it.
2.
Write a shell script which was executed by /system/bin/sysinit * on boot,so it is in the same mount namespace as init(1).It read commands from a FIFO and excute it.It is like this:
#!/system/bin/sh
mknod /data/.global_fifo p
while true;do
eval "$(cat /data/.global_fifo)"
done
Don't forget set correct mode and secure context for it.
sysinit is a application,it execute /system/etc/init.d/* just like most of linux distribution,it was installed on cyanogenmod 13.0.You can write one by yourself and add it into /init.rc.)