5 votes

Comment monter NFS sur Android avec les permissions correctes ?

J'essaie de monter un partage NFS sur mon téléphone Android.

J'ai déjà compilé et installé tous les modules du noyau nécessaires. Le partage NFS se monte sans problème, mais je ne peux le monter que sous le nom de system utilisateur. Ce ne serait pas un problème si je pouvais définir la propriété correcte pour le système de fichiers monté. Le problème est que le partage est toujours monté en tant que user= system et group= system ce qui le rend inaccessible aux applications habituelles.

J'aimerais pouvoir spécifier la propriété du système de fichiers monté au moment du montage.

Voici comment je monte le partage NFS

su -c "busybox mount -o nosuid,nolock,nodev,rw,nofail,noatime,intr,tcp,actimeo=1800,context=u:object_r:rootfs:s0,user -t nfs $REMOTE_URI $LOCAL_DIRECTORY"

donde REMOTE_URI est l'emplacement distant et RÉPERTOIRE LOCAL est le répertoire local. La commande ci-dessus est à l'intérieur d'un script.

Il s'agit de la ligne pertinente de la /etc/exports sur le serveur NFS (un raspberry pi 3)

/media/neo/BLACKBOX XXX.XXX.XXX.XXX/0(rw,insecure,sync,no_root_squash,no_subtree_check,anonuid=1000,anongid=1000)

Spécifications du système :

  • LG V20 H990DS
  • Système - V10i-TWN (6th-Nov-17) 7.0 Stock, Rooted & Xposed
  • Kernel - D.O.T.S. v1.4
  • NFS version 4

PS : L'UID et le GID du serveur sont respectivement 1000 et 1000. Dans Android, ils sont réservés à l'utilisateur et au groupe du système. Tous mes autres ordinateurs ont un UID et un GID 1000 et le même nom d'utilisateur. neo . Il serait beaucoup plus facile de modifier la façon dont Android monte le partage. Je voudrais mettre en correspondance uid=neo(1000)->root(0) y guid=neo(1000)->sdcard_r(1028) donde neo:neo est l'utilisateur sur le serveur et root:sdcard_r est l'utilisateur du téléphone.

10voto

Irfan Latif Points 16863

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 :

  1. 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 :

  1. 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
  2. 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
  3. 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 }'
  4. 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.

2voto

Gopal Points 109

Il semble que toutes les distributions de Busybox qui sont sur Google Play ne sont pas compatibles avec NFSv4 mais seulement NFSv3. J'ai donc abandonné l'idée d'utiliser idmapd sur Android.

  • Au lieu de cela, j'ai changé l'UID et le GID du serveur NFS en 4444 afin qu'ils ne correspondent pas à l'option system plus d'utilisateur.
  • Ensuite, j'ai créé un nouvel utilisateur sur Busybox avec le même nom, UID et GID que le serveur (dans ma distribution Busybox, le fichier adduser y addgroup les services publics sont inclus).
  • J'ai acheté Tasker et téléchargé este ensemble de tâches du forum XDA.
  • J'ai choisi le /mnt/nfs pour monter le partage.

Je n'ai pas le temps de chercher à savoir lequel des points précédents est nécessaire et lequel n'est que non pertinent ou facultatif. Si vous avez une idée, écrivez-la dans un commentaire.

androidalle.com

AndroidAlle est une communauté de androiders où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X