Je voudrais mapper uid=neo(1000)->Root(0) et guid=neo(1000)->sdcard_r(1028) où neo:neo est l'utilisateur sur le serveur et Root:sdcard_r est l'utilisateur sur le téléphone.
Propriété des fichiers root:sdcard_r (0:1028)
sur Android ne fonctionne pas pour les applications. Cela devrait être root:everybody (0:9997)
avec mode 0770
pour les répertoires et 0660
pour les fichiers.
COMMENT FAIRE FONCTIONNER NFS AVEC LES APS Android ?
DAC traditionnel *NIX (UIDs/GIDs) a été conçu pour isoler les utilisateurs humains, pas les programmes. Sur les appareils Android - destinés à un seul utilisateur humain en général - les applications doivent être isolées et protégées afin qu'elles ne puissent pas accéder aux données des autres. Android traite donc chaque application comme un utilisateur humain, avec un UID/GID unique.
Stockage externe ( /sdcard
) - qu'il soit physiquement externe ou interne - est destiné à être partagé par toutes les applications, c'est-à-dire à avoir plusieurs UID. S'il s'agit d'un système de fichiers *NIX traditionnel (tel que ext4
), chaque application créerait des fichiers avec son propre UID/GID, ce qui rend presque impossible le partage de fichiers entre toutes les applications avec un accès en lecture/écriture. Pour trouver une solution, Android a opté pour un système de fichiers émulé - basé sur FUSE ou sdcardfs
- avec une propriété et un mode fixes. Voir les détails dans Qu'est-ce que l'UID "u#_everybody" ?
Ces UIDs/GIDs et ces modes contrôlent également l'accès des applications aux fichiers de l'application. /sdcard
. Donc, si nous voulons que le montage NFS soit accessible par toutes les applications, nous devons atténuer ces autorisations conformément à la conception du stockage d'Android.
SÉCURITÉ UNIX SUR NFS :
sec=sys
Ce mode applique les permissions UNIX sans aucune traduction. Comme expliqué dans la section précédente, les fichiers sont créés avec une propriété aléatoire par différentes applications. Ils doivent donc être lisibles/inscriptibles par le monde entier ( o+rw
), sinon les applications ne pourront pas lire/écrire. Mais il n'y a aucun moyen de faire respecter mode de création du fichier Globalement, ce n'est pas non plus une bonne idée de partager des fichiers avec des autorisations trop ouvertes. Une solution possible est d'utiliser le mappage d'ID et/ou le mode anonyme.
NFSv4 ID MAPPING :
Avec NFSv4, il est possible de mapper différents UIDs/GIDs entre le client et le serveur. Si un utilisateur avec le même nom mais avec des UIDs/GIDs différents existe des deux côtés, les fichiers sur le client semblent appartenir au même nom d'utilisateur, mais pas au même UID. Installation de gestion des clés sous Linux * est utilisé pour stocker les correspondances entre les identifiants d'utilisateurs distants et les identifiants d'utilisateurs locaux. Une bonne explication peut être trouvée ici .
L'idée est donc de créer un groupe d'utilisateurs neo:neo
sur le serveur NFS ( 1000
: 1000
) et sur Android ( 0
: 9997
). Pour cela, rpc.idmapd
doit être exécuté à la fois sur le serveur et le client et interroge la base de données des utilisateurs ( /etc/{passwd,group}
dans le cas le plus simple) par NSS . Sur les noyaux plus récents, le client NFSv4 utilise plutôt nfsidmap et ne revient qu'à rpc.idmapd
s'il y avait un problème pour exécuter le nfsidmap
. Appels du noyau /sbin/request-key
binaire en espace utilisateur qui exécute nfsidmap
pour interroger la base de données des utilisateurs. Ainsi, le noyau mettrait en correspondance le serveur neo
( 1000
: 1000
) au client neo
( 0
: 9997
).
Dans un cas simple, si la plage d'UID/GID 10000 à 19999 n'est attribuée à aucun utilisateur/groupe sur le serveur NFS et que l'UID/GID de la plage 10000 à 19999 n'est pas attribué à un utilisateur/groupe. Nobody-User = root
/ Nobody-Group = everybody
est défini dans /etc/idmapd.conf
sur le client, tous les fichiers (créés par les applications Android) appartenant à des utilisateurs inexistants sur le serveur seraient retournés comme appartenant à 0
: 9997
sur le client. Mais cela ne résout pas le problème de la propriété aléatoire des fichiers sur le serveur.
Running rpc.idmapd
ou en fournissant nfsidmap
sur Android est une tâche compliquée (liens statiques et tout ça). Cependant, l'utilisation de keyutils
( request-key
y keyctl
) - nous pouvons tromper le noyau pour montrer la propriété fixe 0:9997
pour tous les mappings, quelle que soit la propriété réelle :
Sur le serveur NFS :
-
Exécuter les services :
~# mount -t nfsd nfsd /proc/fs/nfsd
~# rpc.mountd -g -N2 -N3 -N4 -N4.1 -N4.2 -p 4000
~# rpc.nfsd -N2 -N3 -N4 -N4.1 -N4.2 -U --p 2049 4
~# mkdir -p /run/rpc_pipefs
~# mount -t rpc_pipefs sunrpc /run/rpc_pipefs
~# rpc.idmapd -S -p /run/rpc_pipefs
~# echo -n N >/sys/module/nfsd/parameters/nfs4_disable_idmapping
~# exportfs -o rw,insecure,hide,no_subtree_check,sec=sys <CLIENT_IP>:/SHARED_DIR
Ou configurez et exécutez les init
services. Débloquez également les ports via le pare-feu sur le client et le serveur.
Sur Android :
-
Créer /sbin/nfsidmap_pseudo
y /etc/request-key.conf
:
#!/system/bin/sh
uid=0
gid=9997
case $2 in
uid:*)
printf '%s\0' "$uid" | /sbin/keyctl pinstantiate $1 0 ;;
gid:*)
printf '%s\0' "$gid" | /sbin/keyctl pinstantiate $1 0 ;;
*)
# won't do anything to "user" or "group" types
exit 1 ;;
esac
# /etc/request-key.conf
create id_resolver * * /sbin/nfsidmap_pseudo %k %d
-
Placez les fichiers, définissez les permissions et activez le mappage d'ID : :
~# chmod 0755 /sbin/request-key /sbin/nfsidmap_pseudo /sbin/keyctl
~# chmod 0644 /etc/request-key.conf
~# chown 0.0 /sbin/request-key /sbin/nfsidmap_pseudo /sbin/keyctl /etc/request-key.conf
~# chcon u:object_r:rootfs:s0 /sbin/request-key /sbin/nfsidmap_pseudo /sbin/keyctl
~# chcon u:object_r:system_file:s0 /etc/request-key.conf
~# echo -n N >/sys/module/nfs/parameters/nfs4_disable_idmapping
-
Comme NFS n'est pas officiellement pris en charge par Android, la politique SELinux n'a pas de règles requises. Vous devrez peut-être définir SELinux permissive ou autoriser le noyau à lire/écrire les clés, exécuter les fichiers en espace utilisateur et établir des connexions :
~# supolicy --live 'allow kernel kernel key { search write view read }'
~# supolicy --live 'allow kernel kernel capability { net_raw net_bind_service sys_admin }'
~# supolicy --live 'allow kernel { rootfs shell_exec system_file } file { execute_no_trans execute open getattr }'
-
Mont :
~# mkdir -p /sdcard/NFS
~# busybox mount -v -t nfs4 -o vers=4.2,sec=sys,rw,tcp,port=2049,context=u:object_r:sdcardfs:s0 <SERVER_IP>:/SHARED_DIR /mnt/runtime/write/emulated/0/NFS
Malheureusement, ce que nous obtenons de toute cette configuration, c'est que maintenant les applications voient apparemment les fichiers en /sdcard/NFS
détenu par 0:9997
. Mais avec sec=sys
sécurité, l'accès réel aux fichiers n'est pas régi par le mappage d'UID NFSv4. ** . Les permissions sont appliquées par le mécanisme RPC qui n'est pas encore prêt à fonctionner avec le mappage d'ID. Ainsi, le mappage d'UID sans Kerberos
La sécurité ne fonctionne que si les espaces des noms et des numéros des utilisateurs/groupes sont cohérents entre le client et le serveur. Cela signifie que neo
L'utilisateur sur le serveur doit avoir un UID/GID : 0
/ 9997
(ce qui annule tout l'objectif du mappage d'identifiants). D'autre part, la sécurité Kerberos ( sec=krb5
) est trop trépidante à essayer sur Android.
De même, le verrouillage des fichiers sur NFSv2/3 nécessite portmapper
( rpcbind
) et rpc.statd
s'exécutant à la fois sur le serveur et le client, ce qui n'est pas le cas avec le client Android. Ainsi, nous devons utiliser nolock
option de montage. Sur NFSv4, cependant, le verrouillage est intégré au protocole NFS, NLM n'est pas nécessaire. Il est donc préférable de ne pas opter pour UID Mapping
(sur NFSv4, et File Locking
sur NFSv2/3). Si vous avez besoin que toutes les fonctionnalités de NFS (y compris Kerberos) fonctionnent sur un appareil Android, essayez plutôt une petite distro Linux en chroot
.
* Sur les noyaux plus anciens que v4.6, /proc/keys
est exposé si le noyau est construit avec KEYS_DEBUG_PROC_KEYS
.
** Références : 1 , 2 , 3 , 4 , 5 , 6
ACCÈS ANONYME NFS :
Une des saveurs de sécurité NFS est mode anonyme . Chaque requête provenant d'un UID/GID quelconque sur le client est traitée comme un UID/GID anonyme sur le serveur. Initialement, tous les fichiers du répertoire partagé doivent appartenir à cet UID/GID et tous les fichiers créés ultérieurement du côté client auront également la même propriété :
Partage de l'exportation avec sec=none
sur le serveur :
~# exportfs -o rw,insecure,no_subtree_check,anonuid=1000,anongid=1000,sec=none,root_squash,all_squash <CLIENT_IP>:/SHARED_DIR
~# chown -R 1000.1000 /SHARED_DIR; chmod 0700 /SHARED_SIR
* Pour NFSv2/3, exécutez également rpcbind
(sur le port 111 par défaut)
A monter avec sec=none
Sur Android :
~# busybox mount -v -t nfs4 -o vers=4.2,sec=none,rw,tcp,port=2049,context=u:object_r:sdcardfs:s0 <SERVER_IP>:/SHARED_DIR /mnt/runtime/write/emulated/0/NFS
* Utiliser -t
y vers=
selon votre configuration de construction du noyau CONFIG_NFS_V[2|3|4|4_1|4_2]
.
* Utiliser -t nfs -o nolock
con vers=3
o vers=2
.
* Assurez-vous que vous montez à partir de l'espace de nom de montage Root.
* Montage avec sec=none
ne fonctionne pas avec NFSv3.
Toutes les applications sur Android peuvent maintenant lire et écrire dans le répertoire NFS et tous les fichiers sont créés avec un seul UID/GID anonyme sur le serveur, facile à gérer par un utilisateur. Cependant, la propriété apparente (si le mappage des ID n'est pas configuré) et le mode de permission ne sont pas conformes à la saveur d'Android, donc...
Essayez la méthode Android...
Utilisons FUSE ou sdcardfs
comme le fait Android :
~# mkdir -p /mnt/NFS /sdcard/NFS
~# busybox mount -v -t nfs4 -o vers=4.2,sec=none,rw,tcp,port=2049,context=u:object_r:sdcardfs:s0 <SERVER_IP>:/SHARED_DIR /mnt/NFS
~# mount -t sdcardfs -o nosuid,nodev,noexec,noatime,mask=7,gid=9997 /mnt/NFS /mnt/runtime/write/emulated/0/NFS
Si votre appareil ne prend pas en charge sdcardfs
utiliser bindfs
et remplacer le contexte SELinux u:object_r:sdcardfs:s0
con u:object_r:fuse:s0
:
~# bindfs -o nosuid,nodev,noexec,noatime,context=u:object_r:fuse:s0 -u 0 -g 9997 -p a-rwx,ug+rw,ugo+X --xattr-none --chown-ignore --chgrp-ignore --chmod-ignore /mnt/NFS /mnt/runtime/write/emulated/0/NFS
Il ne nous reste plus aucun problème. Pour plus de détails, voir Comment lier le montage d'un dossier dans /sdcard avec les permissions correctes ?
DONNEZ UNE CHANCE AU CIF...
NFS étant le système de fichiers natif de Linux (comme ext4
) est destiné à faire respecter les permissions *NIX. Les systèmes de fichiers non natifs comme FAT et CIFS permettent de définir des droits de propriété et des permissions fixes pour l'ensemble du système de fichiers. Ainsi, ce que vous recherchez est relativement facile à réaliser avec la commande CIFS :
~# mkdir -p /sdcard/CIFS
~# busybox mount -v -t cifs -o vers=3.0,nosuid,nodev,noexec,noatime,rw,hard,context=u:object_r:sdcardfs:s0,nounix,uid=0,gid=9997,file_mode=0660,dir_mode=0770,nouser_xattr,port=445,username=USERNAME,password=PASSWORD //<SERVER_IP>/SHARED_DIR /mnt/runtime/write/emulated/0/CIFS
* Le noyau doit être construit avec CONFIG_CIFS
et de préférence CONFIG_CIFS_SMB2
utiliser vers=
en conséquence.
* Pour le détail des options de montage, voir mount.cifs(8)
D'AUTRES OPTIONS ?
Les autres systèmes de fichiers montables basés sur FUSE sont sshfs
y rclone
. Latter offre un large éventail de protocoles et de configurations tout en nécessitant une installation très simple.