11 votos

¿Cómo se puede montar una carpeta dentro de /sdcard con los permisos correctos?

Estoy usando un Sony Xperia M4 Aqua. Como es sabido, la memoria interna es bastante pequeña. Especialmente la Media directorio de WhatsApp utiliza un montón de espacio precioso, por lo tanto, estoy tratando de moverlo a la tarjeta SD. Estoy usando Android 6 y he formateado la tarjeta SD para tener una partición de almacenamiento adoptada.

El almacenamiento adoptado se utilizaría normalmente para migrar todos los /data a la misma, como se discute aquí . Sin embargo, estoy interesado en mover sólo el directorio único WhatsApp/Media en otro lugar (posiblemente en la partición de almacenamiento adoptada), y luego bind-mount a su ubicación original.

Para ello, trasladé el WhatsApp/Media en el directorio adoptado. A continuación, tras esta discusión , he modificado el script /system/etc/init.qcom.post_boot.sh añadiendo lo siguiente mount (el teléfono no tiene soporte para init.d scripts)

mount -o bind /mnt/expand/4fdb2500-9aa7-44bc-a2c4-80aeae28e764/WhatsAppMedia /storage/emulated/0/WhatsApp/Media
mount -o bind /mnt/expand/4fdb2500-9aa7-44bc-a2c4-80aeae28e764/WhatsAppMedia /mnt/runtime/write/emulated/0/WhatsApp/Media
mount -o bind /mnt/expand/4fdb2500-9aa7-44bc-a2c4-80aeae28e764/WhatsAppMedia /mnt/runtime/read/emulated/0/WhatsApp/Media
mount -o bind /mnt/expand/4fdb2500-9aa7-44bc-a2c4-80aeae28e764/WhatsAppMedia /mnt/runtime/default/emulated/0/WhatsApp/Media
mount -o bind /mnt/expand/4fdb2500-9aa7-44bc-a2c4-80aeae28e764/WhatsAppMedia /data/media/0/WhatsApp/Media

Aviso: /mnt/expand/4fdb25.... apunta a la partición de almacenamiento adoptada.

Esto sólo funciona aparentemente: si abro un shell con adb Puedo ver correctamente que el WhatsApp/Media contiene el directorio montado. Además, no veo ninguna vista adicional que contenga el directorio WhatsApp, como se puede comprobar haciendo, en un adb shell

find / -type d -name WhatsApp

Sin embargo, WhatsApp no puede acceder a la galería multimedia. Por ejemplo, en el chat sólo veo imágenes borrosas (como una vista previa), y al pulsar sobre ellas no veo la imagen completa. Además, si alguien me envía una imagen, todo lo que puedo ver es una vista previa borrosa con el icono de descarga. Al hacer clic en el icono de descarga no se produce nada.

Los permisos erróneos son presumiblemente la fuente de los problemas. Por ejemplo, algunos permisos/propiedad de grupos parecen ser incorrectos en algunas vistas:

root@E2303:/ # ls -n /storage/emulated/0/WhatsApp
drwxrwx--x 0        1015              2019-09-04 14:37 Backups
drwxrwx--x 0        1015              2019-10-19 02:00 Databases
drwxrwx--x 0        1015              2019-09-04 20:24 Media
root@E2303:/ # ls -n /mnt/runtime/write/emulated/0/WhatsApp
drwxrwx--- 0        9997              2019-09-04 14:37 Backups
drwxrwx--- 0        9997              2019-10-19 02:00 Databases
drwxrwx--x 0        1015              2019-09-04 20:24 Media
root@E2303:/ # ls -n /mnt/runtime/read/emulated/0/WhatsApp
drwxr-x--- 0        9997              2019-09-04 14:37 Backups
drwxr-x--- 0        9997              2019-10-19 02:00 Databases
drwxrwx--x 0        1015              2019-09-04 20:24 Media
root@E2303:/ # ls -n /mnt/runtime/default/emulated/0/WhatsApp
drwxrwx--x 0        1015              2019-09-04 14:37 Backups
drwxrwx--x 0        1015              2019-10-19 02:00 Databases
drwxrwx--x 0        1015              2019-09-04 20:24 Media
root@E2303:/ # ls -n /data/media/0/WhatsApp/                                   
drwxrwxr-x 1023     1023              2019-09-04 14:37 Backups
drwxrwxr-x 1023     1023              2019-10-19 02:00 Databases
drwxrwx--x 0        1015              2019-09-04 20:24 Media

Permisos y propiedad de grupo del Media debe ser el mismo de los otros directorios (no montados en bind) Backups y Databases . Curiosamente, un intento de volver a montar los directorios con el gid correcto

root@E2303:/ # mount -o remount, gid=9997 /mnt/runtime/write/emulated/0/WhatsApp/Media
root@E2303:/ # mount -o remount, gid=9997 /mnt/runtime/read/emulated/0/WhatsApp/Media
root@E2303:/ # mount -o remount, gid=1023 /data/media/0/WhatsApp/Media

no produce ningún cambio en la propiedad del grupo: ls -n como el anterior da resultados idénticos.

Aún más extraño, pero tal vez no relacionado, es omitir el espacio entre remount y gid=... resultados en

mount: Invalid argument

Cómo atar la montura WhatsApp/Media carpeta de la tarjeta SD externa con los permisos correctos?

15voto

Jack Wade Puntos 231

He estado utilizando dos enfoques diferentes con mis versiones más antiguas de Android para montar todo /sdcard/WhatsApp directorio de la tarjeta SD externa. He probado, funciona en Android 9 también, pero las cosas de almacenamiento han cambiado en Android 10.

Antes de entrar en detalles prácticos, debemos tener en cuenta algunos puntos:

  • /sdcard no es una realidad sino sistema de archivos emulado . Android utiliza sdcardfs (o FUSE ) para emular el almacenamiento real en /sdcard . Ver ¿Qué es /storage/emulated/0/?

  • Los dos sistemas de archivos anteriores tienen un contexto SELinux fijo : u:object_r:sdcardfs:s0 (o u:object_r:fuse:s0 ).

  • Normalmente /data/media se emula sobre /sdcard Pero en el caso del Almacenamiento Adoptable cuando se migran los datos, /mnt/expand/[UUID]/media se emula. Véase ¿Cómo liberar el Almacenamiento Interno moviendo los datos o usando symlink / bind-mount con el Almacenamiento Adoptable?

  • Archivos y directorios en /sdcard tienen propiedad y permisos fijos que dependen de si la aplicación tiene android.permission.[READ|WRITE]_EXTERNAL_STORAGE permiso concedido o no. Los archivos nunca tienen permiso de ejecución. Los directorios de datos de las aplicaciones en /sdcard/Android/data/ tienen la propiedad establecida en el UID de la aplicación respectiva. Para más detalles, consulte ¿Qué es el UID "u#_everybody"?

    Suponemos que todas las aplicaciones pueden escribir en /sdcard estableciendo la propiedad 0 / 9997 (usuario/grupo) y permisos 0771 / 0660 (directorios/archivos).

  • Para lograr dicho comportamiento, desde Android 6 cada aplicación se ejecuta en un espacio de nombres de montaje aislado y /storage/emulated está montado en otro VER : /mnt/runtime/[default|read|write]/emulated con propagación de montaje privado/esclavo. Por lo tanto, montar directamente en /storage/emulated no aparecerá en los espacios de nombres de montaje de las aplicaciones a menos que introduzcas explícitamente el espacio de nombres de montaje de cada aplicación. Lo mismo ocurre si montas desde un espacio de nombres de montaje aislado de alguna aplicación. Ver La partición se desmonta automáticamente en Android Oreo .

    Vamos a montar desde el espacio de nombres Root mount a /mnt/runtime/write/emulated que se propaga a todos los espacios de nombres de montaje de las aplicaciones. Esta vista se expone a las aplicaciones que tienen permiso de almacenamiento concedido.

  • /sdcard no admite los atributos extendidos ( xattr ) y el tiempo de acceso ( atime ). Otras opciones de montaje son nosuid , nodev y noexec . Ver página de manual de montaje para más detalles.


En primer lugar, asegúrese de que está en el espacio de nombres de montaje de root como se explica en el enlace dado anteriormente. O utilice nsenter para obtener un shell root en el espacio de nombres global:

~# [ $(readlink /proc/1/ns/mnt) = $(readlink /proc/self/ns/mnt) ] || busybox nsenter -t 1 -m /system/bin/sh

1. ALMACENAMIENTO PORTÁTIL:

La forma más sencilla es formatear la tarjeta SD externa como almacenamiento portátil con exFAT o FAT32 . Dado que estos sistemas de archivos no son nativos de Linux, sus implementaciones de controladores en el núcleo son compatibles con uid , gid , fmask y dmask opciones de montaje. Puede utilizar exfat o sdfat conductores con exFAT y vfat con FAT32 . El anterior tiene también una implementación en el espacio de usuario mount.exfat-fuse que sólo requiere el soporte de FUSE desde el kernel. Compruebe con grep fuse /proc/filesystems .

Digamos que /dev/block/sda1 es su exFAT partición:

~# mount -t exfat -o nosuid,nodev,noexec,noatime,context=u:object_r:sdcardfs:s0,uid=0,gid=9997,fmask=0117,dmask=0006 /dev/block/sda1 /mnt/runtime/write/emulated/0/WhatsApp
~# mv /data/media/0/WhatsApp/* /sdcard/WhatsApp/

* Sustituir u:object_r:sdcardfs:s0 con u:object_r:fuse:s0 o cualquier etiqueta que su /sdcard tiene.

La parte negativa con este enfoque es que vold monta la tarjeta SD externa en el arranque, por lo que es necesario desmontarla primero. También puede crear múltiples particiones. O bien, después de montar con las opciones de montaje requeridas, también puede enlazar el montaje de un directorio en lugar de toda la partición.
En segundo lugar, los datos de la tarjeta SD no están encriptados, aunque hay múltiples formas de encriptarlos manualmente. Ver Desencriptar la tarjeta microSD en otro dispositivo Android u ordenador de sobremesa .

2. ALMACENAMIENTO ADOPTABLE:

Una forma fácil de contrarrestar los inconvenientes mencionados anteriormente es hacer uso del FDE incorporado en el kernel formateando la tarjeta SD como Almacenamiento Adoptable, pero sólo si no quieres migrar todo /data/media/ a la tarjeta SD externa. Una vez formateada, la tarjeta SD externa se montará en /mnt/expand/[UUID] (sistema de archivos UUID es un número de 16 bytes). Pero no podemos simplemente montar un directorio de allí a /sdcard porque el sistema de archivos en Adoptable Storage es ext4 que sigue el modelo de permisos de UNIX, pero las aplicaciones no pueden manejarlos como se ha explicado anteriormente. Incluso si lo haces funcionar de alguna manera (usando chown , chmod etc.), cada aplicación creará archivos con su propio UID que no serán accesibles para otras aplicaciones, por ejemplo, la Galería no podrá ver las imágenes descargadas por WhatsApp.

Así que nos encontramos con dos posibilidades:

  • Si su kernel soporta sdcardfs (consultar con grep sdcardfs /proc/filesystems ), crear un directorio en la tarjeta SD adoptada y emularlo a /sdcard/WhatsApp :

    ~# mkdir /mnt/expand/[UUID]/media/0/WhatsApp
    ~# mv /sdcard/WhatsApp/* /mnt/expand/[UUID]/media/0/WhatsApp/
    ~# restorecon -rv /mnt/expand/[UUID]/media/
    ~# mount -t sdcardfs -o nosuid,nodev,noexec,noatime,mask=7,gid=9997 /mnt/expand/[UUID]/media/0/WhatsApp /mnt/runtime/write/emulated/0/Whatsapp

    Tenga en cuenta que necesariamente tenemos que utilizar la ruta /mnt/expand/[UUID]/media/ porque está etiquetado como media_rw_data_file ( 1 ) (como /data/media ( 2 ) ) al que la política de SELinux permite acceder a las aplicaciones ( 3 ) . Si utiliza una ruta diferente, deberá modificar la política de SELinux. A diferencia de otros sistemas de archivos sdcardfs no cambia el contexto de SELinux al acceder al sistema de archivos subyacente.

  • O utilizar una herramienta de terceros llamada bindfs (que utiliza FUSE) para simular el comportamiento del sistema de archivos emulado. En realidad, la herramienta incorporada de Android /system/bin/sdcard hace exactamente esto, pero tiene algunas rutas fijas y otras cosas innecesarias, por lo que hay que modificar su código fuente para conseguir lo que queremos. Se puede construir bindfs usted mismo o intente este uno.

    ~# mkdir /mnt/expand/[UUID]/WhatsApp
    ~# mv /sdcard/WhatsApp/* /mnt/expand/[UUID]/WhatsApp/
    ~# bindfs -o nosuid,nodev,noexec,noatime,context=u:object_r:sdcardfs:s0 -u 0 -g 9997 -p a-rwx,ug+rw,ugo+X --create-with-perms=a-rwx,ug+rw,ugo+X --xattr-none --chown-ignore --chgrp-ignore --chmod-ignore /mnt/expand/[UUID]/WhatsApp /mnt/runtime/write/emulated/0/WhatsApp

    Como nota al margen herramientas como rclone , encfs , sshfs etc. que hacen uso de FUSE también se pueden montar dentro de /sdcard de la misma manera.


Así que puedes optar por el método que más te convenga. Por lo general, los controladores dentro del núcleo funcionan mejor que las soluciones de espacio de usuario, y los métodos nativos del núcleo de Linux son más robustos y estables. FUSE (sobre FUSE) puede ejercer una penalización de rendimiento a veces, por ejemplo, si la propia tarjeta SD soporta transferencias de datos de alta velocidad.

Puede colocar los comandos de montaje necesarios en un init.d script o definir y init servicio. Ver ¿Cómo ejecutar un ejecutable en el arranque y mantenerlo en funcionamiento?

Nota:

  • Aplicaciones que no escanean /sdcard sistema de archivos, sino que dependen del MediaProvider de Android para cualquier cambio, pueden necesitar un escaneo forzado de medios para que los nuevos archivos en el sistema de archivos montado aparezcan inmediatamente.
  • Si utiliza varios usuarios o perfiles, deberá montar un nuevo sistema de archivos para cada User_ID . Para el propietario del dispositivo es 0 .

0 votos

Hola Irfan . Pasando por tu meticulosa respuesta... ( y gracias por la misma ) ... Mi situación es un multi partitioned ext4 tarjeta donde incluso la partición principal es ext4 . Mi ROM es una ROM Stock que a diferencia de lineage no es compatible ext4 mount fuera de la caja . Puedo mount mi partitions con un enfoque similar al de init.d y son visibles para rooted TC aplicaciones pero no son RW. Me gustaría partition amplia RW para determinadas aplicaciones. No sólo los dirs privados. He probado vold-posix no le gusta mi sistema operativo y el arco. n ot executable: 64-bit ELF file Me aparece este error para bindfs . ¿Alguna otra?

0 votos

getprop ro.product.cpu.abilist gives armeabi-v7a,armeabi . Cualquier otro enfoque para que pueda obtener una RW partition amplia mount para un caso concreto rooted y las aplicaciones no arraigadas (la aplicación no rooteado es el gestor de archivos de la ROM original que todas las aplicaciones invocan por defecto para recorrer los directorios). ¡Según tengo entendido, Android 'desaprueba esto, pero lo apreciaría', si usted puede lanzar en sus 2 centavos!

0 votos

Si esto partition wide no es factible entonces en el momento del montaje quiero dar IDs de aplicaciones específicas RW. como parte del montaje. ¿Cómo puedo hacer esto?

PreguntAndroid.com

PreguntAndroid es una comunidad de usuarios de Android en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X