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 :w
et 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.
la source
CAP_CHOWN
est nécessaire d'appelerchown(2)
. Soit dit en passant, je peux reproduire sur Debian, avec vim 7.4.Réponses:
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:
Sur la base de ce journal, je peux deviner le processus suivant:
Certaines vérifications des autorisations antérieures (et
chown
tentatives, etc.) sont omises par souci de concision.open
Tentative d'ouverture du fichier en écriture (échec: autorisation refusée)lstat
Vérifier le propriétaire du fichiergetuuid
Vérifiez l'ID utilisateur actuel pour voir s'il correspond au propriétaire du fichierunlink
Supprimez le fichier (cela est autorisé car l'autorisation d'écriture sur le répertoire)open
Créez un nouveau fichier avec le même nomwrite
Le contenu du fichier (lu plus tôt, j'ai tapé du charabia)fsync
Vider le fichier sur le disque (pas vraiment important)close
chmod
Modifiez les autorisations du nouveau fichier pour qu'il ressemble à l'ancien - il se trouve que vous avez maintenant un nouveau propriétaire.la source
:w!
, ce qui est logique.strace
: utiliser l'-o
option pour écrire la sortie dans un fichier; sinon, il se heurte àvim
la sortie de. En ce qui concerne les droits d'écriture, je ne vois pas la vérification des autorisations de répertoire avec ,stat
mais il ne tente de créer un fichier (nom4913
, semble aléatoire) dans le répertoire courant, puis le supprimer.4913
soit 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