I mounted a directory into another directory with:

mount --bind "/storage/sdcard/dir1" "/storage/sdcard/dir2"

I do this at boot completion with Tasker. I can see the mounted files in adb shell and in Termux, even as non-root user. But I can not see these files in apps like Total Commander or my Music Player.

I use Lineage 7.1.2.

In this thread, a solution is to switch off "mount namespaces" in SuperSU. Unfortunately, I have the LineageOS default SU app which does not seem to provide such option. Any suggestions?


1 Answer 1


I have been using bind mounts without disabling mount namespaces on Android for a while - Marshmallow (Android 6) and Nougat (Android 7.1, LineageOS 14.1).

The bind mount is not visible to other apps because /storage/sdcard/ itself is also a layer of indirection. For example, when you run mount, you can see that the emulated "internal" SD card is not located at /storage/emulated, but at /data/media:

/data/media on /mnt/runtime/default/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,uid=1023,gid=1023,multiuser)
/data/media on /storage/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,uid=1023,gid=1023,multiuser)
/data/media on /mnt/runtime/read/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,uid=1023,gid=1023,multiuser)
/data/media on /mnt/runtime/write/emulated type sdcardfs (rw,nosuid,nodev,noexec,noatime,uid=1023,gid=1023,multiuser)

These three mountpoints in /mnt/runtime are documented at Storage, Runtime permissions:

Android 6.0 introduces a new runtime permissions model where apps request capabilities when needed at runtime. Because the new model includes the READ/WRITE_EXTERNAL_STORAGE permissions, the platform needs to dynamically grant storage access without killing or restarting already-running apps. It does this by maintaining three distinct views of all mounted storage devices:

  • /mnt/runtime/default is shown to apps with no special storage permissions, and to the root namespace where adbd and other system components live.
  • /mnt/runtime/read is shown to apps with READ_EXTERNAL_STORAGE
  • /mnt/runtime/write is shown to apps with WRITE_EXTERNAL_STORAGE

So to make a directory visible to all other apps, you need to create the mounts in these places:

mkdir /mnt/runtime/{default,read,write}/dir2
mount -o bind /mnt/runtime/default/sdcard/dir1 /mnt/runtime/default/sdcard/dir2
mount -o bind /mnt/runtime/read/sdcard/dir1 /mnt/runtime/read/sdcard/dir2
mount -o bind /mnt/runtime/write/sdcard/dir1 /mnt/runtime/write/sdcard/dir2

To unmount:

umount /mnt/runtime/default/dir2
umount /mnt/runtime/read/dir2
umount /mnt/runtime/write/dir2
rmdir /mnt/runtime/{default,read,write}/dir2

In your question, the source and target are at the same filesystem, so the above will probably work as-is and show dir2 to other apps.

You can verify that the bind mounts are "visible" as intended by looking up the process ID of the desired app, and then checking the list of mounts from that app's point of view:

# cat /proc/(process ID here)/mountinfo

Debugging tips

If you cannot access the contents of the bind mount (i.e. "Permission denied" or something similar), then you should check whether the original file has the right UNIX permissions/ownership AND a SELinux label that matches the context. The latter can be debugged by looking for "avc: denied" errors in logcat-color (or just adb logcat). In some cases this can be fixed by using restorecon or chcon.

For example, I used to get the following error when I tried to access /sdcard/DCIM (which is a bind mount to a directory on external SD card).

avc: denied { write } for comm=... name="Camera" dev="dm-1" ino=3547138 scontext=u:r:priv_app:s0:c512,c768 tcontext=u:object_r:mnt_media_rw_file:s0 tclass=dir permissive=0

And fixed that one by observing that the SELinux label is wrong (the tcontext in the error message already told me so):

# ls -Z /mnt/media_rw/myextcard/my_DCIM_directory
drwxrwx--x  4 media_rw media_rw  u:object_r:mnt_media_rw_file:s0  4096 2018-06-08 12:34 .

and changed that (recursively) to a label which is allowed by the default policy on LineageOS:

# chcon -R u:object_r:media_rw_data_file:s0:c512,c768 /mnt/media_rw/myextcard/my_DCIM_directory

This worked for me, because /sepolicy has a rule that states that priv_app can access media_rw_data_file files. Those who have a different situation/ROM can use setools-android to parse their /sepolicy file to see their options.

  • Thanks for this awesome explanation. I will try as soon as I have time for it. Btw. I used the same filesystem in the question, but in reality I tried to mount a directory from my external SD to the internal SD.
    – KCD
    Commented Jun 13, 2018 at 9:36
  • 1
    This statement is misleading: I have been using bind mounts without disabling mount namespaces. You need to be in root mount namesapce before creating bind mounts. Otherwise source directory will only be visible within the isolated mount namespace, not to all apps. Also /mnt/runtime/{default,read,write}/dir2 is same directory, so you don't need to do mkdir and rmdir on all separately. Also mounting on one automatically propagates to other two, so mount and umount are also required only on any one of the three. Commented Oct 14, 2019 at 10:38

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .