Un file può essere recuperato dal suo inode?


27

Ho eseguito i seguenti comandi nell'ordine specificato:

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

Da questo test ho concluso che il comando rmrimuove effettivamente solo il nome file ( ain questo test) anziché il file, poiché l'inode esiste ancora e potrebbe essere recuperato tramite un altro nome file ( b).

La mia domanda è: se un file è strettamente collegato a un solo nome file, quando rmviene eseguito sul file, il file reale (cioè l'inode) viene rimosso completamente? E se no, un inode di file può essere recuperato senza un nome file e solo attraverso l'inode?


Mi sembra specifico del sistema operativo.
Ignacio Vazquez-Abrams,

@Ignacio Vazquez-Abrams. Vuoi dire che dipende dalla versione?
user43312

No, intendo che dipende dal sistema operativo. Ognuno ha modi diversi (se presenti ) di accedere al VFS.
Ignacio Vazquez-Abrams,

@Ignacio Vazquez-Abrams Hai qualche idea su RHL o RHEL?
user43312

1
@BruceEdiger Os X lo fa. Puoi accedere a un oggetto filesystem usando un "URL di riferimento al file" che è fondamentalmente costruito dal numero del file system e dal numero del nodo. Tuttavia, non è ufficialmente supportato per costruirli da soli. Invece si ottiene un "URL di riferimento al file" per un file e quindi lo si utilizza al posto del nome percorso per gli accessi successivi nella stessa sessione di runtime in modo che l'applicazione diventi ignara del fatto che il file venga spostato altrove sullo stesso volume.
File analogico

Risposte:


29

Se provi ad aprire un file tramite il suo inode, questo ignora qualsiasi attraversamento di directory. Il traversal di directory è necessario per determinare le autorizzazioni del file e delle directory che lo portano. Senza un attraversamento di directory, il kernel non ha modo di determinare se il processo di chiamata può accedere al file.

È stata proposta una patch al kernel Linux per consentire la creazione di un collegamento a un file da un descrittore di file . È stato respinto perché implementarlo in modo sicuro sarebbe stato estremamente difficile .

Sotto Linux (e probabilmente su altre varianti unix per lo stesso motivo), non è possibile creare un collegamento a un file eliminato, quindi se un file non ha più un nome, non è possibile aggiungerne di nuovo uno.¹ È possibile aprire un file eliminato file aprendo i collegamenti magici sotto /proc/$pid/fd/.

Se un file non ha più alcun collegamento e non è più aperto, non esiste più e lo spazio precedentemente utilizzato dai suoi dati può essere recuperato in qualsiasi momento.

¹ Potrebbe essere possibile farlo twiddly i byte direttamente nel filesystem in modo dipendente dal filesystem, ad esempio con debugfsext2 / ext3 / ext4. Ciò richiede l'accesso al dispositivo su cui è montato il filesystem (cioè in genere solo il root può provarlo). Tuttavia, mentre debugfs può accedere a un file tramite inode, questo non aiuta se il file viene eliminato: il file verrà effettivamente eliminato se l'applicazione lo chiude e l'esecuzione di debugfs in modalità lettura-scrittura su un filesystem montato è una ricetta per disastro.


11

Su Linux, debugfsil debugger interattivo del file system ext2 / ext3 / ext4 fornisce un lncomando che può prendere un numero di inode filespece creare un nuovo collegamento reale al file corrispondente. In pratica, tuttavia, ciò richiede che il file non collegato sia tenuto aperto da un processo , mantenendo un descrittore di file aperto in /proc/[pid]/fd/[n]. Tentare questo su un file cancellato molto probabilmente porterà alla corruzione del file system.

Questo perché al fine di garantire che ext3 (e l'estensione ext4) possano riprendere in modo sicuro un unlink dopo un crash, in realtà azzera i puntatori di blocco nell'inode , mentre ext2 contrassegna questi blocchi come inutilizzati nelle bitmap del blocco e contrassegna il inode come "cancellato" e lascia soli i puntatori di blocco. Tuttavia, poiché è necessario montare il file system in lettura-scrittura per creare il collegamento reale, i blocchi riservati per il file eliminato potrebbero essere già stati riallocati.

Prima della versione 2.6.39 del kernel, era possibile che l' opzione introdotta in GNU coreutils v8.0 potesse essere utilizzata per recuperare un file non collegato tramite un descrittore di file aperto se entrambi i file non collegati e il nuovo hardlink risiedevano in un file system tmpfs . Da allora, questa funzionalità è stata disabilitata a causa, come sottolineato da Gilles , delle considerazioni sulla sicurezza necessarie per consentire la creazione di collegamenti diretti direttamente da un descrittore di file.ln -L|--logical/proc/[pid]/fd/[n]


Ho appena provato a usare ln -Lper recuperare un file cancellato da / proc e ho ricevuto l'errore: "Nessun file o directory", quindi non credo che supporti effettivamente questo. Ho coreutils 8.21.
wingedsubmariner,

1
ln -Lnon fa quello che dici che fa. Indica lnche se l'origine è un collegamento simbolico, dovrebbe essere difficile collegare l'obiettivo. I collegamenti simbolici /proc/$pid/fdsono speciali e il collegamento diretto di un (deleted)collegamento non funziona.
Gilles 'SO- smetti di essere malvagio' il

Inoltre debugfs, non sarà d'aiuto se il file è stato eliminato, a meno che non si desideri rischiare di eseguirlo in modalità di lettura / scrittura su un filesystem montato, che rischia di rovinare completamente l'intero filesystem.
Gilles 'SO- smetti di essere malvagio' il

Aggiornato la risposta in merito a ln -L. In passato era possibile creare collegamenti reali /proc/[pid]/fd/[n]dall'utilizzo in determinate circostanze speciali, ma da allora è stato risolto.
Thomas Nyman,

1
debugfsIl lnlivello è davvero basso e crea solo un nome, non aggiorna il conteggio né deseleziona i blocchi come inutilizzati, quindi è altamente pericoloso . Preferiscono debugfss' undelche des tutto questo. Attenzione: debugfsè di non essere eseguito su un filesystem montato a meno che non si vuole prendere una possibilità di bruciare le FS in cenere.
Lloeki il

9

I comandi 'ln' e 'rm' hanno funzionato esattamente così in tutti i filesystem UNIX dall'inizio degli anni '70. Mac OSX, BSD e Linux ereditano tutti questo design originale.

Di per sé, un file UNIX non ha nome, solo un numero di inode o inum. Ma puoi accedervi solo attraverso una voce in uno speciale file "directory" che associa un nome all'inum in questione; non è possibile specificare direttamente l'inum.

Una directory è essa stessa un file, quindi è necessario accedere anche esso tramite la directory (un altro) e così via, attraverso una serie di nomi di directory delimitato da barre (/), noto come un "percorso". Un percorso inizia nella "directory di lavoro corrente" del processo a meno che il nome non inizi con un "/", nel qual caso inizia con la directory principale del file system. Ad esempio, se il nome del percorso non contiene caratteri "/", si prevede che sia una voce nella directory corrente.

Un file non di directory può avere un numero qualsiasi di nomi di percorso, noti come "collegamenti reali", e continuerà a esistere fino a quando tutti i suoi nomi di percorso non saranno stati rimossi e l'ultimo processo avrà chiuso il file. Quindi il file viene effettivamente eliminato e il suo spazio contrassegnato come disponibile per il riutilizzo. Cioè, puoi creare () o aprire () un file collegato singolarmente e quindi scollegarlo () in modo che non appaia più nello spazio dei nomi del file system, ma il file continuerà a esistere fino a quando non lo chiudi. Ciò è utile per i file temporanei temporanei che non verranno letti da nessun altro programma.

Sebbene le directory abbiano numeri di inode, la maggior parte dei file system non consente collegamenti rigidi ad essi; possono apparire solo in un'altra directory. (Un'eccezione insolita è il file system HFS + di Mac OSX; ciò consente il funzionamento dei backup di Time Machine.) È comunque possibile creare "collegamenti software" alle directory (o qualsiasi altro file). Un collegamento software assomiglia a una voce della directory tranne per il fatto che contiene un altro nome di percorso anziché un inum.

Ogni file UNIX ha un proprietario, un gruppo e autorizzazioni di accesso. È necessario ma non sufficiente che ti consentano di aprire il file; è inoltre necessario disporre almeno dell'autorizzazione di esecuzione per ogni directory nel percorso che si utilizza per fare riferimento ad essa. Ecco perché non esiste un modo standard per aprire un file UNIX in base al suo numero di inode; ciò aggirerebbe un importante meccanismo di sicurezza ampiamente utilizzato.

Ma questo non spiega perché non ci possa essere un modo standard per un utente root (privilegiato) di aprire un file per numero di inode, poiché il controllo delle autorizzazioni viene comunque ignorato. Ciò sarebbe molto utile per alcune funzioni di gestione del sistema come i backup. Per quanto ne so, esistono meccanismi di questo tipo, ma sono tutti specifici del filesystem; non esiste un modo generale per farlo per qualsiasi filesystem UNIX.


1
L'avanti /è silenzioso, quindi è pronunciato "barra".
ctrl-alt-delor,

4

La domanda può essere presa teoricamente (che può essere raggiunto con debugfs) o pragmaticamente (situazione di emergenza). In quest'ultimo caso, suppongo che l'intento sia salvare la giornata e ripristinare il contenuto del file, possibilmente con urgenza (che è il modo in cui sono arrivato a questa domanda, quindi penso che sia ancora pertinente e utile).

Poiché non esiste un'API del kernel, debugfsnon deve essere eseguito su un file system live poiché modifica direttamente la struttura di FS. Pertanto per farlo dal vivo, devi ottenere un altro nome file. Supponendo che il file sia ancora aperto da qualche processo (qualsiasi processo), si può raggiungere i descrittori di file sempre convenienti in /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

Suggerimenti:

  • se hai dei dubbi sul giusto fd, puoi eseguire comandi come filesu di esso
  • se è presente un processo di scrittura nel file, assicurati di interrompere tale processo il prima possibile o non otterrai i dati più recenti. Un trucco (non testato) potrebbe essere quello di aprire il file letto solo attraverso il fd con qualche altro processo (provare tail -f < /proc/$pid/fd/$fd > /dev/null, uscire dal processo di scrittura in modo che esca in modo pulito e usare il nuovo fd del processo.

2
Questo dovrebbe essere tail -f < /proc/...nel secondo suggerimento.
Murray Jensen,

Oppure usalo tail -c +0 -f per copiarlo in primo luogo invece di cat, se il processo di scrittura è solo accodato (non cercare indietro e riscrivere). Esci prima dall'altro processo tail, quindi attendi tailche arrivi alla fine del file.
Peter Cordes,
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.