Warum sind (bind) Mounts in /storage/emulated/0 in Apps nicht sichtbar?

Ich habe ein Verzeichnis in ein anderes Verzeichnis gemountet mit:

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

Ich mache das beim Booten mit Tasker. Ich kann die gemounteten Dateien in adb shellund in Termux sehen, auch als Nicht-Root-Benutzer. Aber ich kann diese Dateien nicht in Apps wie Total Commander oder meinem Music Player sehen.

Ich verwende Lineage 7.1.2.

In diesem Thread besteht eine Lösung darin, "Mount-Namespaces" in SuperSU auszuschalten. Leider habe ich die LineageOS-Standard-SU-App, die diese Option anscheinend nicht bietet. Irgendwelche Vorschläge?

Antworten (1)

Ich verwende seit einiger Zeit Bind-Mounts, ohne Mount-Namespaces auf Android zu deaktivieren - Marshmallow (Android 6) und Nougat (Android 7.1, LineageOS 14.1).

Der Bind-Mount ist für andere Apps nicht sichtbar, da /storage/sdcard/er selbst auch eine indirekte Ebene ist. Wenn Sie beispielsweise ausführen mount, können Sie sehen, dass sich die emulierte „interne“ SD-Karte nicht unter befindet /storage/emulated, sondern unter /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)

Diese drei Einhängepunkte sind unter Speicher, Laufzeitberechtigungen/mnt/runtime dokumentiert :

Android 6.0 führt ein neues Laufzeitberechtigungsmodell ein , bei dem Apps bei Bedarf zur Laufzeit Funktionen anfordern. Da das neue Modell die READ/WRITE_EXTERNAL_STORAGE-Berechtigungen enthält, muss die Plattform den Speicherzugriff dynamisch gewähren, ohne bereits ausgeführte Apps zu beenden oder neu zu starten. Dazu werden drei unterschiedliche Ansichten aller gemounteten Speichergeräte beibehalten:

  • /mnt/runtime/defaultwird Apps ohne spezielle Speicherberechtigungen und dem Root-Namespace angezeigt, in dem sich adbd und andere Systemkomponenten befinden.
  • /mnt/runtime/readwird Apps mit angezeigtREAD_EXTERNAL_STORAGE
  • /mnt/runtime/writewird Apps mit angezeigtWRITE_EXTERNAL_STORAGE

Um also ein Verzeichnis für alle anderen Apps sichtbar zu machen, müssen Sie die Mounts an diesen Stellen erstellen:

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

Zum Aushängen:

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

In Ihrer Frage befinden sich Quelle und Ziel im selben Dateisystem, sodass das obige wahrscheinlich unverändert funktioniert und anderen Apps dir2 anzeigt.

Sie können überprüfen, ob die Bind-Mounts wie beabsichtigt "sichtbar" sind, indem Sie die Prozess-ID der gewünschten App nachschlagen und dann die Liste der Mounts aus der Sicht dieser App überprüfen:

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

Debugging-Tipps

Wenn Sie nicht auf den Inhalt des Bind-Mounts zugreifen können (dh "Permission denied" oder ähnliches), sollten Sie überprüfen, ob die Originaldatei die richtigen UNIX-Berechtigungen/Besitzrechte UND eine dem Kontext entsprechende SELinux-Bezeichnung hat. Letzteres kann debuggt werden, indem nach „avc: denied“-Fehlern in logcat-color (oder einfach nur adb logcat) gesucht wird. In einigen Fällen kann dies mit restoreconoder behoben werden chcon.

Zum Beispiel habe ich früher den folgenden Fehler erhalten, wenn ich versucht habe, darauf zuzugreifen /sdcard/DCIM(was ein Bind-Mount für ein Verzeichnis auf einer externen SD-Karte ist).

avc: verweigert {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 zulässig=0

Und das behoben, indem festgestellt wurde, dass das SELinux-Label falsch ist (das tcontextin der Fehlermeldung hat mir das bereits gesagt):

# 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 .

und änderte dies (rekursiv) in ein Label, das von der Standardrichtlinie auf LineageOS zugelassen wird:

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

Das hat bei mir funktioniert, weil /sepolicyes eine Regel gibt, die besagt, dass auf Dateien priv_appzugegriffen werden kann media_rw_data_file. Diejenigen, die eine andere Situation/ROM haben, können setools-android verwenden , um ihre /sepolicyDatei zu parsen, um ihre Optionen anzuzeigen.

Danke für diese tolle Erklärung. Ich werde es versuchen, sobald ich Zeit dafür habe. Übrigens. Ich habe in der Frage dasselbe Dateisystem verwendet, aber in Wirklichkeit habe ich versucht, ein Verzeichnis von meiner externen SD auf die interne SD zu mounten.
Diese Aussage ist irreführend: Ich habe Bind-Mounts verwendet, ohne Mount-Namespaces zu deaktivieren . Sie müssen sich im Root-Mount-Namespace befinden, bevor Sie Bind-Mounts erstellen können. Andernfalls ist das Quellverzeichnis nur innerhalb des isolierten Mount-Namespace sichtbar, nicht für alle Apps. Es ist auch /mnt/runtime/{default,read,write}/dir2dasselbe Verzeichnis, sodass Sie nicht alles separat mkdirtun müssen. rmdirAuch die Montage auf einem verbreitet sich automatisch auf die anderen zwei, so mountdass sie umountauch nur auf einem der drei erforderlich sind.