How To Guide How to run a script at shutdown - ASUS ZenFone 8

How to run a script at shutdown
To define additional startup scripts via Magisk the Magisk directories /data/adb/service.d and /data/adb/post-fs-data.d can be used. Unfortunately there is no equivalent for scripts that should be executed during shutdown.
So we must use other methods to implement these kind of scripts.
Using the overlay feature of Magisk to run a script at shutdown
Introduction
in Android it is possible to define actions that will be executed when certain conditions are satisfied.
These definitions are done in the file init.rc (and other .rc files) using the Android Init Language.
And this feature can be used to execute a command when the phone is shutting down.
Note:
For details about the Android Init Language used for these files see here https://android.googlesource.com/platform/system/core/+/master/init/README.md
The .rc files used by Android are in the directories
/system/etc/init​/vendor/etc/init​/odm/etc/init​
Note: The first .rc file read is /system/etc/init/hw/init.rc
Unfortunately it's useless to change the .rc files in these directories using the Magisk features to change files in the directory /system because these files are processed by the OS before the new files are "created" by Magisk.
Therefor the overlay functionality from Magisk must be used to create additional .rc files (see the section Root Directory Overlay System on this page https://github.com/topjohnwu/Magisk/blob/master/docs/guides.md for details about this Magisk Feature).
Preparation
To be able to restore the original boot partition in case of an error create an image of the original boot partition from the phone on your PC before starting the development:
Code:
CUR_SLOT=$( adb shell getprop ro.boot.slot_suffix )
adb shell su - -c dd if=/dev/block/by-name/boot${CUR_SLOT} | cat >boot${CUR_SLOT}
e.g.
Code:
[ OmniRomDev - [email protected] /data/develop/android/test ] $ CUR_SLOT=$( adb shell getprop ro.boot.slot_suffix )
[ OmniRomDev - [email protected] /data/develop/android/test ] $ echo ${CUR_SLOT}
_b
[ OmniRomDev - [email protected] /data/develop/android/test ] $
[ OmniRomDev - [email protected] /data/develop/android/test ] $ adb shell su - -c dd if=/dev/block/by-name/boot${CUR_SLOT} | cat >boot${CUR_SLOT}.img
196608+0 records in
196608+0 records out
100663296 bytes (96 M) copied, 2.668147 s, 36 M/s
[ OmniRomDev - [email protected] /data/develop/android/test ]
[ OmniRomDev - [email protected] /data/develop/android/test ] $ ls -ltr boot${CUR_SLOT}.img
-rw-r--r--. 1 xtrnaw7 xtrnaw7 100663296 Oct 1 12:13 boot_b.img
[ OmniRomDev - [email protected] /data/develop/android/test ] $
To trouble shoot issues with this approach it is highly recommended to create an Magisk init script in the directory
/data/adb/post-fs-data.d
to fetch and store the Android logs into a persistent file. Use these commands to create the script:
Code:
cat >/data/adb/post-fs-data.d/0002logcatboot <<-EOT
mkdir -p /cache/logs
# backup the OS logs from before the reboot:
#
[ -r /cache/logs/log ] && mv /cache/logs/log /cache/logs/oldlog
/system/bin/logcat -r 102400 -n 9 -v threadTime -f /cache/logs/log >/cache/logs/info.log 2>/cache/logs/err.log &
EOT
chmod 755 /data/adb/post-fs-data.d/0001logcatboot
Using this script the log messages from before the last reboot are stored in the file /cache/logs/oldlog.
To activate the script the phone must be rebooted.
Check the contents of the directory /cache/logs/log after the reboot as user root to be sure that it works.
Code:
[email protected]_I006D:/ $ su - -c ls -ltr /cache/logs
total 205008
-rw-rw-rw- 1 root root 0 1970-01-06 08:16 info.log
-rw-rw-rw- 1 root root 0 1970-01-06 08:16 err.log
-rw-r----- 1 root root 4707523 2022-10-01 17:29 log
[email protected]_I006D:/ $
Details
The trigger in the .rc files for the action that should be done while shutting down is
on shutdown
The trigger can be used more then once; the OS will execute all defined actions for the trigger in the order they are found in the rc files.
The action to run an executable in the .rc file is
exec [ <seclabel> [ <user> [ <group>\* ] ] ] -- <command> [ <argument>\* ]
Fork and execute command with the given arguments. The command starts after “--” so that an optional security context, user, and supplementary groups can be provided. No other commands will be run until this one finishes. seclabel can be a - to denote default. Properties are expanded within argument. Init halts executing commands until the forked process exits.
Click to expand...
Click to collapse
In Android SELinux is enabled by default. Therefor it's neccessary to use the correct SELinux context for the files used.
(Note: The SELinux context for the init process executing the action is u:r:init:0 )
It's quite difficult to find the correct SELinux contexts in Android for this approach therefor it's better to use the general SELinux context defined by Magisk: u:r:magisk:s0 .
Implementation
Note:
All commands must be done as user root in an session on the phone or in an adb session.
So first create the neccessary directories and files:
Code:
mkdir -p /data/init_scripts
mkdir -p /data/init_scripts/log
Create the script to execute on shutdown:
Code:
cat >/data/init_scripts/my_shutdown.sh <<-\EOT
#!/system/bin/sh
SHUTDOWN_LOG="/data/init_scripts/log/myshutdown.$$.log"
echo "$0: Shutdown with parameter \"$*\" started at $( date ) " >>${SHUTDOWN_LOG}
echo "*** id : " >>${SHUTDOWN_LOG} 2>&1
id >>${SHUTDOWN_LOG} 2>&1
# ... add necessary commands ...
EOT
chmod 755 /data/init_scripts/my_shutdown.sh
Correct the SELinux context:
Code:
chcon -R u:r:magisk:s0 /data/init_scripts/
Check the result
Code:
[email protected]_I006D:/ # find /data/init_scripts/ -exec ls -ld {} \;
drwxr-xr-x 3 root root u:r:magisk:s0 3452 2022-10-01 16:12 /data/init_scripts/
-rwxr-xr-x 1 root root u:r:magisk:s0 637 2022-10-01 16:12 /data/init_scripts/my_shutdown.sh
drwxr-xr-x 2 root root u:r:magisk:s0 3452 2022-10-01 16:16 /data/init_scripts/log
[email protected]_I006D:/ #
Create a working directory:
Code:
#
# create a working directory
#
mkdir -p /data/adb/workdir
cd /data/adb/workdir
Now create the additional .rc file:
Code:
#
# change the current directory to the working directory
#
cd /data/adb/workdir
cat >init.custom.rc <<-\EOT
on shutdown
exec u:r:magisk:s0 -- /system/bin/sh /data/init_scripts/my_shutdown.sh 0008
on early-init
setprop my_custom_rc_file loaded
EOT
Note:
The additional trigger for early-init is for testing the new .rc file (see the trouble shooting section below for details). Magisk supports more then one .rc file; the name of the .rc file is meaningless but the extension must be .rc.
And now add the new file to the ramdisk on the boot partition:
Code:
#
# change the current directory to the working directory
#
cd /data/adb/workdir
# get the current active slot
#
CURRENT_SLOT=$( getprop ro.boot.slot_suffix )
echo "The current active slot is: ${CURRENT_SLOT}"
# copy the boot partition from the active slot to a file
#
dd if=/dev/block/by-name/boot${CURRENT_SLOT} of=./boot_root.img
# unpack the image file
#
/data/adb/magisk/magiskboot unpack ./boot_root.img
# add the new dirs and files to the ramdisk from the boot partition
#
/data/adb/magisk/magiskboot cpio ramdisk.cpio \
"mkdir 0700 overlay.d" \
"add 0700 overlay.d/init.custom.rc init.custom.rc"
# recreate the image file for the boot partition
#
/data/adb/magisk/magiskboot repack boot_root.img
# write the corrected image file to the boot partition
#
dd if=./new-boot.img of=/dev/block/by-name/boot${CURRENT_SLOT}
Note:
The commands to unpack and pack the ramdisk manually using the cpio command are (if NOT using the Magisk binary magiskboot):
Code:
RAMDISK=$PWD/ramdisk
mkdir ${RAMDISK}
cd ${RAMDISK}
# unpack the ramdisk
#
cpio -idm <../ramdisk.cpio
# ... do what ever is necessary with the files/dirs in ${RAMDISK}
# pack the ramdisk again
#
cd ${RAMDISK}
find . | cpio -o >../ramdisk.cpio
Now reboot the phone to activate the new .rc config and after the reboot check that the .rc file was processed
Code:
getprop my_custom_rc_file
e.g
Code:
[email protected]_I006D:/ $ getprop my_custom_rc_file
loaded
[email protected]_I006D:/ $
If the property defined in the .rc file, my_custom_rc_file, is not set something went wrong and you should check the OS logs and double check your config.
If the new property is defined you can test the shutdown action by rebooting the phone again.
While doing this reboot the new shutdown script should be executed and after the reboot is done there should be the log file from the shutdown script:
Code:
[email protected]_I006D:/ $ su -
[email protected]_I006D:/ # ls -l /data/init_scripts/log
total 0
-rw------- 1 root root 179 2022-10-01 18:23 myshutdown.4617.log
[email protected]_I006D:/ # cat /data/init_scripts/log/myshutdown.4617.log
/data/init_scripts/my_shutdown.sh: Shutdown with parameter "0008" started at Sat Oct 1 18:23:14 CEST 2022
*** id :
uid=0(root) gid=0(root) groups=0(root) context=u:r:magisk:s0
[email protected]_I006D:/ #
That's it.
Note that you can change the script executed while doing the shutdown without changing the boot image again.
But you should always test the script before rebooting -- an error in your script may stop the reboot.
To change the additional .rc files it's necessary to recreate the ramdisk and boot partition.
The filesystems for /data and for /sdcard are still mounted while executing the actions for the trigger "on shutdown" .
To log the current environment while executing the shutdown script you can add code like this to the script:
Code:
(
echo
echo "*** Environment while executing the shutdown script ..."
echo
echo "*** pwd: "
pwd
echo
echo "*** id: "
id
echo
echo "*** df -h: "
df -h
echo
echo "*** ps -efZ : "
ps -efZ
echo
echo "*** env: "
env
echo
echo "*** set: "
set
echo
) >>/data/init_scripts/log/myshutdown_env.log 2>&1
To create a directory in which other actions from the .rc file (like write) can write with SELinux enabled use one of the SELInux contexts the init process can write to, e.g:
Code:
mkdir /data/system_data
chcon u:object_r:system_data_file:s0 /data/system_data
Now the .rc config
Code:
on shutdown
write /data/system_data/myshutdown.log Shutdown_started\n
will work.
See the file ./plat_file_contexts in the ramdisk from the boot partition for other existing SELinux contexts, e.g.:
Code:
[email protected]_I006D:/data/adb/test # /data/adb/magisk/magiskboot cpio ramdisk.cpio "extract plat_file_contexts plat_file_contexts" <
Loading cpio: [ramdisk.cpio]
Extract [plat_file_contexts] to [plat_file_contexts]
[email protected]_I006D:/data/adb/test # ls -l plat_file_contexts
-rw-r--r-- 1 root root 40490 2022-10-03 16:27 plat_file_contexts
[email protected]_I006D:/data/adb/test #
Please be aware that these changes will be gone after the next OS update. But on the other hand it's quite easy to create a script to re-install the shutdown script without user intervention.
Trouble Shooting
The main reason for problems with this approach are invalid SELinux contexts. Therefor you should test your script in permissive SELinux mode if it does not work like expected. To do that temporary disable SELinux before rebooting (SELinux will be automatically enabled again after the reboot), e.g.:
Code:
# set SELinux to permissive
#
setenforce 0
reboot
and check the log messages in the directory /cache/logs/oldlog for SELinux related messages:
Code:
su - -c grep deny /cache/logs/oldlog
Note that you can not disable SELinux in an action in an .rc file.
To check if your additional .rc file is processed by Magisk add a statement like these to the custom .rc file in the overlay directory:
Code:
on early-init
setprop sys.example.foo bar
If this statement is processed by Magisk and Android the property sys.example.foo should be defined after the reboot, e.g.:
Code:
[email protected]_I006D:/ # getprop sys.example.foo
bar
[email protected]_I006D:/ #
To check if the "on shutdown" trigger is processed use :
Code:
on shutdown
write /sdcard/Download/myshutdown.log Shutdown_started\n
and reboot with disabled SELinux:
Code:
setenforce 0
reboot
If the "on shutdown" trigger in your .rc file is processed there should exist the file
/sdcard/Download/myshutdown.log
after the reboot
If the shutdown of the phone hangs open another adb session to the phone and kill the script (the adb daemon should still run while the shutdown script is running).
If the phone does not boot anymore with the new shutdown script reboot the phone from the TWRP image and fix / delete the new shutdown script. Or reflash the boot partition with the image file created before starting the development.
In general you should carefully check your .rc file for syntax errors -- entries in the file after the first syntax error will be ignored
Useful URLs
I used ideas and code from the web pages listed below for this HowTo:
How to run an executable on boot and keep it running?
How to run an Android init service with superuser SELinux context?
Magisk overlay - execute a script or copy files
History
03.10.2022 /bs
added code about to extract a single file (plat_file_contexts) from the ramdisk cpio image using magiskboot

Related

How To Guide How to use the Hardware Test App from ASUS on a Zenfone running a CustomROM

How to use the Hardware Test App from ASUS on a Zenfone running a CustomROM
The Hardware Test App from ASUS for the Zenfone 8 can also be used on a ASUS Zenfone 8 running a CustomROM.
But to get the App working on a CustomROM some efforts are neccessary.
The ASUS Hardware Test App needs the permission to modify system settings. To get this permission the app must be signed with the platform certificate used for the running Android OS.
And because these certificates are not available for the public for all public available CustomROMs (for some very good reasons ...) you must compile your own CustomROM for using the ASUS Hardware Test App on a CustomROM.
So -- for those who still want to continue: Here are the steps neccessary to run the Hardware Test App from ASUS for the Zenfone 8 on a phone running a CustomROM :
First copy the apk with the ASUS Hardware Test App from a Zenfone 8 running the original Android 12 from ASUS to your PC.
This is the file
/system/apps/SMMI_TEST/SMMI_TEST.apk
on the phone running the ASUS Android OS.
Now it's neccessary to sign the App with the platform key from your CustomROM:
In the OmniROM (and I assume that's also true for other AOSP based CustomROMs) the neccessary files, platform.pk8 and platform.x509.pem, are in the directory
Code:
./build/make/target/product/security
in your build tree for the CustomROM, e.g.
Code:
[[email protected] /data/develop/android/OmniROM]$ ls -l ./build/make/target/product/security/platform.*
-rw-------. 1 xtrnaw7 xtrnaw7 1219 Jun 25 09:39 ./build/make/target/product/security/platform.pk8
-rw-rw-r--. 1 xtrnaw7 xtrnaw7 1460 Jun 25 09:39 ./build/make/target/product/security/platform.x509.pem
[[email protected] /data/develop/android/OmniROM]$
Now re-sign the apk file using these commands:
Code:
# remove the current certificate files from the apk (probably not neccessary -- but shouldn't harm)
#
zip -d SMMI_TEST.apk META-INF/CERT.SF META-INF/CERT.RSA
# do a zip align for the apk and write the output to SMMI_TEST1.apk
#
# (zipalign is part of the OTA tools)
#
/data/develop/android/otatools/bin/zipalign 4 SMMI_TEST.apk SMMI_TEST1.apk
# test the result (there should be NO output from this command)
#
/data/develop/android/otatools/bin/zipalign -c 4 SMMI_TEST1.ap
# and now sign the apk with the platform key from the development tree for your self compiled CustomROM
# (apksigner.jar is part of the Sdk from Google for Android)
#
java -jar ./Android/Sdk/build-tools/33.0.0/lib/apksigner.jar sign --key platform.pk8 --cert platform.x509.pem SMMI_TEST1.apk
That's it . The re-signed apk file SMMI_TEST1.apk should work on your CustomROM
To test it:
To test the signed apk do:
Copy the signed apk to the phone running your self compiled CustomROM and issue
Code:
ls -l /sdcard/Download/SMMI_TEST1.apk
# 25733396 in the next command is the size of the file /sdcard/Download/SMMI_TEST1.apk in byte
#
cat /sdcard/Download/SMMI_TEST1.apk | pm install -S 25733396
If you get an error like this
Code:
130|ASUS_I006D:/ # ls -l /sdcard/Download/SMMI_TEST1.apk
-rw-rw---- 1 u0_a111 media_rw 25733396 2022-08-04 19:02 /sdcard/Download/SMMI_TEST1.apk
ASUS_I006D:/ #
ASUS_I006D:/ # cat /sdcard/Download/SMMI_TEST1.apk | pm install -S 25733396
Failure [INSTALL_FAILED_SHARED_USER_INCOMPATIBLE: Reconciliation failed...: Reconcile failed: Package com.asus.atd.smmitest has no signatures that match those in shared user android.uid.system; ignoring!]
1|ASUS_I006D:/ #
something went wrong signing the apk. Just do it again.
To install the apk do:
If not already done:
Compile your own CustomROM (using the certificates used to sign the ASUS Hardware Test App!) and install it on the ASUS Zenfone 8. (see How to compile the OmniROM for the ASUS Zenfone 8 for how to compile the OmniROM)
Install Magisk on your phone running the self compiled CustomROM
Simulate a Magisk Module using these commands:
Code:
adb shell su - -c mkdir -p /data/adb/modules/SMMI_TEST/system/app/SMMI_TEST
adb push SMMI_TEST1.apk /sdcard/Download/
adb shell su - -c cp /sdcard/Download/SMMI_TEST1.apk /data/adb/modules/SMMI_TEST/system/app/SMMI_TEST/SMMI_TEST1.apk
adb shell su - -c chmod o+r /data/adb/modules/SMMI_TEST/system/app/SMMI_TEST/SMMI_TEST1.apk
and reboot the phone
Code:
adb reboot
After the reboot the ASUS Hardware Test App should be visible in the directory /system/app, e.g.
Code:
130|ASUS_I006D:/ # find /system/app/SMMI_TEST/
/system/app/SMMI_TEST/
/system/app/SMMI_TEST/SMMI_TEST1.apk
ASUS_I006D:/ #
To execute the ASUS Hardware Test App do
Code:
# open a shell on the ASUS Zenfone 8 (either local or via "adb shell"), become root user
su -
and execute
Code:
# switch SELinux to permissive mode (I currently do not know the neccessary SELinux policies to avoid this step ...)
#
setenforce 0
# and start the ASUS Hardware Test App from within the shell
#
am start -n com.asus.atd.smmitest/com.asus.atd.smmitest.main.MAIN
Do not forget to enable SELinux enforcing mode after the tests are done (or reboot the phone ...)
Code:
# switch SELinux to permissive mode (I currenlty do not know the neccessary SELinux policies to avoid this step ...)
#
setenforce 1
Sample Script to start the ASUS Hardware Test App
Code:
# simple script to start the ASUS Hardware App
CUR_SELINUX_STATUS="$( getenforce )"
CUR_USERID=$( id -u -n )
RESTORE_SELINUX_STATE="false"
if [ "${CUR_SELINUX_STATUS}"x != "Permissive"x ] ; then
if [ "${CUR_USERID}"x != "root"x ] ; then
echo "Either start this script as user \"root\" or set the SELinux mode to \"permissive\" using the command \"setenforce 0\" before starting this script"
exit 1
fi
echo "Setting the SELinux mode to \"Permissive\" ..."
setenforce 0
RESTORE_SELINUX_STATE="true"
else
echo "The SELinux mode is already \"Permissive}\" "
fi
am start -n com.asus.atd.smmitest/com.asus.atd.smmitest.main.MAIN 2>&1 | tee /sdcard/Download/test.out
if [ ${RESTORE_SELINUX_STATE} = true ] ; then
echo "Press return when done with the tests .."
read USER_INPUT
echo "Setting the SElinux mode back to \"Enforcing\" ...."
setenforce 1
else
echo "Do not forget to set the SELinxu mode back to \"Enforcing\" using the command \"setenforce 1\" "
fi
Trouble Shooting
If the boot process of the phone hangs after adding the pseudo Magisk Module for the ASUS Hardware Test App do:
Code:
# connect to the phone via adb (that should work!)
#
adb shell
# become root user
#
su -
# delete the file with the AUS Hardware Test App
#
rm /data/adb/modules/SMMI_TEST/system/app/SMMI_TEST/SMMI_TEST1.apk
# and reboot the phone
#
reboot
Most probably something went wrong signing the app or you did not do the zip align (there should be some messages visible in logcat to find the reason for the boot loop; check the output of logcat before rebooting the phone)
A useful test to find reason for the boot loop is :
Code:
# try to install the apk as root user
#
su -
# and then
#
setenforce 0
pm install /sdcard/Download/SMMI_TEST.apk
If booting the phone works but the App does not start make sure that the SELinux status is permissive.
Update 26.06.2022
The adb commands to create the "simulated" Magisk Module must be executed by the user root - fixed.
Added a sample script to start the ASUS Hardware Test Tool
Update 04.08.2022
Added instructions to to test if signing the apk was successfull
Thank you so much for your guides! This is very detailled documentation with good explanations!

How To Guide How to backup the data from the phone using rsync and ssh (including some hints for using sshd on an Android phone)

How to backup the data from the phone using rsync and ssh (including some hints for using sshd on an Android phone)
Like for all computer it's important to have a backup of the data on the phone.
For those who like me don't like to store their private data in one of the suspicious clouds there is a solution with standard Linux tools:
Use rsync and ssh to backup the data from the phone to your local workstation (see the man page for rsync for details regarding rsync and why it is useful for this task)
The neccessary tools for Android for this method can be installed with the Magisk Module MagiskSSH.
Download the Magisk Module with MagiskSSH from here
https://gitlab.com/d4rcm4rc/MagiskSSH_releases
Copy the ZIP file with the Magisk Module to the phone :
Code:
adb push magisk_ssh_v0.14.zip /sdcard/Download/
and install it via the module installation from within the Magisk App or manuell using :
Code:
adb shell su - -c /data/adb/magisk/magisk64 --install-module /sdcard/Download/magisk_ssh_v0.14.zip
Sample output of the installation:
Code:
ASUS_I006D:/ # /data/adb/magisk/magisk64 --install-module /sdcard/Download/magisk_ssh_v0.14.zip
- Current boot slot: _a
- Device is system-as-root
*******************************
OpenSSH for Android
*******************************
[0/7] Preparing module directory
[1/7] Extracting architecture unspecific module files
[2/7] Extracting libraries and binaries for arm64
[3/7] Configuring library path wrapper
[4/7] Recreating symlinks
[5/7] Creating SSH user directories
[6/7] Found sshd_config, will not copy a default one
[7/7] Cleaning up
- Setting permissions
- Done
ASUS_I006D:/ #
A reboot is required now.
Code:
adb shell reboot
For the next tasks open an adb shell and become root user.
Next create the authorized_keys file for the user root :
Code:
touch /data/ssh/root/.ssh/authorized_keys
chmod 600 /data/ssh/root/.ssh/authorized_keys
and add your public ssh key to the file /data/ssh/root/.ssh/authorized_keys.
To make sure that the keys and other data files for the MagiskSSH module are not removed while deinstalling the module you should create the file /data/ssh/KEEP_ON_UNINSTALL:
Code:
touch /data/ssh/KEEP_ON_UNINSTALL
The MagiskSSH module also installs a service to start sshd after each reboot: to disable this start create the file /data/ssh/no-autostart:
Code:
touch /data/ssh/no-autostart
To manually start or stop the sshd use the script /data/adb/modules/ssh/opensshd.init :
Code:
# start the sshd (as user root)
#
/data/adb/modules/ssh/opensshd.init start
# to stop the sshd (as user root)
#
/data/adb/modules/ssh/opensshd.init stop
Now test the access via ssh from your Linux workstation:
Code:
ssh -l root <phone_ip_address> id
Use this command to retrieve the current IP address of the phone:
Code:
PHONE_IP_ADDRESS=$( adb shell ifconfig wlan0 | grep "inet addr:" | sed -e "s/.*inet addr://g" -e "s/[[:space:]]*Bcast.*//g" )
example :
Code:
[[email protected] ~]$ ssh -l root ${PHONE_IP_ADDRESS} id
uid=0(root) gid=0(root) groups=0(root) context=u:r:magisk:s0
[[email protected] ~]$
Now you can use rsync to backup the data from the phone, e.g. to backup the photos from the phone do :
Code:
# on your local Linux workstation do:
# start the sshd on the phone via adb if not already running
#
adb shell su - -c /data/adb/modules/ssh/opensshd.init start
# retrieve the current IP address from the phone
#
PHONE_IP_ADDRESS=$( adb shell ifconfig wlan0 | grep "inet addr:" | sed -e "s/.*inet addr://g" -e "s/[[:space:]]*Bcast.*//g" )
# backup the new photos from the phone to the Linux workstation (rsync only copies new files from the phone)
# to the local directory /data/backup/ASUS_ZENFONE8/DCIM
#
rsync -av --rsync-path /data/adb/modules/ssh/usr/bin/rsync [email protected]${PHONE_IP_ADDRESS}:/sdcard/DCIM/ /data/backup/ASUS_ZENFONE8/DCIM
# optional stop the sshd on the phone via adb
#
adb shell su - -c /data/adb/modules/ssh/opensshd.init stop
Note: The sshd configuration file used is /data/ssh/sshd_config
Sample Script to backup all data in the directory /sdcard
Code:
##!/bin/bash
#
# simple script to backup the data of an phone using adb, ssh, and rsync
#
# History
# 27.06.2022 /bs
# initial release
#
# for testing
#
#RSYNC_OPTIONS="${RSYNC_OPTIONS} --dry-run"
RSYNC_OPTIONS="${RSYNC_OPTIONS} --del "
# default is to backup the phone connected via adb over LAN
#
[ $# -ne 0 ] && ADB_OPTIONS="$*" || ADB_OPTIONS="-e"
# retrieve the serial number of the attached phone
#
SERIAL_NO="$( adb ${ADB_OPTIONS} shell getprop ro.serialno )"
if [ "${SERIAL_NO}"x = ""x ] ; then
echo "ERROR: Can not read the serial number of the connected phone"
exit 89
fi
VENDOR_MODEL="$( adb ${ADB_OPTIONS} shell getprop ro.product.vendor.model )"
# directory for the backup
#
BACKUP_DIR="/data/backup/ASUS_ZENFONE8/data_backup/${VENDOR_MODEL}_${SERIAL_NO}"
if [ ! -d "${BACKUP_DIR}" ] ; then
echo "ERROR: The directory \"${BACKUP_DIR}\" does not exist"
exit 99
fi
PHONE_IP_ADDRESS="$( adb ${ADB_OPTIONS} shell ifconfig wlan0 | grep "inet addr:" | sed -e "s/.*inet addr://g" -e "s/[[:space:]]*Bcast.*//g" )"
if [ "${PHONE_IP_ADDRESS}"x = ""x ] ; then
echo "ERROR: Can not detect the IP address of the phone"
exit 100
fi
echo "Updating a backup of the data on the phone with the serial number \"${SERIAL_NO}\" and the IP \"${PHONE_IP_ADDRESS}\" to the directory \"${BACKUP_DIR}\" ..."
set -x
# start the sshd if neccessary
#
adb ${ADB_OPTIONS} shell su - -c /data/adb/modules/ssh/opensshd.init start
# do the backup
#
time rsync ${RSYNC_OPTIONS} -av --rsync-path /data/adb/modules/ssh/usr/bin/rsync [email protected]${PHONE_IP_ADDRESS}:/sdcard/ "${BACKUP_DIR}/"
# stop the sshd
#
adb ${ADB_OPTIONS} shell su - -c /data/adb/modules/ssh/opensshd.init stop
set +x
How to enable access via ssh for non-root user
In the standard configuration installed by MagiskSSH ssh access is only allowed as user root because the ssh keys are in the directory /data and all non-root user can not read files in the directory /data. Therefor some efforts are neccessary to add ssh access for non-root user.
e.g. To enable the ssh access for the user shell do:
To configure ssh access for the user shell we must create a .ssh directory for the user shell in a directory tree owned by the user shell. The only directory on the phone owned by the user shell that can be used for this purpose is /storage :
Code:
ASUS_I006D:/ # ls -ld /storage
drwx--x--- 4 shell everybody 80 2022-06-26 18:37 /storage
ASUS_I006D:/ #
But unfortunately all files and directories in this directory are temporary and will be deleted after a reboot of the phone.
Therefor we configure a startup script in Magisk to create this directory tree after each reboot, e.g.
/data/adb/service.d/create_ssh_dir_for_shell.sh:
Code:
# /data/adb/service.d/create_ssh_dir_for_shell.sh
#
mkdir -p /storage/shell/.ssh
chmod -R 700 /storage/shell/
touch /storage/shell/.ssh/authorized_keys
echo "<ssh_public_key>" > /storage/shell/.ssh/authorized_keys
chmod 600 /storage/shell/.ssh/authorized_keys
chown -R shell:shell /storage/shell
Make the script executable:
Code:
su - -c chmod +x data/adb/service.d/create_ssh_dir_for_shell.sh
To test the script just execute it one time manually as user root.
Code:
su - -c sh data/adb/service.d/create_ssh_dir_for_shell.sh
Now create a backup of the sshd config file
Code:
su - -c cp /data/ssh/sshd_config /storage/ssh/sshd_config.org.$$
and add these lines at the end of the file /data/ssh/sshd_config
Code:
Match User shell
AuthorizedKeysFile /storage/shell/.ssh/authorized_keys
Restart the sshd if it's already running
Now test the access as user shell, example:
Code:
[[email protected] ~]$ ssh -l shell 192.168.1.148 id
uid=2000(shell) gid=2000(shell) groups=2000(shell) context=u:r:magisk:s0
[[email protected] ~]$
The reason for this config is the setting "StrictMode yes" in the sshd config file /data/ssh/sshd_config (see the man page for sshd_config for details). So another "solution" is to change this setting:
With the setting "StrictModes no" in the file sshd_config the directory with the authorized_keys file for the non-root users can be anywhere (for example in /sdcard/shell)
Execute as user root:
Code:
sed -i -e "s/.*StrictModes.*//g" -e "s/UsePrivilegeSeparation/StrictModes no\nUsePrivilegeSeparation/g" /data/ssh/sshd_config
and change the entry in the file /data/ssh/sshd_config for the authorized_keys file for the user shell, for example:
Code:
Match User shell
AuthorizedKeysFile /sdcard/shell/.ssh/authorized_keys
Afterwards restart the sshd:
Code:
/data/adb/modules/ssh/opensshd.init stop
/data/adb/modules/ssh/opensshd.init start
Now create the directories and files neccessary for the ssh access (see above) in the directory /sdcard/shell:
Code:
SUS_I006D:/ # find /sdcard/shell -exec ls -ld {} \;
drwxrws--- 3 u0_a118 media_rw 3452 2022-06-26 18:32 /sdcard/shell
drwxrws--- 2 u0_a118 media_rw 3452 2022-06-26 18:32 /sdcard/shell/.ssh
-rw-rw---- 1 u0_a118 media_rw 408 2022-06-26 18:32 /sdcard/shell/.ssh/authorized_keys
ASUS_I006D:/ #
and the access as user shell via ssh should work

How To Guide How to change the home directory for the user root on an Android phone

How to change the home directory for the user root on an Android phone
When working a lot in a shell via adb on an Android phone it's usefull to be able to store some user dependent config files in the home directory of the user. So let's see how that can be implemented on a phone running Android.
Note: The config was done and tested on a phone running OmniROM (based on Android 12)
The home directory for all user used in an (adb) shell on Android is the root directory "/".
Using a home directory for more then one user is not really usefull and in addition on Android "/" is mounted read-only so more or less useless as home directory.
Therefor this should be changed . Unfortunately there is no /etc/passwd file in Android to configure the home directory for a user.
Well, there is an /etc/passwd file (probably for compatibily reasons) but it's empty:
Code:
[email protected]_I006D:/ $ ls -l /etc/passwd
-rw-r--r-- 1 root root 0 2009-01-01 01:00 /etc/passwd
[email protected]_I006D:/ $
And as far as I know there is no other config file to configure the home directory of the user in the Android OS.
So we must implement some work around to get this working.
The shell on Android behaves like normal shells on Linux and executes the file /etc/profile when starting a new session.
In Android /etc is a symbolic link to /system/etc:
Code:
[email protected]_I006D:/ # ls -ld /etc
lrw-r--r-- 1 root root 11 2009-01-01 01:00 /etc -> /system/etc
[email protected]_I006D:/ #
And in the default config there is no file called profile in that directory:
Code:
[email protected]_I006D:/ $ ls -l /etc/system/profile
ls: /etc/system/profile: No such file or directory
[email protected]_I006D:/ $
Because /system is also mounted read-only we need the magic tool Magisk again to create the file /system/etc/profile.
To create the file /system/etc/profile create these directories and files on the phone as user root (assuming Magisk is already installed on the phone):
Code:
[email protected]_I006D:/ # find /data/adb/modules/initshell/
/data/adb/modules/initshell/
/data/adb/modules/initshell/system
/data/adb/modules/initshell/system/etc
/data/adb/modules/initshell/system/etc/profile
[email protected]_I006D:/ #
and reboot the phone. After the reboot there should be the writable file /etc/profile:
Code:
[email protected]_I006D:/ # ls -l /etc/profile
-rw-rw-rw- 1 root root 1100 2022-07-14 14:51 /etc/profile
[email protected]_I006D:/ #
which is in reality the file
Code:
/data/adb/modules/initshell/system/etc/profile
Now you can edit the file /etc/profile as user root until it fullfills your requirements (be aware that all changes in that file are now persistent).
To test the changes open a new adb session (you should not close the current adb session to be able to fix an error in the profile if opening a new adb session fails).
This file can now be used to define the home directory for the user. The home directory should be on one of the writable filesystem, e.g. in /data:
Code:
# add in /etc/profile
HOME="/data/home/root"
export HOME
and the result is:
Code:
[email protected]_I006D:/ # id
uid=0(root) gid=0(root) groups=0(root),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),1078(ext_data_rw),1079(ext_obb_rw),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc),3011(uhid) context=u:r:su:s0
[email protected]_I006D:/ # echo $HOME
/data/home/root
[email protected]_I006D:/ #
Note that there is not really a writable filesystem for the user shell so this approach to change the home directory is mainly usable for the user root.
The file /etc/profile can also be used to init some other settings for (adb) sessions (e..g. change the PATH, etc) . This feature can be used for sessions for non-root users also.
For additional user dependent configs you can also create the file .profile in the home directory of the user; the file ${HOME}/.profile will be executed after the execution of the file /etc/profile.
Notes:
Be aware that creating a profile for the user root and changing the home directory for the user root might have some side effects on other processes using the shell!
Therefor it's recommended to use the command "tty -s" to test if the profile is executed in an interactive session:
Code:
#
# check if we're running in an interactive session
#
if ! tty -s; then
#
# this is not an interactive session - so we're just doing nothing at all
#
:
else
#
# running in an interactive session
#
...
fi
You can also check if the parent process is the adb daemon to not do anything in non-adb sessions.
Code:
ps -fp $PPID| grep adbd >/dev/null
if [ $? -ne 0 ] ; then
#
# not running in an adb session
:
else
#
# running in an adb session
...
fi
For testing purpose I suggest to open at least two shells via adb to be able to fix an error in case opening a new shell fails due to a bug in the profile.
If opening a shell session fails due to an error in the /etc/profile and you do not have another open shell either delete the file /data/adb/modules/initshell/system/etc/profile with a filemanager with root access on the phone or boot the phone from a recovery image (like TWRP) and delete or edit the file /data/adb/modules/initshell/system/etc/profile.
I initially looked at this feature to enable a persistent command history for the shell on the Android phone. But after some google searches I found out that persistent history shells are disabled for the shell binary on Android. So this will not work without recompiling the shell binary.
The attached example for the profile (rename the attached file profile.txt to profile) will use the directory /data/home/root as home directory for the user root and will not change the home directory for other users. The profile will do nothing if not running in an interactive session.
The directory /data/home/root will be created by the profile if it does not yet exist.
As always, if the config is working you should create a real Magisk Module for the profile.
The Magisk Module attached, initshell.zip, can be used to create a Magisk Module with your own profile:
To create a new Magisk Module with your own /etc/profile do:
Code:
# create an empty working directory
#
TEMPDIR="/tmp/newdir"
mkdir "${TEMPDIR}"
cd "${TEMPDIR}"
# unpack the zip file in the new directory
#
unzip ../initshell.zip
# now edit the file ${TEMPDIR}/system/etc/profile
# also (optional) edit the files config.sh and module.prop in the new directory to document your changes
# the script customize.sh from the module will be executed once when the module is installed. You might add the code
# create the home directories or any other code here
#
# and recreate the zip file
#
zip -r ../initshell.zip .
Note:
Both attached files are also available from my web site: http://bnsmb.de/My_HowTos_for_Android.html

How To Guide How to trigger an action when a property is changed

How to trigger an action when a property is changed
In Android it's possible to trigger various actions by changing the value of a property.
This feature is quite handy and the implementation using Magisk is not really difficult.
As an example:
In the original Android from ASUS for the Zenfone 8 you can disable and enable the swap on a ZRAM device by changing the value for the property vendor.zram.enable:
e.g.:
To turn the swap on use
Code:
setprop vendor.zram.enable 1
and to turn the swap off use
Code:
setprop vendor.zram.enable 0
To get the current value use
Code:
getprop vendor.zram.enable
or
check the output of the OS command free.
(see How to disable or change the swap device in the Android 12 from ASUS for the Zenfone 8 for details)
This feature is not implemented in the OmniROM for the ASUS Zenfone 8 but quite useful so let's see how to implement it in the OmniROM.
The Triggers and Action for this Android feature are configured in the init.rc files in the root filesystem for the OS (see https://android.googlesource.com/platform/system/core/+/master/init/README.md for details). The root filesystem for Android is read-only mounted so without creating your own Android OS image for the phone it's not possible to add the functionality to the OS.
But we can use the Root Directory Overlay System from Magisk (see https://github.com/topjohnwu/Magisk/blob/master/docs/guides.md for the documentation) to implement it.
The detailed process for creating additional *.rc files for Android via Magisk is described here:
How to run a script at shutdown
Therefore I will not go into the details here. But please read that post before you continue
First we check how this feature is implemented in the Original Android for the Zenfone:
Enabling and disabling the swap device on ZRAM is configured in the .rc file
/vendor/etc/hw/init.asus.debugtool.rc
using these settings in the original Android OS for the Zenfone 8:
Code:
service asus_zram /system/vendor/bin/sh /vendor/bin/init.asus.zram.sh
user root
group root
disabled
seclabel u:r:vendor_qti_init_shell:s0
oneshot
on property:persist.vendor.zram.enable=1
setprop vendor.zram.enable "1"
setprop vendor.zram.disksize ${persist.vendor.zram.disksize}
on property:persist.vendor.zram.enable=0
setprop vendor.zram.enable "0"
setprop vendor.zram.disksize ${persist.vendor.zram.disksize}
on property:vendor.zram.enable=*
start asus_zram
The script used to enable or disable the swap device on ZRAM in the original Android for the Zenfone 8 is:
/vendor/bin/init.asus.zram.sh
The script is quite simple (see also below):
It uses two properties to configure the swap device:
vendor.zram.enable : if this property is set to 1 the script enables the swap device and if the property is set to 0 it disables the swap device
vendor.zram.disksize : the value of this property is the size of the ramdisk.
Now we can implement this feature for the OmniROM:
Note:
All commands must be done as user root in a shell on the phone or in an adb shell
First we check the prerequisites for the feature:
The used shell for the service exists in the OmniROM:
Code:
[email protected]_I006D:/data/adb/workdir # ls -Zl /vendor/bin/sh
-rwxr-xr-x 1 root shell u:object_r:vendor_shell_exec:s0 318216 2009-01-01 01:00 /vendor/bin/sh
[email protected]_I006D:/data/adb/workdir #
The script to toggle the ramdisk on the swap device also already exists in the OmniROM:
Code:
[email protected]_I006D:/data/adb/test # ls -l /vendor/bin/init.asus.zram.sh
-rwxr-xr-x 1 root shell 1127 2009-01-01 01:00 /vendor/bin/init.asus.zram.sh
[email protected]_I006D:/data/adb/test #
And the necessary SELinux contexts are also already defined in the OmniROM.
So, let's start:
Code:
# create a temporary directory
#
mkdir /data/adb/workdir
cd /data/adb/workdir
# create the additional .rc file
#
cat >init.asus.zram.rc <<-\EOT
#
# Note:
#
# The service definition for an OS without the script init.asus.zram.sh should be
#
# service asus_zram /system/bin/sh /system/sbin/init.asus.zram.sh
#
service asus_zram /system/vendor/bin/sh /vendor/bin/init.asus.zram.sh
user root
group root
disabled
seclabel u:r:vendor_qti_init_shell:s0
oneshot
#
# these properties can be used to define the initial state of the ramdisk on ZRAM
#
on property:persist.vendor.zram.enable=1
setprop vendor.zram.enable "1"
setprop vendor.zram.disksize ${persist.vendor.zram.disksize}
on property:persist.vendor.zram.enable=0
setprop vendor.zram.enable "0"
setprop vendor.zram.disksize ${persist.vendor.zram.disksize}
on property:vendor.zram.enable=*
start asus_zram
# The property persist.vendor.zram.enable is not defined in the OmniROM. If necessary you can add another triger in the .rc file,
# e.g to enable the swap device by default use
#
on early-init
setprop persist.vendor.zram.enable 1
EOT
# get the current active slot
#
CURRENT_SLOT=$( getprop ro.boot.slot_suffix )
echo "The current active slot is: ${CURRENT_SLOT}"
# copy the boot partition from the active slot to a file
dd if=/dev/block/by-name/boot${CURRENT_SLOT} of=./boot_root.img
# unpack the image file
/data/adb/magisk/magiskboot unpack ./boot_root.img
# add the new dir and file to the ramdisk from the boot partition
/data/adb/magisk/magiskboot cpio ramdisk.cpio \
"mkdir 0700 overlay.d" \
"add 0700 overlay.d/init.custom.rc init.asus.zram.rc"
# recreate the image file for the boot partition
/data/adb/magisk/magiskboot repack boot_root.img
# write the corrected image file to the boot partition
dd if=./new-boot.img of=/dev/block/by-name/boot${CURRENT_SLOT}
That's it.
After the next reboot switching the ramdisk on the ZRAM device via an property should be active:
Code:
[email protected]_I006D:/ # reboot
# .....
# start a new adb session
# ....
[email protected]_I006D:/ $ getprop ro.omni.version
12-20220703-zenfone8-MICROG
#
# Note: The property is only visible to the user root
#
[email protected]_I006D:/ $ su -
[email protected]_I006D:/ # id
uid=0(root) gid=0(root) groups=0(root) context=u:r:magisk:s0
[email protected]_I006D:/ #
[email protected]_I006D:/ # free
total used free shared buffers
Mem: 7612493824 4835229696 2777264128 14585856 14487552
-/+ buffers/cache: 4820742144 2791751680
Swap: 4294963200 0 4294963200
[email protected]_I006D:/ #
[email protected]_I006D:/ # getprop vendor.zram.enable
1
[email protected]_I006D:/ #
# -> now disable the swap on ZRAM
[email protected]_I006D:/ # setprop vendor.zram.enable 0
[email protected]_I006D:/ #
[email protected]_I006D:/ # getprop vendor.zram.enable
0
[email protected]_I006D:/ #
[email protected]_I006D:/ # free
total used free shared buffers
Mem: 7612493824 4840824832 2771668992 14524416 14483456
-/+ buffers/cache: 4826341376 2786152448
Swap: 0 0 0
[email protected]_I006D:/ #
# -> now enable the swap on ZRAM again
[email protected]_I006D:/ # setprop vendor.zram.enable 1
[email protected]_I006D:/ #
[email protected]_I006D:/ # getprop vendor.zram.enable
1
[email protected]_I006D:/ #
[email protected]_I006D:/ # free
total used free shared buffers
Mem: 7612493824 4844777472 2767716352 14524416 14512128
-/+ buffers/cache: 4830265344 2782228480
Swap: 4294963200 0 4294963200
[email protected]_I006D:/ #
Workarounds for other configuration
Find below some workarounds for OS versions without the prerequisites for implementing this feature.
1. The script to toggle the swap /vendor/bin/init.asus.zram.sh does not exist
If the script /vendor/bin/init.asus.zram.sh does not exist in your OS create a Magisk Module for the script
To create a (dummy) Magisk Module for the script do:
Code:
mkdir -p /data/adb/modules/toggle_ram/system/bin
#
# create the script to toggle the ramdisk on ZRAM
#
cat >/data/adb/modules/toggle_ram/system/bin/init.asus.zram.sh <<-\EOT
lahaina_set=`getprop vendor.asus.zram_setting`
if test "$lahaina_set" != "1"; then
echo "[asus_zram] init.kernel.post_boot-lahaina.sh not finished yet!"> /dev/kmsg
exit 0
fi
disksize=`getprop vendor.zram.disksize`
zram_enable=`getprop vendor.zram.enable`
MemTotalStr=`cat /proc/meminfo | grep MemTotal`
MemTotal=${MemTotalStr:16:8}
let RamSizeGB="( $MemTotal / 1048576 ) + 1"
if test "$disksize" = ""; then
disksize="4096M"
fi
echo "[asus_zram]RamSizeGB=${RamSizeGB}" > /dev/kmsg
if test "$zram_enable" = "1"; then
if [ $RamSizeGB -le 7 ]; then #this is for 6G; or the value will be 4G(8G,12G,16G,18G,etc)
disksize="( $RamSizeGB * 1024 ) / 2""M"
fi
swapoff /dev/block/zram0 2>/dev/kmsg
echo 1 > sys/block/zram0/reset 2>/dev/kmsg
sleep 1
echo lz4 > /sys/block/zram0/comp_algorithm
echo $disksize > /sys/block/zram0/disksize 2>/dev/kmsg
mkswap /dev/block/zram0 2>/dev/kmsg
swapon /dev/block/zram0 -p 32758 2>/dev/kmsg
echo "[asus_zram]write zram disksize=${disksize}" > /dev/kmsg
fi
if test "$zram_enable" = "0"; then
swapoff /dev/block/zram0 2>/dev/kmsg
echo "[asus_zram]turn off the zram" > /dev/kmsg
fi
EOT
chmod 755 /data/adb/modules/toggle_ram/system/bin/init.asus.zram.sh
chown root:shell /data/adb/modules/toggle_ram/system/bin/init.asus.zram.sh
chcon u:object_r:vendor_file:s0 /data/adb/modules/toggle_ram/system/bin/init.asus.zram.sh
Check the result:
Code:
[email protected]_I006D:/ # ls -lZ /data/adb/modules/toggle_ram/system/bin/init.asus.zram.sh
-rwxr-xr-x 1 root shell u:object_r:vendor_file:s0 1109 2022-10-03 21:14 /data/adb/modules/toggle_ram/system/bin/init.asus.zram.sh
[email protected]_I006D:/ #
Then change the script to execute in the service definition in the .rc file to /system/bin/init.asus.zram.sh:
Code:
service asus_zram /system/vendor/bin/sh /system/bin/init.asus.zram.sh
The rest of the instructions can be be used without changes.
2. The binary /system/vendor/bin/sh does not exist
If the shell /system/vendor/bin/sh does not exist in the OS create an Magisk Module with an approbiate shell:
Note:
The shell /system/bin/sh can not be used because it's configured with another SELinux context:
Code:
[email protected]_I006D:/ # ls -lZ /system/vendor/bin/sh
-rwxr-xr-x 1 root shell u:object_r:vendor_shell_exec:s0 318216 2009-01-01 01:00 /system/vendor/bin/sh
[email protected]_I006D:/ #
# but
[email protected]_I006D:/data/adb/workdir # ls -Zl /system/bin/sh
-rwxr-xr-x 1 root shell u:object_r:shell_exec:s0 307768 2009-01-01 01:00 /system/bin/sh
[email protected]_I006D:/data/adb/workdir #
To create a (dummy) Magisk Module for the necessary shell do:
Code:
mkdir -p /data/adb/modules/vendorshell/system/bin
cp /system/bin/sh /data/adb/modules/vendorshell/system/bin/sh
chcon u:object_r:vendor_shell_exec:s0 /data/adb/modules/vendorshell/system/bin/vendor_sh
Check the result:
Code:
[email protected]_I006D:/data/adb/workdir # ls -lZ /data/adb/modules/vendorshell/system/bin/vendor_sh
-rwxr-xr-x 1 root root u:object_r:vendor_shell_exec:s0 307768 2022-10-03 20:41 /data/adb/modules/vendorshell/system/bin/vendor_sh
[email protected]_I006D:/data/adb/workdir #
Now change the shell in the service definition in the .rc file to /system/bin/vendor_sh:
Code:
service asus_zram /system/bin/vendor_sh /vendor/bin/init.asus.zram.sh
The rest of the instructions can be be used without changes.
3. The necessary shell /system/vendor/bin/sh and the script /vendor/bin/init.asus.zram.sh do both not exist
If the necessary shell /system/vendor/bin/sh and the script /vendor/bin/init.asus.zram.sh do not exist you can also create one (dummy) Magisk module for both.
See
https://topjohnwu.github.io/Magisk/guides.html
and
Some hints for using Magisk on Android phones
for instructions and infos about how to create a real Magisk Module
4. Missing SELinux contexts
These instructions assume that all necessary SELinux contexts are already defined in the used OS.
If there are SELinux contexts missing it might not work without adding the missing SELinux contexts
(that might be difficult and I must admit that I did not test that)
5. only for the records:
The magiskboot command can also be used to add new files to the /sbin directory in the root filesystem.
This can be can be configured like this:
Code:
/data/adb/magisk/magiskboot cpio ramdisk.cpio \
"mkdir 0700 overlay.d" \
"add 0700 overlay.d/init.custom.rc init.asus.zram.rc" \
"mkdir 0700 overlay.d/sbin" \
"add 0700 overlay.d/sbin/my_new_script.sh my_script.sh"
This is useful for adding binaries or scripts for actions that should be executed while the other partitions are not yet mounted and therefor the files in these filesystems not yet available. But for the action defined in this post this is not necessary.
And be aware that the files added to the root filesystem ( /sbin/my_new_script.sh in this example) is only available while booting the phone.
6. Other problems
In case of problems please check the post
How to run a script at shutdown
again.
Also check the restrictions for this approach documented in that post
History
06.10.2022 /bs
corrected some typos

How To Guide How to configure the WiFI in Android via script

In the current version of Android the WiFi configuration is stored in the file
/data/misc/apexdata/com.android.wifi/WifiConfigStore.xml
e.g.
Code:
ASUS_I006D:/ # ls -lZtr /data/misc/apexdata/com.android.wifi/WifiConfigStore.xml
-rw------- 1 system system u:object_r:apex_system_server_data_file:s0 4884 2023-01-29 08:55 /data/misc/apexdata/com.android.wifi/WifiConfigStore.xml
ASUS_I006D:/ #
The file is in plain ASCII xml format so it can be processed by any executable to change text files (editor, sed, etc).
But IMHO it's better to configure the WiFi manually via GUI and then use the file WifiConfigStore.xml with that configuration for configuring the WiFi via script. Therefor I use this code in the post install script to install and configure my phone (see How to install and configure the Android OS via Script):
Spoiler: script commands to enable and configure WiFi
Bash:
#
# sample post install script for the customizing of the phone
#
# This script will be copied to the phone and executed there
#
# The script is executed by the user shell; use "su - -c <command>" to execute commands as user root
#
echo ""
echo "*** Postinstall script is running ..."
echo ""
# ... other customizations ....
#
# create the WiFi config file
#
# -rw------- 1 system system u:object_r:apex_system_server_data_file:s0 4884 2023-01-29 08:55 /data/misc/apexdata/com.android.wifi/WifiConfigStore.xml
#
WIFI_CONFIG_FILE="/data/misc/apexdata/com.android.wifi/WifiConfigStore.xml"
WIFI_CONFIG_FILE_BACKUP="${WIFI_CONFIG_FILE}.$$.bkp"
NEW_WIFI_CONFIG_FILE="/sdcard/Download/WifiConfigStore.xml"
if [ -r "${WIFI_CONFIG_FILE}" ] ; then
echo "Creating a backup of the file \"${WIFI_CONFIG_FILE}\" in \"${WIFI_CONFIG_FILE_BACKUP}\" ...."
cp "${WIFI_CONFIG_FILE}" "${WIFI_CONFIG_FILE_BACKUP}"
fi
echo "Creating the file \"${NEW_WIFI_CONFIG_FILE}\" ..."
cat >"${NEW_WIFI_CONFIG_FILE}" <<-\EOT
*** add here the contents of the file /data/misc/apexdata/com.android.wifi/WifiConfigStore.xml from the phone after manually configuring the WLAN
EOT
if [ $? -eq 0 ] ; then
echo "Creating the file \"${WIFI_CONFIG_FILE}\" ..."
su - -c cp "${NEW_WIFI_CONFIG_FILE}" "${WIFI_CONFIG_FILE}" && \
su - -c chmod 600 "${WIFI_CONFIG_FILE}" && \
su - -c chown system:system "${WIFI_CONFIG_FILE}" && \
su - -c chcon -v "u:object_r:apex_system_server_data_file:s0" "${WIFI_CONFIG_FILE}"
if [ $? -ne 0 ] ; then
echo "Error creating the file \"${WIFI_CONFIG_FILE}\" "
fi
else
echo "Error creating the file \"${NEW_WIFI_CONFIG_FILE}\" "
fi
# enable WiFi
#
echo "Enabling WiFi ..."
svc wifi enable
# optional: Disable mobile data connections
#
echo "Disabling mobile data ..."
svc data disable
# Now reboot the phone to activate the new WiFi config ..
#
echo "Waiting 15 seconds now before rebooting - press CTRL-C to abort ...."
i=0
while [ $i -lt 15 ] ; do
(( i = i + 1 ))
printf "."
sleep 1
done
printf "\n"
echo "Now rebooting the phone ..."
reboot
#
Notes:
Be aware the the file /data/misc/apexdata/com.android.wifi/WifiConfigStore.xml contains the passwords for all configured WLANs in plain text.
There should be a command to force Android to reread the file WifIConfigStore.xml but I don't know that.
Android can be forced to re-read the file WifIConfigStore.xml by killing the process system_server, e.g:
Bash:
pkill system_server
But that is more or less a warm reboot and I do not know what other side effects that restart triggers
There is an app to configure WiFi via adb command
https://github.com/steinwurf/adb-join-wifi
Bash:
adb shell am start -n com.steinwurf.adbjoinwifi/.MainActivity -e ssid myssid -e password mywlan_password -e password_type WPA
The app works but unfortunately it does not support enabling the setting to use the device MAC instead of the random MAC so it's not usable in my environment.
Another app to configure WiFi via adb command is available here:
https://github.com/pr4bh4sh/adb-wifi-setting-manager
Unfortunately that app also does not support enabling choosing the MAC address for the connection.
There is also a script to convert an old Android wpa_supplicant.conf file to the newer (post-Oreo) WifiConfigStore.xml file (not tested):
https://github.com/mnalis/android-wifi-upgrade
It's also possible to use the command wpa_cli to configure WiFi but be aware the wpa_cli only works if selinux is (temporary) disabled, example:
Spoiler: wpa_cli example
Code:
ASUS_I006D:/ $ su -
ASUS_I006D:/ #
ASUS_I006D:/ # setenforce 0
ASUS_I006D:/ #
ASUS_I006D:/ #
ASUS_I006D:/ # wpa_cli
wpa_cli v2.10-devel-11
Copyright (c) 2004-2019, Jouni Malinen <[email protected]> and contributors
This software may be distributed under the terms of the BSD license.
See README for more details.
Using interface 'wlan0'
Interactive mode
<3>Control interface command 'BSS RANGE=ALL MASK=0x2'
<3>Control interface command 'LIST_CREDS'
<3>Control interface command 'LIST_NETWORKS'
<3>Control interface command 'STA-FIRST'
>
> list_networks
network id / ssid / bssid / flags
0 Zeilsheim any [CURRENT]
1 any [DISABLED]
<3>Control interface command 'LIST_NETWORKS'
>
> quit
ASUS_I006D:/ #
Note: Use help to get list of known commands
Test Environment
I tested the WiFi config via script described above in these Android distributions:
OmniROM 13 (Android 13)
OmniROM 12 (Android 12)
ASUS Android 12
ASUS Android 13
This method seems not to work in Android 11

Categories

Resources