Comment vim vole-t-il les fichiers appartenant à la racine?

39

Soyez témoin de ce qui suit:

sh-3.2$ mkdir testcase
sh-3.2$ cd testcase
sh-3.2$ sudo touch temp
sh-3.2$ ls -al
total 0
drwxr-xr-x   3 glen  staff  102 19 Dec 12:38 .
drwxr-xr-x  12 glen  staff  408 19 Dec 12:38 ..
-rw-r--r--   1 root  staff    0 19 Dec 12:38 temp

sh-3.2$ echo nope > temp
sh: temp: Permission denied

sh-3.2$ vim temp
# inside vim
itheivery
# press [ESC]
:wq!
# vim exits

sh-3.2$ ls -al
total 8
drwxr-xr-x   3 glen  staff  102 19 Dec 12:38 .
drwxr-xr-x  12 glen  staff  408 19 Dec 12:38 ..
-rw-r--r--   1 glen  staff    7 19 Dec 12:38 temp

D'une manière ou d'une autre, vim a pris ce fichier appartenant à la racine et l'a transformé en un fichier appartenant à l'utilisateur!

Cela ne semble fonctionner que si l'utilisateur est propriétaire du répertoire - mais cela semble quand même que cela ne devrait pas être possible. Quelqu'un peut-il expliquer comment cela est fait?

Glenjamin
la source

Réponses:

51

Vous glenêtes le propriétaire du répertoire (voir le .fichier dans votre liste). Un répertoire est simplement une liste de fichiers et vous avez la permission de modifier cette liste (par exemple, ajouter des fichiers, supprimer des fichiers, changer les propriétaires pour le rendre à nouveau, etc.). Vous ne pouvez pas être en mesure de modifier le contenu du fichier directement, mais vous pouvez lire et unlink (supprimer) le fichier dans son ensemble et ajouter de nouveaux fichiers par la suite. 1 Seulement en regardant avant et après, cela peut donner l'impression que le fichier a été modifié.

Vim utilise des fichiers d'échange et les déplace sous l'eau, ce qui explique pourquoi il semble écrire dans le même fichier que dans votre shell, mais ce n'est pas la même chose. 2

Donc, ce que Vim fait, se résume à ceci:

cat temp > .temp.swp          # copy file by contents into a new glen-owned file
echo nope >> .temp.swp        # or other command to alter the new file
rm temp && mv .temp.swp temp  # move temporary swap file back

1 Il s'agit d'une différence importante dans la gestion des autorisations de fichiers entre Windows et Unices. Sous Windows, il n’est généralement pas possible de supprimer des fichiers pour lesquels vous n’avez pas le droit d’écrire.

2 mise à jour: comme indiqué dans les commentaires, Vim ne le fait pas de cette façon pour changer de propriétaire, car le numéro d'inode du tempfichier ne change pas ( ls -liavant et après). En utilisant stracenous pouvons voir exactement ce qui vimfait. La partie intéressante est ici:

open("temp", O_WRONLY|O_CREAT|O_TRUNC, 0664) = -1 EACCES (Permission denied)
unlink("temp")                               = 0
open("temp", O_WRONLY|O_CREAT|O_TRUNC, 0664) = 4
write(4, "more text bla\n", 14)              = 14
close(4)                                     = 0
chmod("temp", 0664)                          = 0

Cela montre qu'il ne fait que dissocier , mais ne ferme pas le descripteur de fichier à temp. Il remplace plutôt tout son contenu ( more text bla\ndans mon cas). Je suppose que cela explique pourquoi le numéro d'inode ne change pas.

Gertvdijk
la source
3
FWIW vous pouvez vérifier que cela se produit en exécutant ls -ilavant et après ... si temple numéro d'inode a changé, vous savez qu'il s'agit d'un fichier différent portant le même nom.
Inutile
3
On pourrait ajouter que rm ne supprime pas réellement le fichier, mais supprime simplement un lien vers le fichier et que le fichier n'est pas supprimé avant que le nombre de liens ne soit réduit à 0. rm supprime simplement l'entrée du fichier dans le répertoire. Si root a un autre lien (lien dur) vers le fichier dans un autre répertoire, l'utilisateur ne peut pas supprimer le fichier.
gerrit
1
@ Inutile j'ai essayé, et le nombre n'a pas changé bien que le propriétaire et l'horodatage aient changé!
Amyassin
1
@amyassin Vous avez raison! J'ai mis à jour ma réponse avec un extrait de strace l'expliquant.
gertvdijk
1
Si vous voulez un comportement semblable à Windows sous Unix, vous pouvez créer un répertoire appartenant à root (ou à un autre utilisateur qui devrait disposer d'autorisations universelles de suppression / changement de nom / etc) et définissez le paramètre persistant. bit sur le répertoire. Les utilisateurs ne pourront alors supprimer que leurs propres fichiers.
Matthew Crumley
16

avant:

-rw-r--r-- 1 root staff 0 19 Dec 12:38 temp

après:

-rw-r--r-- 1 glen staff 7 19 Dec 12:38 temp

Vim ne franchit pas la barrière des autorisations. Il suffit de jeter un coup d’œil aux informations sur le fichier répertoriées avec précaution, vous pourrez alors découvrir que vim a effectivement supprimé le fichier original (car vous avez l’autorisation de supprimer le fichier même si vous ne pouvez pas en modifier le contenu), puis vous avez créé un nouveau fichier ( voir le propriétaire n'est plus 'root').

Et lorsque vous modifiez le fichier d'origine dans vim, il vous avertit que vous modifiez un fichier en lecture seule. Ainsi, lorsque vous tapez la commande :wq!(forcer l'opération), vim ne peut que supprimer le fichier existant et créer un nouveau fichier portant le même nom.

J'espère que ça t'as aidé.

ymfoi
la source
1

Utilisez l' -ioption de lspour voir le numéro d'inode, qui est un identifiant unique (dans le système de fichiers) d'un fichier ou d'un autre objet.

Vous verrez que le fichier a été remplacé par un autre objet: le numéro d'inode changera probablement.

Voir le même numéro d'inode ne prouve rien: un numéro d'inode peut être recyclé. Si nous supprimons le dernier lien vers un fichier et créons ensuite un nouveau fichier, nous pourrions en obtenir un avec le même numéro d'inode. Mais cela ne peut pas arriver si l'ancien fichier est supprimé après la création du nouveau. Par exemple mv file file.tmp; touch file; rm file.tmp. Je soupçonne que Vim fait quelque chose d'analogue à cela echo new_content > tmpfile; mv tmpfile file. L' mvopération sera traduite en un renameappel système. L'attribution de numéros d'inode dépend donc de la manière dont le système de fichiers implémente un changement de nom qui dissocie une destination.

Kaz
la source