Un fichier peut-il être récupéré par son inode?

27

J'ai exécuté les commandes suivantes dans l'ordre spécifié:

$ln a b
$ls -i a b
523669 a 523669 b
$rm -f a
$ls -i b
523669 b

J'ai conclu de ce test que la commande rmsupprime uniquement le nom de fichier ( adans ce test) au lieu du fichier, car l'inode existe toujours et pourrait être récupéré via un autre nom de fichier ( b).

Ma question est la suivante: si un fichier est lié en dur à un seul nom de fichier, lorsqu'il rmest exécuté dans le fichier, le vrai fichier (c'est-à-dire l'inode) est-il complètement supprimé? Et sinon, un inode de fichier peut-il être récupéré sans nom de fichier et uniquement via l'inode?

user43312
la source
Cela me semble spécifique au système d'exploitation.
Ignacio Vazquez-Abrams
@Ignacio Vazquez-Abrams. Vous voulez dire que cela dépend de la version?
user43312
Non, je veux dire que cela dépend du système d'exploitation. Chacun a des façons différentes (le cas échéant ) de puiser dans le VFS.
Ignacio Vazquez-Abrams
@Ignacio Vazquez-Abrams Avez-vous une idée de RHL ou RHEL?
user43312
1
@BruceEdiger Os X sorte de cela. Vous pouvez accéder à un objet de système de fichiers à l'aide d'une "URL de référence de fichier" qui est, fondamentalement, construite à partir du numéro de système de fichiers et du numéro de nœud. Cependant, il n'est pas officiellement pris en charge pour les construire vous-même. Au lieu de cela, vous obtenez une «URL de référence de fichier» pour un fichier, puis vous l'utilisez à la place du chemin d'accès pour les accès ultérieurs dans la même session d'exécution afin que votre application ne soit pas consciente du déplacement du fichier ailleurs sur le même volume.
Fichier analogique

Réponses:

29

Si vous essayez d'ouvrir un fichier via son inode, cela contourne toute traversée de répertoire. La traversée du répertoire est nécessaire pour déterminer les autorisations du fichier et des répertoires y menant. Sans traversée de répertoire, le noyau n'a aucun moyen de déterminer si le processus appelant est autorisé à accéder au fichier.

Il y avait un correctif proposé pour le noyau Linux pour permettre de créer un lien vers un fichier à partir d'un descripteur de fichier . Elle a été rejetée car la mise en œuvre de cette méthode en toute sécurité aurait été extrêmement difficile .

Sous Linux (et probablement sur d'autres variantes Unix pour la même raison), vous ne pouvez pas créer de lien vers un fichier supprimé, donc si un fichier n'a plus de nom, vous ne pouvez pas en rajouter un .¹ Vous pouvez ouvrir un fichier supprimé fichier en ouvrant les liens magiques sous /proc/$pid/fd/.

Si un fichier n'a plus de lien et n'est plus ouvert, il n'existe plus et l'espace anciennement utilisé par ses données peut être récupéré à tout moment.

¹ Vous pouvez le faire en tournant les octets directement dans le système de fichiers en fonction du système de fichiers, par exemple avec debugfspour ext2 / ext3 / ext4. Cela nécessite un accès au périphérique sur lequel le système de fichiers est monté (c'est-à-dire que seul root peut l'essayer). Cependant, alors que debugfs peut accéder à un fichier par inode, cela n'aide pas si le fichier est supprimé: le fichier sera vraiment supprimé si l'application le ferme, et l'exécution de debugfs en mode lecture-écriture sur un système de fichiers monté est une recette pour catastrophe.

Gilles 'SO- arrête d'être méchant'
la source
11

Sous Linux, debugfsle débogueur de système de fichiers interactif ext2 / ext3 / ext4 fournit une lncommande qui peut prendre un numéro d'inode filespecet créer un nouveau lien dur vers le fichier correspondant. En pratique cependant, cela nécessite que le fichier non lié soit maintenu ouvert par un processus , en maintenant un descripteur de fichier ouvert dans /proc/[pid]/fd/[n]. Tenter de le faire sur un fichier supprimé entraînera très probablement une corruption du système de fichiers.

En effet, afin de garantir que ext3 (et dans l'extension ext4) peut reprendre en toute sécurité une dissociation après un crash, il met à zéro les pointeurs de bloc dans l'inode , tandis que ext2 marque simplement ces blocs comme inutilisés dans les bitmaps de bloc et marque le inode comme "supprimé" et laisse les pointeurs de bloc seuls. Même ainsi, comme le système de fichiers doit être monté en lecture-écriture pour créer le lien dur, les blocs réservés pour le fichier supprimé peuvent déjà avoir été réalloués.

Avant la version 2.6.39 du noyau, il était possible que l' option introduite dans GNU coreutils v8.0 puisse être utilisée pour récupérer un fichier non lié via un descripteur de fichier ouvert si le fichier non lié et le nouveau lien physique résidaient sur un système de fichiers tmpfs . Cette capacité a depuis été désactivée en raison, comme l'a souligné Gilles , des considérations de sécurité impliquées dans la création de liens physiques directement à partir d'un descripteur de fichier.ln -L|--logical/proc/[pid]/fd/[n]

Thomas Nyman
la source
J'ai juste essayé d'utiliser ln -Lpour récupérer un fichier supprimé à partir de / proc et j'ai obtenu l'erreur: "Aucun fichier ou répertoire", donc je ne pense pas qu'il supporte réellement cela. J'ai coreutils 8.21.
wingedsubmariner
1
ln -Lne fait pas ce que vous dites. Il indique lnque si la source est un lien symbolique, elle doit lier en dur la cible. Les liens symboliques dans /proc/$pid/fdsont spéciaux et un (deleted)lien dur avec un lien ne fonctionne pas.
Gilles 'SO- arrête d'être méchant'
N'aidera debugfspas non plus si le fichier a été supprimé - sauf si vous voulez risquer de l'exécuter en mode lecture-écriture sur un système de fichiers monté, ce qui est susceptible de complètement gâcher tout le système de fichiers.
Gilles 'SO- arrête d'être méchant'
Mise à jour de la réponse concernant ln -L. Il était possible de créer des liens durs à partir de son /proc/[pid]/fd/[n]utilisation dans certaines circonstances spéciales, mais cela a depuis été corrigé.
Thomas Nyman
1
debugfsLe niveau lnest vraiment bas et ne crée qu'un nom, ne met pas à jour le décompte et ne désélectionne pas les blocs comme inutilisés, il est donc très dangereux . Préférer debugfs« s undelqui des tout cela. Attention: debugfsest de ne pas être exécuté sur un système de fichiers monté à moins que vous voulez prendre une chance de brûler votre FS en cendres.
Lloeki
9

Les commandes 'ln' et 'rm' fonctionnent exactement comme ceci dans tous les systèmes de fichiers UNIX depuis le début des années 1970. Mac OSX, BSD et Linux héritent tous de cette conception originale.

En soi, un fichier UNIX n'a ​​pas de nom, seulement un numéro d' inode ou un inum. Mais vous ne pouvez y accéder que par une entrée dans un fichier "répertoire" spécial qui associe un nom à l'inum en question; vous ne pouvez pas spécifier directement l'inum.

Un répertoire est lui - même un fichier, vous devez donc également accéder à ce travers (un autre) annuaire et ainsi de suite, à travers une série de noms de répertoires délimités par des barres obliques vers l' avant (/) connu sous le nom d' un « nom de chemin ». Un chemin commence dans le "répertoire de travail actuel" du processus, sauf si le nom commence par un "/", auquel cas il commence par le répertoire racine du système de fichiers. Par exemple, si le nom du chemin ne contient aucun caractère "/", il devrait être une entrée dans le répertoire courant.

Un fichier non répertoire peut avoir n'importe quel nombre de noms de chemin d'accès, appelés «liens matériels», et il continuera d'exister jusqu'à ce que tous ses noms de chemin d'accès aient été supprimés et que le dernier processus ait fermé le fichier. Ensuite, le fichier est réellement supprimé et son espace marqué comme disponible pour une réutilisation. Autrement dit, vous pouvez créer () ou ouvrir () un fichier lié individuellement, puis le dissocier () pour qu'il n'apparaisse plus dans l'espace de nom du système de fichiers, mais le fichier continuera d'exister jusqu'à ce que vous le fermiez. Ceci est utile pour les fichiers de travail temporaires qui ne seront lus par aucun autre programme.

Bien que les répertoires aient des numéros d'inode, la plupart des systèmes de fichiers interdisent les liens durs vers eux; ils ne peuvent apparaître que dans un autre répertoire. (Une exception inhabituelle est le système de fichiers Mac OSX HFS +; cela permet aux sauvegardes Time Machine de fonctionner.) Vous pouvez toujours créer des "liens logiciels" vers des répertoires (ou tout autre fichier). Un lien logiciel ressemble à une entrée de répertoire, sauf qu'il contient un autre nom de chemin plutôt qu'un inum.

Chaque fichier UNIX possède un propriétaire, un groupe et des autorisations d'accès. Il est nécessaire mais pas suffisant qu'ils vous permettent d'ouvrir le fichier; vous devez également avoir au moins l'autorisation d'exécution pour chaque répertoire du nom de chemin que vous utilisez pour vous y référer. C'est pourquoi il n'existe aucun moyen standard d'ouvrir un fichier UNIX par son numéro d'inode; cela contournerait un mécanisme de sécurité important et largement utilisé.

Mais cela n'explique pas pourquoi il ne peut pas y avoir de moyen standard pour un utilisateur root (privilégié) d'ouvrir un fichier par numéro d'inode, car la vérification des autorisations est de toute façon contournée. Cela serait très utile pour certaines fonctions de gestion du système telles que les sauvegardes. À ma connaissance, de tels mécanismes existent, mais ils sont tous spécifiques au système de fichiers; il n'y a aucun moyen général de le faire pour n'importe quel système de fichiers UNIX.

Phil Karn
la source
1
L'avant /est silencieux, il est donc prononcé «barre oblique».
ctrl-alt-delor
4

La question peut être prise théoriquement (ce qui peut être réalisé avec debugfs) ou pragmatique (situation d'urgence). Dans ce dernier cas, je suppose que l'intention est de sauver la journée et de restaurer le contenu du fichier, peut-être de toute urgence (c'est ainsi que j'ai atterri sur cette question, donc je pense qu'elle est toujours pertinente et utile).

Comme il n'y a pas d'API du noyau, debugfsne doit pas être exécuté sur un système de fichiers en direct car il manipule directement la structure FS. Par conséquent, pour le faire en direct, vous devez vous procurer un autre nom de fichier. En supposant que le fichier est toujours ouvert par un processus (n'importe quel processus), on peut accéder aux descripteurs de fichiers toujours pratiques dans /proc:

$ lsof -F pf "$PWD/a" | sed 's/^p//' # find pid and file descriptor number of any process having the file open
$ pid=1234
$ ls -l /proc/$pid/fd/* | grep "$PWD/a" # find file descriptor number
$ fd=42
$ cat /proc/$pid/fd/$fd > "$PWD/a.restored" # read contents to a new filename

Conseils:

  • si vous avez un doute sur le bon fd, vous pouvez exécuter des commandes comme celle- fileci
  • s'il y a un processus d'écriture dans le fichier, assurez-vous d'arrêter ce processus dès que possible ou vous n'obtiendrez pas les dernières données. Une astuce (non testée) peut être d'ouvrir le fichier en lecture seule via le fd avec un autre processus (essayez de tail -f < /proc/$pid/fd/$fd > /dev/nullquitter le processus d'écriture pour qu'il se termine proprement et utilisez le fd du nouveau processus.
Lloeki
la source
2
Cela devrait être tail -f < /proc/...dans la deuxième astuce.
Murray Jensen
Ou utilisez-le tail -c +0 -f pour le copier en premier lieu au lieu de cat, si le processus d'écriture ne fait que s'ajouter (ne pas chercher en arrière et réécrire). Quittez l'autre processus avant tail, puis attendez taild'arriver à la fin du fichier.
Peter Cordes