Perché posso modificare un file di sola lettura?


42

Breve domanda:

Perché possiamo manipolare un file di sola lettura in Vim usando :+ w+ q+ !anche senza essere un amministratore?

Domanda lunga:

Ho un file di testo (myFile.txt) che è di sola lettura per tutti:

navid@navid-ThinkPad-T530:~/ubuntuTest$ ls -l myFile.txt 
-r--r--r-- 1 navid navid 26 Aug 22 21:21 myFile.txt

Posso aprirlo con Vim senza avere i privilegi di amministratore:

navid@navid-ThinkPad-T530:~/ubuntuTest$ vi myFile.txt 

Lo modifico e premo: Esc+ :+ w+ q+ Entere vedo questo messaggio di errore:

E45: 'readonly' option is set (add ! to override)

Finora tutto ha un senso. Ma quando premo: Esc+ :+ w+ q+ !+ Enter, Vim salva le modifiche.

Sto usando Ubuntu 16.04 e VIM 7.4.


1
@Zanna Possiedi la directory in cui si trova il file?
Rob,

Sì, questo sarebbe un problema enorme altrimenti :)
Rob

11
La modifica di un file e la sostituzione di un file sono due cose diverse con requisiti di autorizzazione diversi.
David Schwartz,

1
Potresti dare un'occhiata a questo . Fondamentalmente risponde alla tua domanda e come correttamente sottolineato da @DavidSchwartz :Modifying a file and replacing a file are two different things
Panagiotis Tabakis

@PanagiotisTabakis Molto bello trovare questo è geniale .. chmod per rendere il file in lettura-scrittura e viceversa se lo possiedi .. ADORO :)
Rob

Risposte:


58

Come già accennato da @Rob , puoi farlo solo se hai accesso in scrittura alla directory che contiene il file. Il tentativo di fare la stessa cosa su un file, ad esempio, /etcfallirà.

Per quanto riguarda come vim sta facendo, elimina il file e lo ricrea. Per verificarlo, ho creato un file di proprietà di root:

echo foo | sudo tee fff

E poi ho proceduto alla modifica del file con vimil modo in cui descrivi, ma allego il processo straceper vedere cosa sta succedendo:

strace vim fff 2> strace.out

Ho quindi controllato strace.oute trovato:

unlink("fff")                           = 0
open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 4
write(4, "foasdasdao\n", 11)            = 11

Quindi, il file è stato prima eliminato ( unlink("fff")), quindi è stato creato un nuovo file con lo stesso nome ( open("fff", O_WRONLY|O_CREAT|O_TRUNC, 0644)) e le modifiche che avevo apportato sono state scritte su di esso ( write(4, "foasdasdao\n", 11)). Se lo provi a casa, vedrai che dopo averlo modificato con vim, il file ora apparterrà a te e non a root.

Quindi, a rigor di termini, vimnon sta modificando un file a cui non si ha accesso in scrittura. Si sta eliminando un file da una directory in cui si ha accesso in scrittura e quindi si crea un nuovo file a cui, di nuovo, si ha accesso in scrittura.



8
@CCJ è un'operazione di scrittura nella directory ma non nel file, no. Le operazioni di scrittura sui file sono quelle che modificano il contenuto del file. Allo stesso modo, la creazione / eliminazione di file è un'operazione di scrittura nella directory poiché si sta modificando il suo contenuto.
terdon

2
Inoltre, è un pericoloso ordine di operazioni. Sarebbe più sicuro scrivere la sostituzione in un nuovo nome file e quindi utilizzare rename(2)per sostituire il vecchio file. Quindi non esiste una finestra temporale in cui i dati non esistono sul disco.
Peter Cordes,

5
@PeterCordes um, OK. Tuttavia, potresti voler inoltrare i tuoi reclami agli sviluppatori di VIM. Non uso nemmeno la cosa, sono nel campo di emacs.
terdon

3
@CCJ L'eliminazione di un file è un'operazione di scrittura nella directory che lo contiene, non nel file stesso. È perfettamente intuitivo che se sei responsabile di una directory (ad esempio, hai accesso in scrittura ad essa), dovresti essere in grado di controllare cosa c'è in essa, e il proprietario di un singolo file non dovrebbe essere autorizzato a sovrascriverti.
fkraiem,

16

Finché possiedi la directory principale puoi rimuovere o sostituire un file indipendentemente dall'autorizzazione poiché puoi modificare il contenuto della directory :).

Provalo con altri comandi come rm, ti verrà richiesto ma puoi ancora farlo. Rendi la directory non scrivibile e questo dovrebbe fermarla.

aggiunta:

Ho appena provato, ma finché possiedo il file posso ancora modificarlo, anche con la cartella di sola lettura. Tuttavia, quando cambio la proprietà in root: root non può aprire il file per la scrittura. Quindi risolve i file di modifica di proprietà di root (o di qualcun altro)


7
Sembra che VIM scelga tra più strategie, tra cui riscrivere sul posto o scollegare + scrivere un nuovo file.
Peter Cordes,

3
@PeterCordes Sì Apparentemente si sforzerà molto di fare quello che gli dici :) molto furbo. :)
Rob,

16

Usando w!si rimuove il file originale ( cosa che si è autorizzati a fare ) e si scrive invece la versione.

Quando si ha accesso in scrittura a una directory, è possibile: creare, spostare o eliminare file all'interno di quella directory.

$ mkdir foo
$ echo hi > foo/file
$ chmod 777 foo
$ chmod 700 foo/file
$ ls -l foo/file 
-rwx------ 1 ravexina ravexina 7 Aug 31 03:19 foo/file

Ora fammi cambiare utente e cambiare il file

$ sudo -u user2 -s
$ vi foo/a # save using w! (I wrote into the file bye)
$ ls -l foo/a
-rwx------ 1 user2 user2 7 Aug 31 03:20 foo/file

Ora vedi cosa c'è dentro:

$ cat foo/file
bye

10

Vedi :help write-readonly:

                                                        write-readonly
When the 'cpoptions' option contains 'W', Vim will refuse to overwrite a
readonly file.  When 'W' is not present, ":w!" will overwrite a readonly file,
if the system allows it (the directory must be writable).

Poiché si dispone delle autorizzazioni di scrittura sulla directory (ovvero è possibile creare, eliminare o rinominare i file in essa contenuti), il sistema lo consente.


Il valore predefinito di cpoptionsnon contiene W:

                                                'cpoptions' 'cpo' cpo
'cpoptions' 'cpo'       string  (Vim default: "aABceFs",
                                 Vi default:  all flags)
                        global

2

Questo è un avvertimento di VIM che potrebbe essere relativamente importante considerando come funzionano le autorizzazioni in UNIX. L'apparente non intuitività di ciò è dovuta al fatto che i filesystem UNIX dispongono delle autorizzazioni per i file archiviati nell'i-node del file. La struttura della directory è in qualche modo separata e collega solo questi i-nodi. Le directory hanno anche le loro autorizzazioni che indicano se è possibile collegare / scollegare i file al suo interno, oppure leggerlo o attraversare le sottodirectory. Questo design consente di visualizzare lo stesso file in diversi punti della struttura della directory (tramite collegamenti reali). Dicendo "aggiungi! Per sovrascrivere" VIM sta cercando di avvisarti che il file originale non sarà collegato (quindi rimarrà intatto in tutti gli altri posti) e che il nuovo file verrà creato e collegato al posto originale nella struttura della directory. Nel caso in cui il conteggio dei collegamenti del file originale diminuisca a zero, il file originale verrà liberato, ma in caso contrario, si sta effettivamente clonando il file. L'apertura del file conta anche come collegamento, quindi se un programma ha aperto il file e si accetta di "aggiungere! Per sovrascrivere", il programma non vedrà le modifiche apportate al file con VIM. Il file viene scollegato dalla directory solo da VIM e dopo aver chiuso il file da un altro programma, il file verrà liberato, a meno che non sia stato collegato altrove.

Si noti che in Windows, le autorizzazioni per i file sono archiviate nella directory, quindi dal punto di vista del paradigma delle autorizzazioni di Windows, questo comportamento vim potrebbe davvero sembrare strano. Per scrivere sul file, Windows potrebbe logicamente controllare anche alcune autorizzazioni di directory, anche autorizzazioni di super-directory. Come detto sopra, in UNIX, i permessi di directory sono irrilevanti per la manipolazione del file nella misura in cui è stato possibile elencarlo e aprirlo (cioè c'erano x per tutte le super-directory). Il file aperto in UNIX potrebbe non avere più il nome del file anche se dopo essere stato scollegato da tutte le directory.

Ad esempio, hai il file / home / user1 / foo ed è lo stesso file di (ovvero hardlinked to) / home / user2 / foo e il file non è scrivibile da nessuno e attualmente aperto dal programma P (aperto in lettura-scrittura da programma avviato da root). Se user1 lo apre con vim e lo sovrascrive, crea la propria copia e non vede più il file originale. Se successivamente user2 apre il suo link con vim e lo scrive, verrà nuovamente scollegato e ne creerà un'altra copia. Il programma P vedrà comunque il file originale e potrà liberamente leggerlo o scriverlo. Non appena il programma chiude il file, il file scompare (viene liberato dal filesystem).


2

Sia il tuo processo dell'editor vim che il tuo file portano il tuo

 getpwnam("navid")->pw_uid

proprietà in modo che tu possa anche sborsare

 :!chmod +w %

e potresti immaginare che una volta era ancora più semplice

 :!rm %

(richiedendo solo + w, il permesso di scollegamento su. e nemmeno la proprietà) è diventato troppo frequente per qualcuno da digitare in modo che Vim fosse riprogrammato per offrire automaticamente e su richiesta eseguire automagicamente tale operazione.

Prova a sovrascrivere tua sorella maggiore

 /home/whoopi/.profile

dato che il semplice vascello e le scommesse sono il tuo vim ti dà il rifiuto desiderato.


Grazie @Zanna per la modifica del codice anche se mi è costato un po 'di reputazione ai principianti, meritatamente.
Roman Czyborra,

1

Questa non è esattamente una risposta, ma se vuoi davvero impostare un file in modo che nessuno possa modificarlo o eliminarlo, puoi renderlo immutabile.

Normalmente, anche quando un file è di proprietà di root, è comunque possibile eliminare il file se si dispone delle autorizzazioni di scrittura per la cartella. Ma quando si rende il file immutabile, anche root non può modificarlo o eliminarlo.

Per rendere immutabile un file (è necessario sudo):

sudo chattr +i myFile.txt

Puoi vederlo con lsattr(la lettera inel risultato):

$ lsattr myFile.txt
----i--------e-- myFile.txt

Per rendere di nuovo normale il file:

sudo chattr -i myFile.txt

Per chiarire: quando un file è immutabile, non può essere cancellato, rinominato, modificato o addirittura collegato.

Vale la pena leggere man chattr, perché i file possono avere una serie di attributi utili.

Potresti anche trovare utile la "cancellazione limitata". Se posizionato su una cartella (non un file), ciò significa che chiunque crei un file all'interno della cartella è autorizzato a modificare o eliminare quel file, ma nessun altro lo è (tranne root). La cartella /tmpha questo flag impostato. Puoi vederlo con la tbandiera su /tmp:

$ ls -l --directory /tmp
drwxrwxrwt 10 root root 4096 Sep  6 09:00 /tmp

Per impostare o rimuovere il flag di eliminazione limitata su una cartella:

chmod +t myFolder      # Add the restricted deletion flag.
chmod -t myFolder      # Remove the restricted deletion flag.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.