Vim peut casser les permissions des fichiers?

8

J'utilisais Vim l'autre jour comme d'habitude, quand j'ai remarqué quelque chose d'étrange. Voici ce que j'ai fait:

~$ touch testfile
~$ ls -l | grep testfile
-rw-r--r-- 1 username groupname 0 Jul 23 10:00 testfile
~$ vim testfile

Ensuite, j'ai fait un changement, j'ai enregistré et j'ai quitté avec :wq. Assez normal. Mais alors:

~$ sudo chown root:root testfile
~$ sudo chmod 644 testfile
~$ sudo -k
~$ ls -l | grep testfile
-rw-r--r-- root root 0 Jul 23 10:02 testfile
~$ vim testfile

Donc, root devrait avoir un accès r / w et tout le monde devrait avoir seulement lu. Modifiez le fichier, essayez de l'enregistrer - vous ne pouvez pas. Génial, fonctionne comme prévu. Cependant, si vous enregistrez avec :w!, vim change en quelque sorte la propriété du fichier en nom d'utilisateur: groupe d'utilisateurs et le fichier est enregistré. Même si vous faites cela:

~$ sudo chmod 444 testfile
~$ sudo -k
~$ ls -l | grep testfile
-r--r--r-- 1 root root 0 Jul 23 10:06 testfile
~$ vim testfile

Vous pouvez toujours écraser avec :w!! Qu'est-ce qui se passe? Comment vim peut-il enfreindre les lois sur la propriété et l'autorisation des fichiers comme celle-ci? J'ai regardé la page d'aide dans vim en disant :help :wet j'ai trouvé ceci:

:w[rite]! [++opt]    Like ":write", but forcefully write when 'readonly' is set or there is another reason why writing was refused.
                     Note: This may change the permission and ownership of the file and break (symbolic) links. Add the 'W' flage to 'cpoptions' to avoid this.

Je n'ai pas pu écrire dans un fichier dans vim auparavant alors que je ne devrais pas le faire, donc je suppose que le véritable cœur de ma question est de savoir comment rendre un fichier non éditable par vim et pourquoi n'est-il pas basé sur un fichier les autorisations système, comme je m'y attendais, et quel mécanisme vim utilise-t-il pour éditer le fichier que les autres éditeurs (gedit, nano) ne peuvent pas utiliser?

EDIT: L'ordinateur sur lequel j'ai essayé utilise le noyau Linux 3.15.5-2-ARCH. Le numéro de version de Vim est 7.4.373-1, et c'est celui installé par pacman- je ne l'ai pas compilé à partir de zéro avec des options spéciales.

zrneely
la source
Je ne semble pas être en mesure de reproduire le problème, à moins de prendre quelques astuces comme décrit ici
Davyzhu
Je viens de l'essayer à nouveau en utilisant les commandes de la question, et cela s'est produit de la même manière. Je modifierai la question pour ajouter des détails sur mon ordinateur, car il semble que cela puisse dépendre de la plate-forme.
zrneely
Mon premier pressentiment est que vous êtes autorisé à changer la propriété des fichiers dans un répertoire auquel vous avez accès en écriture. Mais il semble que ce ne soit pas le cas . CAP_CHOWNest nécessaire d'appeler chown(2). Soit dit en passant, je peux reproduire sur Debian, avec vim 7.4.
Bob

Réponses:

10

Je peux voir que votre chemin d'accès actuel est ~le répertoire personnel de votre utilisateur. Vous devez avoir des autorisations d'écriture sur ce répertoire.

Pensez-y d'une autre manière - si vous avez des autorisations de lecture et d'écriture sur le répertoire, qu'est-ce qui vous empêche de copier le fichier, de supprimer l'ancien et de renommer le nouveau avec des autorisations différentes?

C'est exactement ce que fait Vim!


Si vous exécutez vim sous strace, par exemple:

open("testfile", O_WRONLY|O_CREAT|O_TRUNC, 0644) = -1 EACCES (Permission denied)
lstat("testfile", {st_mode=S_IFREG|0644, st_size=10, ...}) = 0
getuid()                                = 1000
unlink("testfile")                      = 0
open("testfile", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 3
write(3, "ffjidfjds\n", 10)             = 10
fsync(3)                                = 0
close(3)                                = 0
chmod("testfile", 0644)                 = 0

Sur la base de ce journal, je peux deviner le processus suivant:

Certaines vérifications des autorisations antérieures (et chowntentatives, etc.) sont omises par souci de concision.

  1. open Tentative d'ouverture du fichier en écriture (échec: autorisation refusée)
  2. lstat Vérifier le propriétaire du fichier
  3. getuuid Vérifiez l'ID utilisateur actuel pour voir s'il correspond au propriétaire du fichier
  4. unlink Supprimez le fichier (cela est autorisé car l'autorisation d'écriture sur le répertoire)
  5. open Créez un nouveau fichier avec le même nom
  6. write Le contenu du fichier (lu plus tôt, j'ai tapé du charabia)
  7. fsync Vider le fichier sur le disque (pas vraiment important)
  8. close
  9. chmod Modifiez les autorisations du nouveau fichier pour qu'il ressemble à l'ancien - il se trouve que vous avez maintenant un nouveau propriétaire.
Bob
la source
OK merci. Je suis content d'avoir compris cela. Donc, si je n'ai pas d'autorisations d'écriture sur le répertoire, je ne pourrai pas utiliser :w!, ce qui est logique.
zrneely
De plus, les informations de strace sont vraiment utiles - j'ai maintenant un autre outil pour mes propres enquêtes à l'avenir.
2014
1
@zrneely Un conseil pour strace: utiliser l' -ooption pour écrire la sortie dans un fichier; sinon, il se heurte à vimla sortie de. En ce qui concerne les droits d'écriture, je ne vois pas la vérification des autorisations de répertoire avec , statmais il ne tente de créer un fichier (nom 4913, semble aléatoire) dans le répertoire courant, puis le supprimer.
Bob
Il semble que ce ne 4913soit en fait que le prénom qu'il essaie, et son but est de vérifier s'il dispose des autorisations suffisantes pour le faire. Voir: bugzilla.redhat.com/show_bug.cgi?id=427711#c6 et groups.google.com/forum/#!topic/vim_dev/sppdpElxY44
Bob