Existe-t-il un fichier qui existe toujours et un utilisateur «normal» ne peut pas le créer?


14

J'en ai besoin pour un test unitaire. Il y a une fonction qui lstat sur le chemin du fichier passé comme paramètre. Je dois déclencher le chemin de code où lelstat échoue (car la couverture du code doit atteindre 90%)

Le test ne peut s'exécuter que sous un seul utilisateur, donc je me demandais s'il y avait un fichier dans Ubuntu qui existe toujours, mais les utilisateurs normaux n'y ont pas accès en lecture ni dans son dossier. (Donclstat échouerait donc à moins d'être exécuté en tant que root.)

Un fichier inexistant n'est pas une solution, car il existe un chemin de code distinct pour cela, que je déclenche déjà.

EDIT: Le manque d'accès en lecture au fichier n'est pas suffisant. Avec cela lstatpeut toujours être exécuté. J'ai pu le déclencher (sur ma machine locale, où j'ai un accès root), en créant un dossier dans / root et un fichier dedans. Et en définissant l'autorisation 700 sur le dossier. Je recherche donc un fichier qui se trouve dans un dossier qui n'est accessible que par root.


6
IMHO/etc/shadow
Romeo Ninov

3
Vous ne pouvez pas supposer l'existence d'un fichier, car votre programme peut s'exécuter dans un chroot ou un espace de noms séparé. Si supposer que / proc est monté est OK et que init n'a rien de spécial, alors /proc/1/fd/0devrait le faire.
mosvy

1
@mosvy Merci qui fonctionne sur ma machine locale. Hmm alors je vais aussi l'essayer sur le pool QA et Staging.
Crouching Kitten

2
Pourquoi liez-vous votre code de test à une version particulière du système d'exploitation alors que vous pouvez simplement créer un fichier jetable et supprimer votre propre accès en lecture à celui-ci?
Kilian Foth

4
Je dirais que ce n'est pas vraiment un test unitaire une fois qu'il commence en fonction d'un système de fichiers réel, plutôt que simulé.
Toby Speight

Réponses:


21

Sur les systèmes Linux modernes, vous devriez pouvoir utiliser /proc/1/fdinfo/0(informations pour le descripteur de fichier 1 (stdout) du processus de l'id 1 ( initdans l'espace de noms pid racine qui doit s'exécuter commeroot )).

Vous pouvez trouver une liste avec (en tant qu'utilisateur normal):

sudo find /etc /dev /sys /proc -type f -print0 |
  perl -l -0ne 'print unless lstat'

(supprimez -type fsi vous ne souhaitez pas vous limiter aux fichiers normaux).

/var/cache/ldconfig/aux-cacheest un autre candidat potentiel si vous n'avez qu'à considérer les systèmes Ubuntu. Il devrait fonctionner sur la plupart des systèmes GNU car il /var/cache/ldconfigest créé en lecture + écriture + consultable à la racine uniquement par la ldconfigcommande fournie avec la libc GNU.


1
Merci! Si cela /proc/1/fdinfo/0fonctionne sur Ubuntu 16.04 et 18.04, c'est plus que suffisant.
Crouching Kitten

1
L'utilisation /proc/1/fdinfo/0ne fonctionne pas nécessairement dans un conteneur (par exemple, un conteneur Docker), et souvent des tests unitaires sont exécutés dans de tels conteneurs dans CI.
Philipp Wendler

@PhilippWendler, j'ai déjà mentionné l'espace de noms pid racine . L'OP ne pose pas de questions sur les conteneurs, mais sur les fichiers garantis dans la disposition du système de fichiers d'un système Ubuntu. Étant donné que les conteneurs pouvaient contenir n'importe quelle disposition de fichier et de répertoire, cette question ne pouvait pas y être répondue.
Stéphane Chazelas

12

En consultant la page de manuel lstat (2) , vous pouvez vous inspirer des cas susceptibles de provoquer l'échec avec des erreurs autres que ENOENT (le fichier n'existe pas.)

Le plus évident est:

EACCES L' autorisation de recherche est refusée pour l'un des répertoires du préfixe de chemin d' accès path .

Vous avez donc besoin d'un répertoire que vous ne pouvez pas rechercher.

Oui, vous pouvez en chercher un qui est déjà dans votre système (peut /var/lib/private- être s'il existe?) Mais vous pourriez aussi bien en créer un vous-même, avec l'équivalent de:

$ mkdir myprivatedir
$ touch myprivatedir/myunreachablefile
$ chmod 0 myprivatedir
$ ls -l myprivatedir/myunreachablefile

L'opération lstat (2) échouera avec EACCES ici. (La suppression de toutes les autorisations du répertoire garantit cela. Peut-être que vous n'en avez même pas besoin et la chmod -xsuppression des autorisations d'exécution serait suffisante, car les autorisations d'exécution sur un répertoire sont nécessaires pour accéder aux fichiers qu'il contient.)

Il existe une autre façon créative de faire échouer lstat (2), en regardant sa page de manuel:

ENOTDIR Un composant du préfixe de chemin d' accès de chemin d' accès n'est pas un répertoire.

Donc, essayer d'accéder à un fichier tel que /etc/passwd/nonexistentdevrait déclencher cette erreur, qui est encore différente de ENOENT ("Aucun fichier ou répertoire") et pourrait répondre à vos besoins.

Un autre est:

Le chemin ENAMETOOLONG est trop long.

Mais vous pourriez avoir besoin d'un nom très long pour celui-ci (je pense que 4 096 octets est la limite typique, mais votre système / système de fichiers peut en avoir un plus long.)

Enfin, il est difficile de dire si l'un de ces éléments vous sera réellement utile. Vous dites que vous voulez quelque chose qui ne déclenche pas le scénario "le fichier n'existe pas". Bien que cela signifie généralement une erreur ENOENT, dans la pratique, de nombreuses vérifications de niveau supérieur interpréteront simplement les erreurs de lstat (2) comme «n'existe pas». Par exemple, test -eou l'équivalent [ -e ...]du shell pourrait simplement interpréter tout ce qui précède comme "n'existe pas", d'autant plus qu'il n'a pas un bon moyen de renvoyer un message d'erreur différent et ne pas renvoyer une erreur impliquerait que le fichier existe, ce qui n'est certainement pas le cas.


@StephaneChazelas Excellent point! Mis à jour.
filbranden

6

Vous pouvez le findfaire vous-même.

En utilisant /etc- le répertoire des fichiers de configuration comme point de départ:

sudo find /etc -type f -perm 0400 -user root

Sur mon système, cela ne renvoie rien.

Vous pouvez être un groupe moins restrictif et autoriser root(seul l'utilisateur rootdoit être membre du groupe root), et rechercher une autorisation de 440:

sudo find /etc -perm 0440 -user root -group root

Sur mon système, cela renvoie:

/etc/sudoers.d/README
/etc/sudoers

Éditer:

En fonction de votre modification, vous recherchez un répertoire qui ne dispose pas des autorisations suffisantes pour que l'utilisateur appelant empêche la liste des répertoires:

sudo find / -perm o-rwx -type d -user root -group root 

ici je cherche des répertoires ( -type d) qui n'ont pas les bits perm en lecture-écriture-exécution pour others ( o-rwx) et qui appartiennent à root:root.

Techniquement, juste l'absence du xbit execute ( ) empêcherait une liste de répertoires ( lstat(2)) sur le répertoire.

Dans la sortie que j'ai trouvée /run/systemd/inaccessible/sur mon système basé sur l'init Systemd.

En ce qui concerne les fichiers /proc, /sys, /dev:

  • Ces systèmes de fichiers sont virtuels FS c'est-à-dire qu'ils résident sur la mémoire, pas sur le disque

  • Si vous prévoyez de vous fier à /proc, utilisez par /proc/1/exemple compter sur quelque chose sous PID 1, et non à des PID ultérieurs pour avoir une fiabilité / cohérence car les PID (processus) ultérieurs ne sont pas garantis d'exister.


Merci, je pense que ma question est fausse. Je peux toujours créer des fichiers sans y accéder en lecture. Peut-être que l'accès au dossier doit être limité? (J'ai modifié le titre)
Crouching Kitten

Merci. Avec find / -type d -perm 0400 -user rootj'ai trouvé le répertoire /proc/20/map_files/, si je fais référence à un nom de fichier créé à l'intérieur de ce dossier, comme /proc/20/map_files/asdasd, alors il échoue toujours. Ce dossier existe-t-il toujours sur Ubuntu?
Crouching Kitten

@CrouchingKitten, les répertoires dans /proc/1/pourraient être plus sûrs, car init existe toujours. Mais ce n'est procpas un système de fichiers ordinaire, au cas où cela compte.
ilkkachu

Merci, j'ai donné un vote positif, mais j'ai accepté l'autre réponse, car il a dit qu'il est garanti que cela /proc/1/fdinfo/0fonctionne sur Ubuntus moderne.
Crouching Kitten

-perm o-rwxest comme -perm 0, les bits sont tous éteints pour commencer. Ici, tu voudrais ! -perm -1.
Stéphane Chazelas
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.