[ASUS ZenFone 8] bnsmb:
How to make files in /system writable

In Android 12 and newer /system is mounted read-only can not be remounted read-write anymore.

Sometimes it's useful that one or more files in /system are writable (for example for develop tasks or for testing)

This can be implemented using Magisk (see How to change files in the directory /system for more details)

Example :

Make the file /system/etc/vimrc writable

Note:

In Android 12 /etc is a symbolic link to /system/etc.

Open a (adb) shell as user root and do

# create a dummy Magisk module
#
mkdir -p /data/adb/modules/writable_system/system/etc

# copy the file that should be writable to the Magisk module directory
#
cp /system/etc/vimrc /data/adb/modules/writable_system/system/etc/

# make the file in the Magisk module directory writable
#
chmod +w /data/adb/modules/writable_system/system/etc/vimrc

Now reboot the phone.

After the reboot the file /system/etc/vimrc is writable by the user root, Example:

ASUS_I006D:/ # id
uid=0(root) gid=0(root) groups=0(root) context=u:r:magisk:s0
ASUS_I006D:/ #

ASUS_I006D:/ # ls -l /system/etc/vimrc
-rw-r--r-- 0 root root 3350 2022-11-04 11:36 /system/etc/vimrc

ASUS_I006D:/ # tail -2 /system/etc/vimrc
\ | wincmd p | diffthis
endif
ASUS_I006D:/ #

ASUS_I006D:/ # echo '" Test Comment' >>/system/etc/vimrc
ASUS_I006D:/ #

ASUS_I006D:/ # tail -2 /system/etc/vimrc
endif
" Test Comment
ASUS_I006D:/ #

Only the user root can access the directory /data/adb. Therefor the files configured using this approach are only writable by the user root.

To make a file in /system writable for non-root users use this method:

Open a (adb) shell and execute as user shell:

#
# create a directory that is writable for the user shell
#
mkdir /data/local/tmp/writable_system

mkdir /data/local/tmp/writable_system/etc

#
# copy the file that should be writable to that directory
#
cp /system/etc/vimrc /data/local/tmp/writable_system/etc

The next commands must be executed as user root:

# create dummy Magisk module
#
mkdir -p /data/adb/modules/writable_system/system/etc
#
# create a symbolic link to the file in the writable directory in the directory with the dummy Magisk module
#
ln -s /data/local/tmp/writable_system/etc/vimrc /data/adb/modules/writable_system/system/etc

Now reboot the phone.

After the reboot the file /system/etc/vimrc is writable by the user shell, Example:

ASUS_I006D:/ $ id
uid=2000(shell) gid=2000(shell) groups=2000(shell),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),3012(readtracefs) context=u:r:shell:s0
ASUS_I006D:/ $

ASUS_I006D:/ $ tail -2 /system/etc/vimrc
\ | wincmd p | diffthis
endif
ASUS_I006D:/ $

ASUS_I006D:/ $ echo '" Test Comment' >>/system/etc/vimrc
ASUS_I006D:/ $

ASUS_I006D:/ $ tail -2 /system/etc/vimrc
endif
" Test Comment
ASUS_I006D:/ $

Important:

The writable directory can also be in a sub directory in /sdcard. But be aware that /sdcard is mounted late in the boot process so it might be that the overwritten file in /system will be used by the OS when the bind mount points to a non-existent file if using a sub directory in /sdcard.

The changes to the file done using these methods are "persistent" as long as Magisk is installed in the boot partition.

To restore the file with the original contents after each new reboot of the phone without removing the writable config open a (adb) shell as user root and execute:

#
# restore the file /data/adb/modules/writable_system/system/etc/vimrc from the original file /system/etc/vimrc
#
# this must be done before Magisk creates the bind mounts
#
echo "cp /system/etc/vimrc /data/adb/modules/writable_system/system/etc/vimrc">/data/adb/post-fs-data.d/restore_vimrc.sh
chmod 755 /data/adb/post-fs-data.d/restore_vimrc.sh

Now the file in the dummy Magisk module will be restored with the contents of the original file from /system after each reboot

To temporary access the original file from /system just stop the Magisk daemon, Example:

ASUS_I006D:/ # echo '"Test Test' >>/etc/vimrc
ASUS_I006D:/ #

ASUS_I006D:/ # tail -1 /etc/vimrc
"Test Test
ASUS_I006D:/ #

ASUS_I006D:/ # id
uid=0(root) gid=0(root) groups=0(root) context=u:r:magisk:s0
ASUS_I006D:/ #

ASUS_I006D:/ # magisk --stop
ASUS_I006D:/ #

ASUS_I006D:/ # id
uid=0(root) gid=0(root) groups=0(root) context=u:r:magisk:s0

ASUS_I006D:/ #
ASUS_I006D:/ # tail -1 /etc/vimrc
endif
ASUS_I006D:/ #

Note

Stopping the Magisk daemon will disable all bind mounts done by Magisk.

Restarting the Magisk daemon will not re-create the bind mount - to re-activate the bind mount for the writable file after stopping the Magisk daemon the phone must be rebooted.

To make more then one file writable in a sub directory in /system you can also replace the complete folder using these commands as user root:

#
# make all files in /system/etc writable by the user root
#
mkdir -p /data/adb/modules/writable_system/system/etc/

cd /system/etc
find . | cpio -pdum /data/adb/modules/writable_system/system/etc/

touch /data/adb/modules/writable_system/system/etc/.replace

Now Magisk will replace the directory /system/etc with the directory /data/adb/modules/writable_system/system/etc after the next reboot

Notes

You should test these commands with a not important file like /system/etc/vimrc before changing important files.

It is NOT recommended to use this approach on productive phones.

See How to change any file or directory using Magisk for another approach to change files on read-only mounted filesystems.

Trouble Shooting

As always: If something does not work like expected check the Magisk log file /cache/magisk.log and also check the infos in this post.