Documentation for the script  create_overlay_mount.sh

Last Update: 17.06.2025/bs


Contents


  1. Documentation for the script  create_overlay_mount.sh
    1. Contents
    2. Introduction
    3. Author
    4. LIcense
    5. History
    6. Details
      1. Usage examples
      2. Environment variables used by the script
    7. Test Environment
    8. Trouble Shooting
    9. Links



Introduction


Since Android 10 many file systems in the Android OS are only mounted read-only and can no longer be mounted writable even by the root user. This is safe, but extremely unattractive.

One way to circumvent these restrictions is to install Magisk and Magisk modules. Magisk uses bind mounts to change or create files in the read-only file systems. This works very well to create or change binaries in /system/bin, for example. However, when creating the Magisk module you need to know which files are to be added or replaced.

To install new tools directly in Android via “make install”, for example, this does not work

A more flexible solution is the use of overlay mounts. As far as I know, overlay mounts have been supported in Android since Android 10 (at least partially).

For those who have Magisk installed, overlay mounts for the standard read-only directories can be created using the Magisk module

https://github.com/Magisk-Modules-Alt-Repo/magisk_overlayfs

That Magisk module also works perfectly in the Android 15.

(see How to create Magisk Modules that install new files in system for Details).


Because overlay mounts are supported by Android out-of-the-box, Magisk is not mandatory to use overlay mounts in Android.

Therefor I wrote a little script to manually create and use overlay mounts in Android on rooted devices:

create_overlay_mount.sh

The usage for the script is:

ASUS_I006D:/data/local/tmp $ ./create_overlay_mount.sh  -h

 create_overlay_mount.sh - create one or more overlay mounts on a device running a rooted Android OS

 Usage:  create_overlay_mount.sh [-h|--help] [--verbose|-v] [--noselinux] [--selinux] [--initdisk|--format] [--details] [--short] [--active] [var=value]
                                 [help] [vars] [list] [test] [undo] [diff] [get] [restore] [mount_only] [mount] [umount] [remount] [directory0] [... directory#]

ASUS_I006D:/data/local/tmp #


To view the detailed usage help use the parameter -v -h or help:


./create_overlay_mount.sh help
ASUS_I006D:/data/local/tmp $ ./create_overlay_mount.sh  help

 create_overlay_mount.sh - create one or more overlay mounts on a device running a rooted Android OS

 Usage:  create_overlay_mount.sh [-h|--help] [--verbose|-v] [--noselinux] [--selinux] [--initdisk|--format] [--details] [--short] [--active] [var=value]
                                 [help] [vars] [list] [test] [undo] [diff] [get] [restore] [mount_only] [mount] [umount] [remount] [directory0] [... directory#]

 The parameter that neither start with a "-" or "/" nor contain a "=" are the action parameter that determine what is to be done.
 Only one action parameter for a run is allowed.

 Without an action parameter the script prints the short usage help. If one more directories are found in the parameter the default action is "mount".

 All parameter starting with a "/" are considered to be a filename or directory name.
 The parameter with the directory names are optional.

 The default directory list for the actions "mount", "diff", "get" and "undo" is the list of directories in the environment variable DIRS_TO_OVERLAY.
 The default directory list for the actions "test", "umount", and "remount" is the list of directories currently mounted to an overlay filesystem.

 There are no default values for the action "restore"; the actions "mount_only" and "list" ignore directory parameter.

 The actions "vars" and "help" only print help messages.

 If the variable DIRS_TO_OVERLAY is empty the script uses the hardcoded default value for this variable; that is: /system_ext /vendor /product  /odm  /system

 "directory#" must be either "default", "none", or the fully qualified directory name of a directory.
 The value "none" deletes the current list of directories in the variable DIRS_TO_OVERLAY; the value "default" adds the default directories to the list
 of directories.. The parameter can be used more than once.
 
 The known option parameter are:
 
 --verbose    print more messages
 --noselinux  disable SELinux at start of the script (SELinux is NOT enabled again by the script)
 --selinux    enable SELinux at start of the script (SELinux is NOT disabled again by the script)
 --initdisk   format the virtual disk before creating the overlay mounts; this will undo all previous changes in the filesystems
              Without this option the script never formats an existing virtual disk.
 --details    print more details
 --short      print only the important information
 --active     the tasks diff, get, and undo work only on the currently mounted overlay filesystesm if this option is used

 The known action parameter are:

 help         print verbose usage help
 vars         print only the list of supported environment variables
 list         list directories mounted on overlay filesystems
 test         test write access to directories mounted on overlay filesystems;
              default is: test write access to all directories with mounted on overlay filesystems
 undo         delete all changes done in a directory with an overlay mount
              default is: delete all changes done for all directories configured (regardless of the mount status)
 diff         list the file changes for directories with overlay mounts
              default is: list the changes done for all directories configured (regardless of the mount status)
 get          print the name of the backend used for a file or directory mounted on an overlay filesystem
 restore      restore a file or directory mounted on an overlay filesystem

 mount_only   mount the virtual disk and exit
 mount        mount the overlays for the directories
 umount       umount the overlays for the directories; default is to umount all overlays
 remount      remount the overlay mounts

 Other supported parameter:

 var=value sets the variable "var" to the value "value"

 Notes
 
 Set the variable TRACE to any value before starting script execute it with "set -x"


Supported environment variables:

Name                   Default Value
----                   -------------
IMAGE_FILE             /data/local/tmp/image001
BASEDIR                /data/local/tmp/ov
DIRS_TO_OVERLAY        /system_ext /vendor /product /odm /system
FILESYSTEM_TO_USE      ext4
FILESYSTEM_SIZE        100m
MKFS_OPTIONS          
MOUNT_OPTIONS         
SELINUX_CONTEXT        u:object_r:system_file:s0

ASUS_I006D:/data/local/tmp #

----


See the details below for usage examples of the script.



Author


Bernd Schemmer (Bernd.Schemmer@gmx.de)



LIcense


License
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.






History


ChangeLog

17.06.2025 /bs

Initial release



------


Details


The script must be executed by the root user to create the overlay mounts. In addition, root access is necessary to create or change files or directories in the system directories mounted to overlay mounts.

The filesystem type used for the filesystem mounted on /data does not support overlay mounts. Therefore, the script creates a file, configures that file as virtual disk, formats the virtual disk with the ext4 filesystem and mounts the virtual disk. The filesystem on the virtual disks is than used as backend for the overlay mounts. If the virtual disk already exists, the script uses it again without formating the virtual disk.

All changes in the directories mounted via overlay mounts are saved on the virtual disk. Therefore, the changes in the directories that are mounted via the overlay file system are persistent as long as the virtual disk used as the backend for the overlay mounts exists.

Overlay mounts can be created for most of the directories, except for directories in the filesystem mounted to /data and some directories with special meaning (like /dev, /sys, /proc detc.) or directories with special SELinux context like /oem.

If the script is executed without a parameter, the script prints the short usage help.

If there are one or more directories in the parameter but no action parameter, the default action is mount .

If the script is exeucted with an action parameter and one or more directories in the parameter, the requested action is done only for the directories in the parameter.

If the script is executed with an action parameter but without a directory, the action is done for the directories in the default directory list.

The default directory list used by the different actions are:

Action
Default directories
Comment
mount
directories listed in the environment variable DIRS_TO_OVERLAY

diff
directories listed in the environment variable DIRS_TO_OVERLAY
the action is done regardless of the mount status of the directories

use the option --active to process only the mounted overlay filesystems
undo
directories listed in the environment variable DIRS_TO_OVERLAY
the action is done regardless of the mount status of the directories

use the option --active to process only the mounted overlay filesystems



test
directories currently mounted with an overlay filesystem

umount
directories currently mounted with an overlay filesystem
remount
directories currently mounted with an overlay filesystem
get
directories listed in the environment variable DIRS_TO_OVERLAY use the option --active to process only the mounted overlay filesystems



restore
n/a
there are no default files or directories for this action
list
n/a
The action always lists all directories currently mounted with an overlay filesystem
Use the option --details to also list the backend directory and backend disk for each overlay mount
mount_only
n/a



To explicitly request one of the actions only for the directories listed in the variable DIRS_TO_OVERLAY, use the parameter default.


The default value for the variable DIRS_TO_OVERLAY hard-coded in the script is: /system_ext /vendor /product /odm /system  



Usage examples


To create the overlay mounts, use the the script parameter mount.

Example output of executing the script with the parameter mount the first time:

/data/local/tmp/create_overlay_mount.sh mount

ASUS_I006D:/ # date
Wed Jun 18 06:57:54 CEST 2025
ASUS_I006D:/ #
ASUS_I006D:/ # id
uid=0(root) gid=0(root) groups=0(root) context=u:r:magisk:s0
ASUS_I006D:/ #
ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh

 create_overlay_mount.sh v1.0.0 - create one or more overlay mounts on a device running a rooted Android OS

 Usage:  create_overlay_mount.sh [-h|--help] [--version] [--verbose|-v] [--noselinux] [--selinux] [--initdisk|--format] [--details] [--short] [--active] [var=value]
                                 [help] [vars] [list] [test] [undo] [diff] [get] [restore] [mount_only] [mount] [umount] [remount] [directory0] [... directory#] [default]

ASUS_I006D:/ #

ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh mount
Creating the image file "/data/local/tmp/image001" with the size 100m ...
1+0 records in
1+0 records out
104857600 bytes (100 M) copied, 0.093 s, 1.0 G/s
Creating the loop device for the file "/data/local/tmp/image001" ....
Creating an "ext4" filesystem on the loop device "/dev/block/loop37" now ...
mke2fs 1.46.6 (1-Feb-2023)
Discarding device blocks: done                           
Creating filesystem with 102400 1k blocks and 25584 inodes
Filesystem UUID: 975b3b47-73af-4759-92bf-b83d80c5f85c
Superblock backups stored on blocks:
    8193, 24577, 40961, 57345, 73729

Allocating group tables: done                           
Writing inode tables: done                           
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

Mounting the loop device "/dev/block/loop37" to "/data/local/tmp/ov" ...
Creating the directory "/data/local/tmp/ov/upper" ...
Creating the directory "/data/local/tmp/ov/merged" ...
Creating the directory "/data/local/tmp/ov/work" ...

Creating and mounting the directories for the overlay mount for "/system_ext" ...
Creating the directory "/data/local/tmp/ov/upper/system_ext" ...
Creating the directory "/data/local/tmp/ov/merged/system_ext" ...
Creating the directory "/data/local/tmp/ov/work/system_ext" ...
Creating the overlay mount for "/system_ext" ...
Creating the bind mount "/system_ext"...
Checking the overlay mount for "/system_ext" ...

Creating and mounting the directories for the overlay mount for "/vendor" ...
Creating the directory "/data/local/tmp/ov/upper/vendor" ...
Creating the directory "/data/local/tmp/ov/merged/vendor" ...
Creating the directory "/data/local/tmp/ov/work/vendor" ...
Creating the overlay mount for "/vendor" ...
Creating the bind mount "/vendor"...
Checking the overlay mount for "/vendor" ...

Creating and mounting the directories for the overlay mount for "/product" ...
Creating the directory "/data/local/tmp/ov/upper/product" ...
Creating the directory "/data/local/tmp/ov/merged/product" ...
Creating the directory "/data/local/tmp/ov/work/product" ...
Creating the overlay mount for "/product" ...
Creating the bind mount "/product"...
Checking the overlay mount for "/product" ...

Creating and mounting the directories for the overlay mount for "/odm" ...
Creating the directory "/data/local/tmp/ov/upper/odm" ...
Creating the directory "/data/local/tmp/ov/merged/odm" ...
Creating the directory "/data/local/tmp/ov/work/odm" ...
Creating the overlay mount for "/odm" ...
Creating the bind mount "/odm"...
Checking the overlay mount for "/odm" ...

Creating and mounting the directories for the overlay mount for "/system" ...
Creating the directory "/data/local/tmp/ov/upper/system" ...
Creating the directory "/data/local/tmp/ov/merged/system" ...
Creating the directory "/data/local/tmp/ov/work/system" ...
Creating the overlay mount for "/system" ...
Creating the bind mount "/system"...
Checking the overlay mount for "/system" ...

Summary:
--------

5 overlay mount(s) created:

  /system_ext
  /vendor
  /product
  /odm
  /system

ASUS_I006D:/ #

---


To only create an overlay mount for the directory /odm_dlkm the script usage is

/data/local/tmp/create_overlay_mount.sh mount /odm_dlkm

or

/data/local/tmp/create_overlay_mount.sh /odm_dlkm


/data/local/tmp/create_overlay_mount.sh /odm_dlkm
ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh /odm_dlkm
The image file "/data/local/tmp/image001" already exists - there should already be a filesystem

Creating and mounting the directories for the overlay mount for "/odm_dlkm" ...
Creating the directory "/data/local/tmp/ov/upper/odm_dlkm" ...
Creating the directory "/data/local/tmp/ov/merged/odm_dlkm" ...
Creating the directory "/data/local/tmp/ov/work/odm_dlkm" ...
Creating the overlay mount for "/odm_dlkm" ...
Creating the bind mount "/odm_dlkm"...
Checking the overlay mount for "/odm_dlkm" ...

Summary:
--------

1 overlay mount(s) created:

  /odm_dlkm

ASUS_I006D:/ #

----

Further examples for the use of the script:


To list the overlay mounts created by the script use the parameter list :

/data/local/tmp/create_overlay_mount.sh list

ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh list
Directories mounted on an overlay filesystem

/system_ext
/vendor
/product
/odm
/system
/odm_dlkm


ASUS_I006D:/ #
 

ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh  list --details
Directories mounted on an overlay filesystem

Directory        Backend Directory
---------        -----------------
/system_ext      /data/local/tmp/ov (Virtual disk: /data/local/tmp/image001)
/vendor          /data/local/tmp/ov (Virtual disk: /data/local/tmp/image001)
/product         /data/local/tmp/ov (Virtual disk: /data/local/tmp/image001)
/odm             /data/local/tmp/ov (Virtual disk: /data/local/tmp/image001)
/system          /data/local/tmp/ov (Virtual disk: /data/local/tmp/image001)

ASUS_I006D:/ #

---


To test the write access in the directories with overlay mounts use the parameter test:

/data/local/tmp/create_overlay_mount.sh test
90|ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh test
Testing the write access for directories mounted on overlay filesystems ...


Testing write access for the directory "/system_ext" ...
  OK, the write access to the directory "/system_ext" works

Testing write access for the directory "/vendor" ...
  OK, the write access to the directory "/vendor" works

Testing write access for the directory "/product" ...
  OK, the write access to the directory "/product" works

Testing write access for the directory "/odm" ...
  OK, the write access to the directory "/odm" works

Testing write access for the directory "/system" ...
  OK, the write access to the directory "/system" works

Testing write access for the directory "/odm_dlkm" ...
  OK, the write access to the directory "/odm_dlkm" works

ASUS_I006D:/ #

---


To list the backend used for a file or directory use the parameter get:

./create_overlay_mount.sh  get  /system_ext/priv-app/OmniControl/testdir
ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh diff /system_ext
List the changes in the directories ...

 ----------------------------------------------------------------------
List the changes in the directory "/system_ext" ...
There is currently an overlay mounted for the directory "/system_ext"
File changes in the directory "/system_ext" :

./priv-app
./priv-app/OmniControl
./priv-app/OmniControl/testdir
./priv-app/OmniControl/testdir/testdir2
./priv-app/OmniControl/testdir/testdir2/testfile3
./priv-app/OmniControl/testdir/testfile2
./priv-app/OmniControl/testfile1

Files or directories deleted in the directory "/system_ext" :

./priv-app/OmniControl/oat/arm64/OmniControl.odex 
./priv-app/OmniControl/oat/arm64/OmniControl.vdex


ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh get /system_ext/priv-app/OmniControl/testdir
/data/local/tmp/ov/upper/system_ext/priv-app/OmniControl/testdir # /system_ext/priv-app/OmniControl/testdir # the directory was changed

ASUS_I006D:/ #

ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh get /system_ext/priv-app/OmniControl/testdir/testdir2
/data/local/tmp/ov/upper/system_ext/priv-app/OmniControl/testdir/testdir2 # /system_ext/priv-app/OmniControl/testdir/testdir2 # the directory was changed

ASUS_I006D:/ #

ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh get /system_ext/priv-app/OmniControl/testdir/testdir2/testfile3
/data/local/tmp/ov/upper/system_ext/priv-app/OmniControl/testdir/testdir2/testfile3 # /system_ext/priv-app/OmniControl/testdir/testdir2/testfile3 # the file was changed

ASUS_I006D:/ #

ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh get /system_ext/priv-app/OmniControl/testdir/testfile2
/data/local/tmp/ov/upper/system_ext/priv-app/OmniControl/testdir/testfile2 # /system_ext/priv-app/OmniControl/testdir/testfile2 # the file was changed

ASUS_I006D:/ #
ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh get /system_ext/priv-app/OmniControl/testfile1
/data/local/tmp/ov/upper/system_ext/priv-app/OmniControl/testfile1 # /system_ext/priv-app/OmniControl/testfile1 # the file was changed

ASUS_I006D:/ #

ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh get /system_ext/priv-app/OmniControl/testfile5
/data/local/tmp/ov/upper/system_ext/priv-app/OmniControl/testfile5 # /system_ext/priv-app/OmniControl/testfile5 # the file was not yet changed or deleted

ASUS_I006D:/ #

ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh get /system_ext/priv-app/OmniControl/oat/arm64/OmniControl.odex
/data/local/tmp/ov/upper/system_ext/priv-app/OmniControl/oat/arm64/OmniControl.odex # the file/directory was deleted

ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh get /system_ext/priv-app/OmniControl/oat/arm64/OmniControl.vdex 
/data/local/tmp/ov/upper/system_ext/priv-app/OmniControl/oat/arm64/OmniControl.vdex # the file/directory was deleted

ASUS_I006D:/ #

------


The options --short and --details can be used change the information printed by the action get:


Other example for get
ASUS_I006D:/data/local/tmp # ./create_overlay_mount.sh  list
Directories mounted on an overlay filesystem

/odm/etc
/vendor


ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # /data/local/tmp/create_overlay_mount.sh  diff /odm/etc /vendor
List the changes in the directories ...

 ----------------------------------------------------------------------
List the changes in the directory "/odm/etc" ...
There is currently an overlay mounted for the directory "/odm/etc"
File changes in the directory "/odm/etc" :

./passwd
./selinux
./selinux/precompiled_sepolicy

Files or directories deleted in the directory "/odm/etc" :

./group


 ----------------------------------------------------------------------
List the changes in the directory "/vendor" ...
There is currently an overlay mounted for the directory "/vendor"
File changes in the directory "/vendor" :

./etc
./etc/vmmgr.conf

Files or directories deleted in the directory "/vendor" :


ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # ./create_overlay_mount.sh  get /vendor /vendor/etc /vendor/etc/vmmgr.conf  /odm /odm/etc /odm/etc/passwd  /odm/etc/group  /vendor/etc/ueventd.rc /odm/etc/build.prop
/data/local/tmp/ov/upper/vendor # /vendor # the directory was changed
/data/local/tmp/ov/upper/vendor/etc # /vendor/etc # the directory was changed
/data/local/tmp/ov/upper/vendor/etc/vmmgr.conf # /vendor/etc/vmmgr.conf # the file was changed
# There is no overlay mount active for "/odm"
/data/local/tmp/ov/upper/odm#etc # /odm/etc # the directory was changed
/data/local/tmp/ov/upper/odm#etc/passwd # /odm/etc/passwd # the file was changed
/data/local/tmp/ov/upper/odm#etc/group # the file/directory was deleted
/data/local/tmp/ov/upper/vendor/etc/ueventd.rc # /vendor/etc/ueventd.rc # the file was not yet changed or deleted
/data/local/tmp/ov/upper/odm#etc/build.prop # /odm/etc/build.prop # the file was not yet changed or deleted

ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # ./create_overlay_mount.sh  get /vendor /vendor/etc /vendor/etc/vmmgr.conf  /odm /odm/etc /odm/etc/passwd  /odm/etc/group  /vendor/etc/ueventd.rc /odm/etc/build.prop    --short
/data/local/tmp/ov/upper/vendor
/data/local/tmp/ov/upper/vendor/etc
/data/local/tmp/ov/upper/vendor/etc/vmmgr.conf
# There is no overlay mount active for "/odm"
/data/local/tmp/ov/upper/odm#etc
/data/local/tmp/ov/upper/odm#etc/passwd
/data/local/tmp/ov/upper/odm#etc/group
/data/local/tmp/ov/upper/vendor/etc/ueventd.rc
/data/local/tmp/ov/upper/odm#etc/build.prop

ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # ./create_overlay_mount.sh  get /vendor /vendor/etc /vendor/etc/vmmgr.conf  /odm /odm/etc /odm/etc/passwd  /odm/etc/group  /vendor/etc/ueventd.rc /odm/etc/build.prop    --details
drwxr-xr-x 3 root shell u:object_r:vendor_file:s0  1024 2025-06-18 07:01 /data/local/tmp/ov/upper/vendor # /vendor # the directory was changed
drwxr-xr-x 2 root shell u:object_r:vendor_configs_file:s0  1024 2025-06-18 09:04 /data/local/tmp/ov/upper/vendor/etc # /vendor/etc # the directory was changed
-rw-r--r-- 1 root root u:object_r:vendor_configs_file:s0  25 2025-06-18 09:04 /data/local/tmp/ov/upper/vendor/etc/vmmgr.conf # /vendor/etc/vmmgr.conf # the file was changed
# There is no overlay mount active for "/odm"
drwxr-xr-x 3 root root u:object_r:vendor_configs_file:s0  1024 2025-06-18 09:05 /data/local/tmp/ov/upper/odm#etc # /odm/etc # the directory was changed
-rw-r--r-- 1 root root u:object_r:vendor_configs_file:s0  7 2025-06-18 09:04 /data/local/tmp/ov/upper/odm#etc/passwd # /odm/etc/passwd # the file was changed
c--------- 1 root root u:object_r:vendor_configs_file:s0  0,   0 2025-06-18 09:05 /data/local/tmp/ov/upper/odm#etc/group # the file/directory was deleted
/data/local/tmp/ov/upper/vendor/etc/ueventd.rc # /vendor/etc/ueventd.rc # the file was not yet changed or deleted
/data/local/tmp/ov/upper/odm#etc/build.prop # /odm/etc/build.prop # the file was not yet changed or deleted

ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # ./create_overlay_mount.sh  get /vendor /vendor/etc /vendor/etc/vmmgr.conf  /odm /odm/etc /odm/etc/passwd  /odm/etc/group  /vendor/etc/ueventd.rc /odm/etc/build.prop    --details --short 
drwxr-xr-x 3 root shell u:object_r:vendor_file:s0  1024 2025-06-18 07:01 /data/local/tmp/ov/upper/vendor
drwxr-xr-x 2 root shell u:object_r:vendor_configs_file:s0  1024 2025-06-18 09:04 /data/local/tmp/ov/upper/vendor/etc
-rw-r--r-- 1 root root u:object_r:vendor_configs_file:s0  25 2025-06-18 09:04 /data/local/tmp/ov/upper/vendor/etc/vmmgr.conf
# There is no overlay mount active for "/odm"
drwxr-xr-x 3 root root u:object_r:vendor_configs_file:s0  1024 2025-06-18 09:05 /data/local/tmp/ov/upper/odm#etc
-rw-r--r-- 1 root root u:object_r:vendor_configs_file:s0  7 2025-06-18 09:04 /data/local/tmp/ov/upper/odm#etc/passwd
c--------- 1 root root u:object_r:vendor_configs_file:s0  0,   0 2025-06-18 09:05 /data/local/tmp/ov/upper/odm#etc/group
/data/local/tmp/ov/upper/vendor/etc/ueventd.rc
/data/local/tmp/ov/upper/odm#etc/build.prop

ASUS_I006D:/data/local/tmp #


-----


To umount all overlay mounts created by the script use the parameter umount (Note that umounting /system fails in most cases due to open files and therefore, a reboot is necessary to umount /system):

/data/local/tmp/create_overlay_mount.sh umount
ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh umount
Umounting the bind mounts ...
Umounting "/system_ext" ...
Umounting "/vendor" ...
Umounting "/product" ...
Umounting "/odm" ...
Umounting "/system" ...
umount: /system: Device or resource busy
 ... done
Sleeping 8 seconds now ...
Umounting the overlay mounts ...
Umounting "/data/local/tmp/ov/merged/system_ext" ...
Umounting "/data/local/tmp/ov/merged/vendor" ...
Umounting "/data/local/tmp/ov/merged/product" ...
Umounting "/data/local/tmp/ov/merged/odm" ...
 ... done

1|ASUS_I006D:/ #

---


To umount only the overlays of the directories /vendor and /odm use this command:

/data/local/tmp/create_overlay_mount.sh  umount /vendor /odm
ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh  umount /vendor /odm
Umounting the directories found in the parameter ...
Umounting the bind mounts ...
Umounting "/vendor" ...
Umounting "/odm" ...
 ... done
Sleeping 8 seconds now ...
Umounting the overlay mounts ...
Umounting "/data/local/tmp/ov/merged/vendor" ...
Umounting "/data/local/tmp/ov/merged/odm" ...
 ... done

ASUS_I006D:/ #


------

Note:

The sleep between umounting the bind mounts and umounting the overlay mounts seems to be necessary. The number of seconds to wait is defined in the variable UMOUNT_WAIT_TIME in the script.

To test another value for this variable use this Syntax:

/data/local/tmp/create_overlay_mount.sh  umount UMOUNT_WAIT_TIME=<new_number_of_seconds>

If the new value is okay, change the value for UMOUNT_WAIT_TIME in the script.



To create an overlay mount for an additional directory, execute the script again, e.g. to create an additional overlay mount for the directory /vendor_dlkm/etc:

/data/local/tmp/create_overlay_mount.sh /vendor_dlkm/etc
ASUS_I006D:/data/local/tmp # /data/local/tmp/create_overlay_mount.sh /vendor_dlkm/etc  
The image file "/data/local/tmp/image001" already exists - there should already be a filesystem

Creating and mounting the directories for the overlay mount for "/vendor_dlkm/etc" ...
ERROR: "/vendor_dlkm/etc" is a symbolic link for "/vendor/vendor_dlkm/etc" -- ignored

Summary:
--------

1 directory(s) missing:

  /vendor_dlkm/etc

ASUS_I006D:/data/local/tmp #


ASUS_I006D:/data/local/tmp # /data/local/tmp/create_overlay_mount.sh /vendor/vendor_dlkm/etc
The image file "/data/local/tmp/image001" already exists - there should already be a filesystem

Creating and mounting the directories for the overlay mount for "/vendor/vendor_dlkm/etc" ...
Creating the directory "/data/local/tmp/ov/upper/vendor#vendor_dlkm#etc" ...
Creating the directory "/data/local/tmp/ov/merged/vendor#vendor_dlkm#etc" ...
Creating the directory "/data/local/tmp/ov/work/vendor#vendor_dlkm#etc" ...
Creating the overlay mount for "/vendor/vendor_dlkm/etc" ...
Creating the bind mount "/vendor/vendor_dlkm/etc"...
Checking the overlay mount for "/vendor/vendor_dlkm/etc" ...

Summary:
--------

1 overlay mount(s) created:

  /vendor/vendor_dlkm/etc

ASUS_I006D:/data/local/tmp #

ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh list
Directories mounted on overlay filesystem

/system
/system_ext
/vendor
/product
/odm

/vendor/vendor_dlkm/etc


ASUS_I006D:/ #

---


Directory parameters for the script overwrite the variable DIRS_TO_OVERLAY. To create an overlay mount for the default directories and additional directories, use the parameter default, e.g.: to create overlay mounts for the default directories and the directories /vendor_dlkm/etc and /odm_dlkm, execute:

/data/local/tmp/create_overlay_mount.sh default /vendor_dlkm/etc /odm_dlkm
ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh default /vendor_dlkm/etc /odm_dlkm
Creating the loop device for the file "/data/local/tmp/image001" ....
The image file already exists - there should already be a filesystem
Mounting the loop device "/dev/block/loop31" to "/data/local/tmp/ov" ...

Creating and mounting the directories for the overlay mount for "/system_ext" ...
Creating the overlay mount for "/system_ext" ...
Creating the bind mount "/system_ext"...

Creating and mounting the directories for the overlay mount for "/vendor" ...
Creating the overlay mount for "/vendor" ...
Creating the bind mount "/vendor"...

Creating and mounting the directories for the overlay mount for "/product" ...
Creating the overlay mount for "/product" ...
Creating the bind mount "/product"...

Creating and mounting the directories for the overlay mount for "/odm" ...
Creating the overlay mount for "/odm" ...
Creating the bind mount "/odm"...

Creating and mounting the directories for the overlay mount for "/system" ...
Creating the overlay mount for "/system" ...
Creating the bind mount "/system"...

Creating and mounting the directories for the overlay mount for "/vendor_dlkm/etc" ...
Creating the overlay mount for "/vendor_dlkm/etc" ...
Creating the bind mount "/vendor_dlkm/etc"...

Creating and mounting the directories for the overlay mount for "/odm_dlkm" ...
Creating the overlay mount for "/odm_dlkm" ...
Creating the bind mount "/odm_dlkm"...

Summary:
--------

7 overlay mount(s) created:

  /system_ext
  /vendor
  /product
  /odm
  /system
  /vendor_dlkm/etc
  /odm_dlkm

ASUS_I006D:/ #

----


To check the contents of the virtual disk used as backend without creating the overlay mounts use the parameter mount_only:

/data/local/tmp/create_overlay_mount.sh mount_only
# create some test files

ASUS_I006D:/ # for i in /system /system_ext /vendor /product /odm/ /vendor_dlkm/etc ; do touch $i/test.$$ ; ls -l $i/test.$$ ; done
-rw-r--r-- 1 root root 0 2025-03-15 21:01 /system/test.5491
-rw-r--r-- 1 root root 0 2025-03-15 21:01 /system_ext/test.5491
-rw-r--r-- 1 root root 0 2025-03-15 21:01 /vendor/test.5491
-rw-r--r-- 1 root root 0 2025-03-15 21:01 /product/test.5491
-rw-r--r-- 1 root root 0 2025-03-15 21:01 /odm//test.5491
-rw-r--r-- 1 root root 0 2025-03-15 21:01 /vendor_dlkm/etc/test.5491

# and reboot the phone

ASUS_I006D:/ # reboot
...

# execute in an adb shell after the reboot

ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh mount_only
Creating the loop device for the file "/data/local/tmp/image001" ....
The image file already exists - there should already be a filesystem
Mounting the loop device "/dev/block/loop31" to "/data/local/tmp/ov" ...

The virtual disk is mounted to "/data/local/tmp/ov"

ASUS_I006D:/ #

The new files are in the sub directory ./upper:

ASUS_I006D:/ # ls -l /data/local/tmp/ov/upper/*/*
-rw-r--r-- 1 root root 0 2025-03-15 21:01 /data/local/tmp/ov/upper/odm/test.5491
-rw-r--r-- 1 root root 0 2025-03-15 21:01 /data/local/tmp/ov/upper/product/test.5491
-rw-r--r-- 1 root root 0 2025-03-15 21:01 /data/local/tmp/ov/upper/system/test.5491
-rw-r--r-- 1 root root 0 2025-03-15 21:01 /data/local/tmp/ov/upper/system_ext/test.5491
-rw-r--r-- 1 root root 0 2025-03-15 21:01 /data/local/tmp/ov/upper/vendor/test.5491
-rw-r--r-- 1 root root 0 2025-03-15 21:01 /data/local/tmp/ov/upper/vendor_dlkm#etc/test.5491
ASUS_I006D:/ #


---


To create a new virtual disk /data/local/tmp/image001_ext3 with 50 MB and ext3 filesystem withoud creating any overlay filesystem use this command:

/data/local/tmp/create_overlay_mount.sh IMAGE_FILE=/data/local/tmp/image001_ext3 FILESYSTEM_TO_USE=ext3 FILESYSTEM_SIZE=50m  mount_only

ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh IMAGE_FILE=/data/local/tmp/image001_ext3 FILESYSTEM_TO_USE=ext3 FILESYSTEM_SIZE=50m  mount_only
Creating the image file "/data/local/tmp/image001_ext3" with the size 50m ...
1+0 records in
1+0 records out
52428800 bytes (50 M) copied, 0.072 s, 694 M/s
Creating the loop device for the file "/data/local/tmp/image001_ext3" ....
Creating an "ext3" filesystem on the loop device "/dev/block/loop37" now ...
mke2fs 1.46.6 (1-Feb-2023)
128-byte inodes cannot handle dates beyond 2038 and are deprecated
Discarding device blocks: done                           
Creating filesystem with 51200 1k blocks and 12824 inodes
Filesystem UUID: 709aad6f-53d0-4a2a-adc6-c230fb7f283d
Superblock backups stored on blocks:
    8193, 24577, 40961

Allocating group tables: done                           
Writing inode tables: done                           
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

Mounting the loop device "/dev/block/loop37" to "/data/local/tmp/ov" ...

The virtual disk is mounted to "/data/local/tmp/ov"

ASUS_I006D:/ #

ASUS_I006D:/ # ls -alZ /data/local/tmp/ov
total 17
drwxr-xr-x 3 root  root  u:object_r:system_file:s0       1024 2025-06-14 10:57 .
drwxrwx--x 9 shell shell u:object_r:shell_data_file:s0   3452 2025-06-14 10:57 ..
drwx------ 2 root  root  u:object_r:unlabeled:s0        12288 2025-06-14 10:57 lost+found
ASUS_I006D:/ #

ASUS_I006D:/ # df -h /data/local/tmp/ov
Filesystem        Size Used Avail Use% Mounted on
/dev/block/loop37  44M  31K   44M   1% /data/local/tmp/ov
ASUS_I006D:/ #

130|ASUS_I006D:/ # mount | grep /data/local/tmp/ov
/dev/block/loop37 on /data/local/tmp/ov type ext3 (rw,seclabel,relatime)
ASUS_I006D:/ #
 
ASUS_I006D:/ # ls -lZh /data/local/tmp/image001_ext3
-rw-r--r-- 1 root root u:object_r:shell_data_file:s0  50M 2025-06-14 11:01 /data/local/tmp/image001_ext3
ASUS_I006D:/ #
 


------


To use the file /data/local/tmp/image001_ext3 for overlay mounts later use:

/data/local/tmp/create_overlay_mount.sh IMAGE_FILE=/data/local/tmp/image001_ext3 /vendor /vendor_dlkm/
ASUS_I006D:/ # /data/local/tmp/create_overlay_mount.sh IMAGE_FILE=/data/local/tmp/image001_ext3 /vendor /vendor_dlkm/
The image file already exists - there should already be a filesystem
Creating the directory "/data/local/tmp/ov/upper" ...
Creating the directory "/data/local/tmp/ov/merged" ...
Creating the directory "/data/local/tmp/ov/work" ...

Creating and mounting the directories for the overlay mount for "/vendor" ...
Creating the directory "/data/local/tmp/ov/upper/vendor" ...
Creating the directory "/data/local/tmp/ov/merged/vendor" ...
Creating the directory "/data/local/tmp/ov/work/vendor" ...
Creating the overlay mount for "/vendor" ...
Creating the bind mount "/vendor"...
Checking the overlay mount for "/vendor" ...

Creating and mounting the directories for the overlay mount for "/vendor_dlkm/" ...
Creating the directory "/data/local/tmp/ov/upper/vendor_dlkm" ...
Creating the directory "/data/local/tmp/ov/merged/vendor_dlkm" ...
Creating the directory "/data/local/tmp/ov/work/vendor_dlkm" ...
Creating the overlay mount for "/vendor_dlkm" ...
Creating the bind mount "/vendor_dlkm"...
Checking the overlay mount for "/vendor_dlkm" ...

Summary:
--------

2 overlay mount(s) created:

  /vendor
  /vendor_dlkm

ASUS_I006D:/ #

 




To use different virtual disks in parallel the variable BASEDIR must also be different:

Example for using multiple virtual disks
ASUS_I006D:/data/local/tmp #  IMAGE_FILE=/data/local/tmp/virtualdisk001 BASEDIR=/data/local/tmp/virtualfs001 ./create_overlay_mount.sh /vendor /vendor_dlkm
Creating the image file "/data/local/tmp/virtualdisk001" with the size 100m ...
1+0 records in
1+0 records out
104857600 bytes (100 M) copied, 0.091 s, 1.0 G/s
Creating the loop device for the file "/data/local/tmp/virtualdisk001" ....
Creating an "ext4" filesystem on the loop device "/dev/block/loop37" now ...
mke2fs 1.46.6 (1-Feb-2023)
128-byte inodes cannot handle dates beyond 2038 and are deprecated
Discarding device blocks: done                           
Creating filesystem with 102400 1k blocks and 25688 inodes
Filesystem UUID: 2e0dbca9-6030-44a1-bff5-49d6a0c4f152
Superblock backups stored on blocks:
    8193, 24577, 40961, 57345, 73729

Allocating group tables: done                           
Writing inode tables: done                           
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

Creating the directory "/data/local/tmp/virtualfs001" ...
Mounting the loop device "/dev/block/loop37" to "/data/local/tmp/virtualfs001" ...
Creating the directory "/data/local/tmp/virtualfs001/upper" ...
Creating the directory "/data/local/tmp/virtualfs001/merged" ...
Creating the directory "/data/local/tmp/virtualfs001/work" ...

Creating and mounting the directories for the overlay mount for "/vendor" ...
Creating the directory "/data/local/tmp/virtualfs001/upper/vendor" ...
Creating the directory "/data/local/tmp/virtualfs001/merged/vendor" ...
Creating the directory "/data/local/tmp/virtualfs001/work/vendor" ...
Creating the overlay mount for "/vendor" ...
Creating the bind mount "/vendor"...
Checking the overlay mount for "/vendor" ...

Creating and mounting the directories for the overlay mount for "/vendor_dlkm" ...
Creating the directory "/data/local/tmp/virtualfs001/upper/vendor_dlkm" ...
Creating the directory "/data/local/tmp/virtualfs001/merged/vendor_dlkm" ...
Creating the directory "/data/local/tmp/virtualfs001/work/vendor_dlkm" ...
Creating the overlay mount for "/vendor_dlkm" ...
Creating the bind mount "/vendor_dlkm"...
Checking the overlay mount for "/vendor_dlkm" ...

Summary:
--------

2 overlay mount(s) created:

  /vendor
  /vendor_dlkm

ASUS_I006D:/data/local/tmp #
ASUS_I006D:/data/local/tmp #
ASUS_I006D:/data/local/tmp # IMAGE_FILE=/data/local/tmp/virtualdisk002 BASEDIR=/data/local/tmp/virtualfs002 ./create_overlay_mount.sh /odm /odm_dlkm
SELinux is currently enabled
Creating the image file "/data/local/tmp/virtualdisk002" with the size 100m ...
1+0 records in
1+0 records out
104857600 bytes (100 M) copied, 0.094 s, 1.0 G/s
Creating the loop device for the file "/data/local/tmp/virtualdisk002" ....
Creating an "ext4" filesystem on the loop device "/dev/block/loop38" now ...
mke2fs 1.46.6 (1-Feb-2023)
128-byte inodes cannot handle dates beyond 2038 and are deprecated
Discarding device blocks: done                           
Creating filesystem with 102400 1k blocks and 25688 inodes
Filesystem UUID: b7e73573-093d-4038-8efa-c7f3975b8932
Superblock backups stored on blocks:
    8193, 24577, 40961, 57345, 73729

Allocating group tables: done                           
Writing inode tables: done                           
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

Creating the directory "/data/local/tmp/virtualfs002" ...
Mounting the loop device "/dev/block/loop38" to "/data/local/tmp/virtualfs002" ...
Creating the directory "/data/local/tmp/virtualfs002/upper" ...
Creating the directory "/data/local/tmp/virtualfs002/merged" ...
Creating the directory "/data/local/tmp/virtualfs002/work" ...

Creating and mounting the directories for the overlay mount for "/odm" ...
Creating the directory "/data/local/tmp/virtualfs002/upper/odm" ...
Creating the directory "/data/local/tmp/virtualfs002/merged/odm" ...
Creating the directory "/data/local/tmp/virtualfs002/work/odm" ...
Creating the overlay mount for "/odm" ...
Creating the bind mount "/odm"...
Checking the overlay mount for "/odm" ...

Creating and mounting the directories for the overlay mount for "/odm_dlkm" ...
Creating the directory "/data/local/tmp/virtualfs002/upper/odm_dlkm" ...
Creating the directory "/data/local/tmp/virtualfs002/merged/odm_dlkm" ...
Creating the directory "/data/local/tmp/virtualfs002/work/odm_dlkm" ...
Creating the overlay mount for "/odm_dlkm" ...
Creating the bind mount "/odm_dlkm"...
Checking the overlay mount for "/odm_dlkm" ...

Summary:
--------

2 overlay mount(s) created:

  /odm
  /odm_dlkm

ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # ./create_overlay_mount.sh list --details
Directories mounted on an overlay filesystem

Directory         Backend Directory
---------         -----------------
/vendor           /data/local/tmp/virtualfs001 (Virtual disk: /data/local/tmp/virtualdisk001)
/vendor_dlkm      /data/local/tmp/virtualfs001 (Virtual disk: /data/local/tmp/virtualdisk001)
/odm              /data/local/tmp/virtualfs002 (Virtual disk: /data/local/tmp/virtualdisk002)
/odm_dlkm         /data/local/tmp/virtualfs002 (Virtual disk: /data/local/tmp/virtualdisk002)

ASUS_I006D:/data/local/tmp #

------


Note that in this case you must always use BASEDIR=<base_directory> and, for some commands IMAGE_FILE=<image_file>, to process the overlay mounts (e.g. for the actions undo, umount, diff, etc). Therefore it's recommended to create different wrapper scripts for using multiple virtual disks.

This feature can be used for example to create different test environments.


The script can also be used to create overlay mounts for sub directories, e.g. to create overlay filesystems for the directories /*/bin and the directory /system_ext/usr/share do

/data/local/tmp/create_overlay_mount.sh /*/bin /system_ext/usr/share
ASUS_I006D:/data/local/tmp # /data/local/tmp/create_overlay_mount.sh /*/bin /system_ext/usr/share                                                                                                                                            
The image file already exists - there should already be a filesystem

Creating and mounting the directories for the overlay mount for "/product/bin" ...
Creating the directory "/data/local/tmp/ov/upper/product#bin" ...
Creating the directory "/data/local/tmp/ov/merged/product#bin" ...
Creating the directory "/data/local/tmp/ov/work/product#bin" ...
Creating the overlay mount for "/product/bin" ...
Creating the bind mount "/product/bin"...

Creating and mounting the directories for the overlay mount for "/system/bin" ...
There is already an overlay mount for the directory "/system/bin" in place

Creating and mounting the directories for the overlay mount for "/system_ext/bin" ...
Creating the directory "/data/local/tmp/ov/upper/system_ext#bin" ...
Creating the directory "/data/local/tmp/ov/merged/system_ext#bin" ...
Creating the directory "/data/local/tmp/ov/work/system_ext#bin" ...
Creating the overlay mount for "/system_ext/bin" ...
Creating the bind mount "/system_ext/bin"...

Creating and mounting the directories for the overlay mount for "/vendor/bin" ...
Creating the directory "/data/local/tmp/ov/upper/vendor#bin" ...
Creating the directory "/data/local/tmp/ov/merged/vendor#bin" ...
Creating the directory "/data/local/tmp/ov/work/vendor#bin" ...
Creating the overlay mount for "/vendor/bin" ...
Creating the bind mount "/vendor/bin"...

Creating and mounting the directories for the overlay mount for "/system_ext/usr/share" ...
Creating the directory "/data/local/tmp/ov/upper/system_ext#usr#share" ...
Creating the directory "/data/local/tmp/ov/merged/system_ext#usr#share" ...
Creating the directory "/data/local/tmp/ov/work/system_ext#usr#share" ...
Creating the overlay mount for "/system_ext/usr/share" ...
Creating the bind mount "/system_ext/usr/share"...

Summary:
--------

4 overlay mount(s) created:

  /product/bin
  /system_ext/bin
  /vendor/bin
  /system_ext/usr/share

1 overlay mount(s) already created:

  /system/bin

ASUS_I006D:/data/local/tmp #

------


To list the file changes for a directory with overlay mount use the parameter diff, e.g. to list all changes for the directories /odm_dlkm and /system:

./create_overlay_mount.sh diff /odm_dlkm /system
90|ASUS_I006D:/data/local/tmp # ./create_overlay_mount.sh  diff /odm_dlkm /system
List the changes in the directories ...

 ----------------------------------------------------------------------
List the changes in the directory "/odm_dlkm" ...
There is currently an overlay mounted for the directory "/odm_dlkm"
File changes in the directory "/odm_dlkm" :

./testdir
./testdir/testfile1
./testdir/testfile2
./testfile0

Files or directories deleted in the directory "/odm_dlkm" :

./etc


 ----------------------------------------------------------------------
List the changes in the directory "/system" ...
There is currently no overlay mounted for the directory "/system"
File changes in the directory "/system" :

./bin
./bin/0001logcatboot
./bin/configure_microg.sh
./bin/correct_dev_pn553.sh
./bin/disable_intent_filter_verification.sh
./bin/enable_microg.sh
./bin/enable_wifi.sh
./bin/enable_wireless_adb.sh
./bin/install_apk.sh
./bin/install_mm.sh
./bin/list_bind_mounts.sh
./bin/list_logical_device_backends.sh
./bin/list_logical_device_usage.sh
./bin/list_magisk_root_permissions.sh
./bin/list_magisk_settings.sh
./bin/lmm
./bin/myldd
./bin/rcbm.sh
./bin/recreate_bind_mount.sh
./bin/remount_dynamic_partitions.sh
./bin/remove_screenlock.sh
./bin/rename_apk.sh
./bin/search_magisk_package.sh
./bin/setpath.sh
./bin/sudo
./bin/switch_adb_via_wifi.sh

Files or directories deleted in the directory "/system" :



ASUS_I006D:/data/local/tmp #
ASUS_I006D:/data/local/tmp # ./create_overlay_mount.sh  diff /odm_dlkm /system --details
SELinux is currently enabled
List the changes in the directories ...

 ----------------------------------------------------------------------
List the changes in the directory "/odm_dlkm" ...
There is currently an overlay mounted for the directory "/odm_dlkm"
File changes in the directory "/odm_dlkm" :

drwxr-xr-x 3 root root u:object_r:vendor_file:s0  1024 2025-06-17 08:59 ./testdir
-rw-r--r-- 1 root root u:object_r:vendor_file:s0     0 2025-06-17 08:59 ./testdir/testfile1
drwxr-xr-x 2 root root u:object_r:vendor_file:s0  1024 2025-06-17 09:00 ./testdir/testfile2
-rw-r--r-- 1 root root u:object_r:vendor_file:s0     0 2025-06-17 09:00 ./testfile0

Files or directories deleted in the directory "/odm_dlkm" :

./etc


 ----------------------------------------------------------------------
List the changes in the directory "/system" ...
There is currently no overlay mounted for the directory "/system"
File changes in the directory "/system" :

drwxr-x--x 2 root shell u:object_r:system_file:s0   1024 2025-06-16 21:04 ./bin
-rwxr-xr-x 1 root root  u:object_r:system_file:s0    156 2025-06-16 21:04 ./bin/0001logcatboot
-rwxr-xr-x 1 root root  u:object_r:system_file:s0   2919 2025-06-16 21:04 ./bin/configure_microg.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0    354 2025-06-16 21:04 ./bin/correct_dev_pn553.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0     51 2025-06-16 21:04 ./bin/disable_intent_filter_verification.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0    146 2025-06-16 21:04 ./bin/enable_microg.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0   2956 2025-06-16 21:04 ./bin/enable_wifi.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0  22230 2025-06-16 21:04 ./bin/enable_wireless_adb.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0  10108 2025-06-16 21:04 ./bin/install_apk.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0  16046 2025-06-16 21:04 ./bin/install_mm.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0   4432 2025-06-16 21:04 ./bin/list_bind_mounts.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0   7271 2025-06-16 21:04 ./bin/list_logical_device_backends.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0   9463 2025-06-16 21:04 ./bin/list_logical_device_usage.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0    223 2025-06-16 21:04 ./bin/list_magisk_root_permissions.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0    449 2025-06-16 21:04 ./bin/list_magisk_settings.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0  19701 2025-06-16 21:04 ./bin/lmm
-rwxr-xr-x 1 root root  u:object_r:system_file:s0   1038 2025-06-16 21:04 ./bin/myldd
lrwxrwxrwx 1 root root  u:object_r:system_file:s0     24 2025-06-16 21:04 ./bin/rcbm.sh -> ./recreate_bind_mount.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0   3774 2025-06-16 21:04 ./bin/recreate_bind_mount.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0  16866 2025-06-16 21:04 ./bin/remount_dynamic_partitions.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0     69 2025-06-16 21:04 ./bin/remove_screenlock.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0   2708 2025-06-16 21:04 ./bin/rename_apk.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0   1434 2025-06-16 21:04 ./bin/search_magisk_package.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0     42 2025-06-16 21:04 ./bin/setpath.sh
-rwxr-xr-x 1 root root  u:object_r:system_file:s0     13 2025-06-16 21:04 ./bin/sudo
-rwxr-xr-x 1 root root  u:object_r:system_file:s0   5273 2025-06-16 21:04 ./bin/switch_adb_via_wifi.sh

Files or directories deleted in the directory "/system" :



ASUS_I006D:/data/local/tmp #



----

The default directory list for the action diff is the list of directories in the variable DIRS_TO_OVERLAY.  Use the options --active to list only the changes in all mounted overlay filesystems:


./create_overlay_mount.sh  diff --active
ASUS_I006D:/data/local/tmp # ./create_overlay_mount.sh  list
Directories mounted on an overlay filesystem

/odm/etc
/vendor


ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # ./create_overlay_mount.sh  diff --active
List the changes in the directories ...

 ----------------------------------------------------------------------
List the changes in the directory "/odm/etc" ...
There is currently an overlay mounted for the directory "/odm/etc"
File changes in the directory "/odm/etc" :

./passwd
./selinux

Files or directories deleted in the directory "/odm/etc" :

./group


 ----------------------------------------------------------------------
List the changes in the directory "/vendor" ...
There is currently an overlay mounted for the directory "/vendor"
File changes in the directory "/vendor" :

./etc
./etc/vmmgr.conf

Files or directories deleted in the directory "/vendor" :



ASUS_I006D:/data/local/tmp #

----


To undo all changes for a directory with an overlay mount use the parameter undo, e.g. to undo all changes in the directory /system execute:

/create_overlay_mount.sh undo /system
ASUS_I006D:/data/local/tmp # ./create_overlay_mount.sh  undo /system
Undoing the change in the directories ...
Undoing the changes for the directory "/system" ...

ASUS_I006D:/data/local/tmp #

------


To undo all the changes for all directories currently mounted on overlay filesystems do:

./create_overlay_mount.sh  undo
ASUS_I006D:/data/local/tmp # ./create_overlay_mount.sh  undo
Undoing the change in the directories ...
Undoing the changes for the directory "/system_ext" ...
Undoing the changes for the directory "/vendor" ...
Undoing the changes for the directory "/product" ...
Undoing the changes for the directory "/odm" ...
Undoing the changes for the directory "/system" ...

ASUS_I006D:/data/local/tmp #

------

Note that there is no redo.


To undo the changes only for specific files use the parameter restore:

./create_overlay_mount.sh restore /system/etc/hosts
|ASUS_I006D:/data/local/tmp # cat /system/etc/hosts
127.0.0.1       localhost
::1             ip6-localhost
ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # echo "1.1.1.1 dnsserver" >>/system/etc/hosts
ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # cat /system/etc/hosts                                                                                                                                                 
127.0.0.1       localhost
::1             ip6-localhost
1.1.1.1 dnsserver
ASUS_I006D:/data/local/tmp #


ASUS_I006D:/data/local/tmp # ./create_overlay_mount.sh restore /system/etc/hosts
Deleting the files "/data/local/tmp/ov/upper/system/etc/hosts" and "/data/local/tmp/ov/merged/system/etc/hosts" ...
Restoring the file "/system/etc/hosts" ...

ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # cat /system/etc/hosts
127.0.0.1       localhost
::1             ip6-localhost
ASUS_I006D:/data/local/tmp #




To restore a deleted file on a filesystem mount with overlays use the parameter restore :

./create_overlay_mount.sh restore /odm/etc/build.prop
ASUS_I006D:/data/local/tmp # ls -l /odm/etc/build.prop
-rw------- 1 root root 999 2009-01-01 01:00 /odm/etc/build.prop
ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # rm /odm/etc/build.prop
ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # ls -l /odm/etc/build.prop
ls: /odm/etc/build.prop: No such file or directory
1|ASUS_I006D:/data/local/tmp #

1|ASUS_I006D:/data/local/tmp # ./create_overlay_mount.sh restore /odm/etc/build.prop
Restoring the file "/odm/etc/build.prop" ...

ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # ls -l /odm/etc/build.prop
-rw------- 1 root root 999 2009-01-01 01:00 /odm/etc/build.prop
ASUS_I006D:/data/local/tmp #



------


In case of an error in a directory with an overlay you may remount the directory using the script parameter remount:

 ./create_overlay_mount.sh remount /vendor
ASUS_I006D:/data/local/tmp # ./create_overlay_mount.sh remount /vendor
Remounting the bind mounts ...
Remounting "/vendor" ...
 ... done

ASUS_I006D:/data/local/tmp #



------



Environment variables used by the script



The script uses these environment variables:


Variable
Usage
Default value
Comment
IMAGE_FILE file used for the virtual disk
/data/local/tmp/image001

BASEDIR the mount point for the virtual disk /data/local/tmp/ov

DIRS_TO_OVERLAY the directories for which the script creates an overlay mount /system_ext
/vendor
/product
/odm
/system

FILESYSTEM_TO_USE the filesystem used on the virtual disk
ext4
must be a filesystem known by the running Android that supports overlay mounts (e.g. ext4 or ext3)

The parameter is only used when creating a new filesystem on the virtual disk.
 
FILESYSTEM_SIZE the size of the virtual disk 100m
the value can be any value that is known by the binary dd for the parameter bs (see the output of "dd --help")

The variable is only used when the virtual disk is created.
MKFS_OPTIONS additional options for the mkfs* command to create the filesysten on the loop device
The variable is only used when the virtual disk is created.
MOUNT_OPTIONS additional options for the mount command to mount the filesystem on the loop device

SELINUX_CONTEXT the SELinux context used for new directories if the script can not read the SELinux context of an existing directory u:object_r:system_file:s0











To change one or more of these variables use either a command like this

IMAGE_FILE="/data/local/tmp/image002" BASEDIR="/data/local/tmp/ov2" create_overlay_mount.sh

or this

create_overlay_mount.sh IMAGE_FILE="/data/local/tmp/image002" BASEDIR="/data/local/tmp/ov2"


Note:

Use

create_overlay_mount.sh vars

to only print the current list of supported environment variables with default values.


The new files created in the directories with overlay mounts can be found in the directory

${BASEDIR}/upper/${DIR_NAME}

e.g.

ASUS_I006D:/data/local/tmp # df -h /odm
Filesystem      Size Used Avail Use% Mounted on
overlay          93M  71K   93M   1% /odm
ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # touch /odm/testfile.$$
ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # ls -l /odm/testfile.$$                                                                                   
-rw-r--r-- 1 root root 0 2025-06-14 14:13 /odm/testfile.7172
ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # ls -l /data/local/tmp/ov/upper/odm/testfile.7172
-rw-r--r-- 1 root root 0 2025-06-14 14:13 /data/local/tmp/ov/upper/odm/testfile.7172
ASUS_I006D:/data/local/tmp #



For sub directories with overlay mounts the directory name in the directory ${BASEDIR}/upper is in the format subir1#subdir2#....#subdirN,

For an overlay mount for /vendor/etc the directory name is vendor#etc:

ASUS_I006D:/data/local/tmp # df -h /vendor
Filesystem      Size Used Avail Use% Mounted on
/dev/block/dm-4 0.9G 983M   29M  98% /vendor
ASUS_I006D:/data/local/tmp #                                                                                                          

ASUS_I006D:/data/local/tmp # df -h /vendor/etc
Filesystem      Size Used Avail Use% Mounted on
overlay          93M  76K   93M   1% /vendor/etc
ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # touch /vendor/etc/testfile.$$
ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # ls -l /vendor/etc/testfile.$$                                                                            
-rw-r--r-- 1 root root 0 2025-06-14 14:15 /vendor/etc/testfile.7172
ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # ls -l /data/local/tmp/ov/upper/vendor\#etc/testfile.7172                                                 
-rw-r--r-- 1 root root 0 2025-06-14 14:15 /data/local/tmp/ov/upper/vendor#etc/testfile.7172
ASUS_I006D:/data/local/tmp #

 

For deleted files or directories a character device with major 0 and minor 0 is created in the directory ./upper, e.g:

ASUS_I006D:/data/local/tmp # rm /vendor/etc/ueventd.rc                                                                                
ASUS_I006D:/data/local/tmp #

ASUS_I006D:/data/local/tmp # ls -l /vendor/etc/ueventd.rc                                                                             
ls: /vendor/etc/ueventd.rc: No such file or directory

1|ASUS_I006D:/data/local/tmp #
1|ASUS_I006D:/data/local/tmp # ls -l /data/local/tmp/ov/upper/vendor\#etc/ueventd.rc                                                  
c--------- 1 root root 0,   0 2025-06-14 14:17 /data/local/tmp/ov/upper/vendor#etc/ueventd.rc
ASUS_I006D:/data/local/tmp #



ext3 and ext4 filesystems can be increased while mounted:

Instructions to increase the virtual disk used as backend
# Note: only the commands in bold are necessary to increase the virtual disk

ASUS_I006D:/ # ls -lh /data/local/tmp/image001
-rw-r--r-- 1 root root 10M 2025-03-15 20:36 /data/local/tmp/image001
ASUS_I006D:/ #

# -> the size of the file used as virtual disk is 10 MB

ASUS_I006D:/ # df -h /data/local/tmp/ov
Filesystem        Size Used Avail Use% Mounted on
/dev/block/loop31 8.6M  39K  8.6M   1% /data/local/tmp/ov
ASUS_I006D:/ #

# increase the size of the file /data/local/tmp/image001 by 50M

ASUS_I006D:/ # dd if=/dev/zero count=1 bs=50m >>/data/local/tmp/image001
1+0 records in
1+0 records out
52428800 bytes (50 M) copied, 0.058147 s, 860 M/s
ASUS_I006D:/ #

ASUS_I006D:/ # ls -lh /data/local/tmp/image001
-rw-r--r-- 1 root root 60M 2025-03-15 20:38 /data/local/tmp/image001
ASUS_I006D:/ #


# -> the size of the file used as virtual disk is now 60 MB

# update the loop device
#
ASUS_I006D:/ # losetup -j /data/local/tmp/image001 -c
ASUS_I006D:/ #

# resize the filesystem on the virtual disk
#
ASUS_I006D:/ # resize2fs /dev/block/loop31
resize2fs 1.46.2 (28-Feb-2021)
Filesystem at /dev/block/loop31 is mounted on /data/local/tmp/ov; on-line resizing required
old_desc_blocks = 1, new_desc_blocks = 1
The filesystem on /dev/block/loop31 is now 61440 (1k) blocks long.

ASUS_I006D:/ #

ASUS_I006D:/ # df -h /data/local/tmp/ov
Filesystem        Size Used Avail Use% Mounted on
/dev/block/loop31  58M  39K   58M   1% /data/local/tmp/ov
ASUS_I006D:/ #



Note:

ext4 filesystem can also be decreased when the filesystem is not mounted but it is not that easy to shrink the file used for the virtual disk.

----

 
Notes


Run the script only in an adb session as root user -- do not execute it via "su - -c ...." (after creating an overlay mount for /system, the binary su is not available anymore!)


For first tests, I strongly recommend NOT to create an overlay mount for the directory /system:

If something fails when creating an overlay for /system, there is no access to any of the executables and files in /system anymore and a reboot via Android GUI is required to fix that


The script does not support directory names with a hash "#" in the name.


To check, if overlay filesystems are supported in the Android OS use the command:

grep overlay /proc/filesystems

The output should look like this:

ASUS_I006D:/data/local/tmp #  grep overlay /proc/filesystems
nodev    overlay
ASUS_I006D:/data/local/tmp #


Please note that files created with Magisk modules, e.g. in /system/bin, are no longer visible after configuring an overlay mount for /system using the script create_overlay_mount.sh. That's also true for the executable "su" necessary to become root user if Magisk is installed. Therefore, either open enough adb sessions with root access before doing the overlay mount for /system or use a CustomROM with enabled root access.


You can copy the files from the Magisk module to /system after creating an overlay mount for that directory, example

Copy the files from the Magisk module myscripts to /system:
 
cp -r /data/adb/modules/myscripts/system/* /system 


Another way to work around the problem of the missing su command is to start the sshd as root user on the phone before creating the overlay mount for /system.


Or use a Magisk Module to start the adb daemon as root user (see here)
https://xdaforums.com/t/how-to-automatically-start-adbd-as-root-user-after-starting-the-phone.4682701/


If Magisk is installed, I recommend using the Magisk module for the implementation of overlay mounts, as the overlay mounts are created very early in the boot process in the Magisk module. The overlay mounts created by the Magisk module also do not overwrite bind mounts created by other Magisk modules and "su" via Magisk is still possible in adb sessions when using this Magisk module.


Do not use the Magisk module for the implementation of overlay mounts and the script create_overlay_mount.sh in parallel.


create_overlay_mount.sh can be used to mount the virtual disk used by the Magisk Module for overlay mounts, /data/adb/modules/magisk_overlayfs/overlay.img, but the directory structure on that virtual disk is different and therefore the virtual disk should not be used to create overlay mounts with create_overlay_mount.sh .

Details
ASUS_I006D:/data/local/tmp # IMAGE_FILE=/data/adb/modules/magisk_overlayfs/overlay.img ./create_overlay_mount.sh  mount_only
SELinux is currently enabled
Creating the loop device for the file "/data/adb/modules/magisk_overlayfs/overlay.img" ....
The image file "/data/adb/modules/magisk_overlayfs/overlay.img" already exists - there should already be a filesystem
Mounting the loop device "/dev/block/loop37" to "/data/local/tmp/ov" ...

The virtual disk is mounted to "/data/local/tmp/ov"

ASUS_I006D:/data/local/tmp #     

ASUS_I006D:/data/local/tmp # ls -ld $( find /data/local/tmp/ov )
drwxr-xr-x 4 root root    1024 2025-06-16 21:10 /data/local/tmp/ov
drwx------ 2 root root   12288 2025-06-16 21:10 /data/local/tmp/ov/lost+found
drwxr-xr-x 3 root root    1024 2025-06-16 21:10 /data/local/tmp/ov/system
drwxr-xr-x 2 root root    1024 2025-06-16 21:10 /data/local/tmp/ov/system/bin
lrwxrwxrwx 1 root root      18 2025-06-16 21:10 /data/local/tmp/ov/system/bin/magic_remount_ro -> ./overlayfs_system
lrwxrwxrwx 1 root root      18 2025-06-16 21:10 /data/local/tmp/ov/system/bin/magic_remount_rw -> ./overlayfs_system
-rwxrwxrwx 1 root root 6960576 2025-06-16 21:10 /data/local/tmp/ov/system/bin/overlayfs_system
ASUS_I006D:/data/local/tmp #

------



Test Environment



ASUS Zenfone 8 with

/e/ 3.0 (= Android 13)
LineageOS 20 (= Android 13)
LineageOS 21 (= Android 14)
OmniROM 14 (= Android 14)
OmniROM 15 (= Android 15)


Note:

According to ChatGPT this functionality does not work on all Android versions (but ChatGTP is sometimes also a great liar ...)




Trouble Shooting



An overlay mount for sub directories like /system_ext/bin or /system/etc may or may not work.

If it does not work, the files in the sub directory with overlay mount do not have any permission, example:

ASUS_I006D:/data/local/tmp # ls -ldZ /system_ext/bin/*
---------- 1 root root  u:object_r:unlabeled:s0   0 1970-01-04 04:35 /system_ext/bin/adb_root
lrwxrwxrwx 1 root root  u:object_r:unlabeled:s0  16 1970-01-04 04:35 /system_ext/bin/bash -> /system/bin/bash
---------- 1 root root  u:object_r:unlabeled:s0   0 1970-01-04 04:35 /system_ext/bin/dpmd
lrwxrwxrwx 1 root root  u:object_r:unlabeled:s0   3 1970-01-04 04:35 /system_ext/bin/eview -> vim
lrwxrwxrwx 1 root root  u:object_r:unlabeled:s0   3 1970-01-04 04:35 /system_ext/bin/evim -> vim
lrwxrwxrwx 1 root root  u:object_r:unlabeled:s0   3 1970-01-04 04:35 /system_ext/bin/ex -> vim
lrwxrwxrwx 1 root root  u:object_r:unlabeled:s0   3 1970-01-04 04:35 /system_ext/bin/gview -> vim
lrwxrwxrwx 1 root root  u:object_r:unlabeled:s0   3 1970-01-04 04:35 /system_ext/bin/gvim -> vim
lrwxrwxrwx 1 root root  u:object_r:unlabeled:s0   3 1970-01-04 04:35 /system_ext/bin/gvimdiff -> vim
---------- 1 root root  u:object_r:unlabeled:s0   0 1970-01-04 04:35 /system_ext/bin/htop
---------- 1 root root  u:object_r:unlabeled:s0   0 1970-01-04 04:35 /system_ext/bin/nano
...

create_overlay_mount.sh prints a warning in this case, example:

WARNING: Seems like the overlay mount for "/system_ext/bin" works only partial -- please check the directory contents


To work around this problem, create an overlay mount for the upper directory (e.g. /system or /system_ext) -- at least in my tests, overlay mounts for these directories have always worked.

In my tests on the different Android versions there were always such errors, but not for the same subdirectories. There is no error message in logcat or dmesg, so I don't know the reason for this error yet.


Use the script parameter -v or --verbose to print more messages


Set the variable TRACE to any string before executing the script to run it with "set -x"


Most problems with overlay mounts are caused by missing or invalid SELinux contexts for the files and directories for which an overlay mount is configured. It is therefore recommended to
temporarily disable SELinux either by using the command

setenforce 0

or use the script parameter "--noselinux"

Start a parallel adb session with the command

logcat | grep denied

or, on the PC, :

adb logcat | grep denied

while testing the overlay mounts.



Links


The Linux Kernel - overlay filesystems

How to use Overlay FS?




Back to top