Um arquivo pode ser recuperado por seu inode?

26

Eu corri os seguintes comandos na ordem especificada:

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

Concluí desse teste que o comando rm realmente remove apenas o nome do arquivo ( a neste teste) em vez do arquivo, pois o inode ainda existe e pode ser recuperado por meio de outro nome de arquivo ( b ).

A minha pergunta é, se um ficheiro está ligado a apenas um nome de ficheiro, quando rm é executado para o ficheiro, o ficheiro real (ou seja, o inode) é removido completamente? E se não, um arquivo inode pode ser recuperado sem um nome de arquivo e somente através do inode?

    
por user43312 29.09.2013 / 09:07

4 respostas

26

Se você tentar abrir um arquivo através de seu inode, isso ignorará qualquer travessia de diretório. O diretório transversal é necessário para determinar as permissões do arquivo e dos diretórios que levam a ele. Sem uma passagem de diretório, o kernel não tem como determinar se o processo de chamada tem permissão para acessar o arquivo.

Houve um patch proposto para o kernel Linux para permitir a criação de um link para um arquivo a partir de um descritor de arquivo . Foi rejeitado porque implementar isso com segurança seria extremamente difícil .

No Linux (e provavelmente em outras variantes unix pelo mesmo motivo), você não pode criar um link para um arquivo excluído, portanto, se um arquivo não tiver mais um nome, você não poderá adicioná-lo novamente.¹ abra um arquivo excluído abrindo os links mágicos em /proc/$pid/fd/ .

Se um arquivo não tiver mais nenhum link e não estiver mais aberto, ele não existirá mais e o espaço usado anteriormente por seus dados poderá ser recuperado a qualquer momento.

¹ Você pode fazer isso alterando os bytes diretamente no sistema de arquivos de uma maneira dependente do sistema de arquivos, por exemplo, com debugfs para ext2 / ext3 / ext4. Isso requer acesso ao dispositivo no qual o sistema de arquivos é montado (ou seja, normalmente apenas o root pode tentar). No entanto, enquanto o debugfs pode acessar um arquivo por inode, isso não ajuda se o arquivo for excluído: o arquivo será realmente excluído se o aplicativo o fechar e executar o debugfs no modo de leitura e gravação em um sistema de arquivos montado é uma receita para desastre.

    
por 30.09.2013 / 03:04
11

No Linux, debugfs , o ext2 / ext3 / interativo O depurador do sistema de arquivos ext4 fornece um comando ln , que pode obter um número de inode como filespec e criar um novo link físico para o arquivo correspondente. Na prática, porém, isso exige que o arquivo desvinculado seja mantido aberto por um processo , mantendo um descritor de arquivo aberto em /proc/[pid]/fd/[n] . A tentativa de fazer isso em um arquivo excluído provavelmente resultará em corrupção do sistema de arquivos.

Isso porque, para garantir que o ext3 (e na extensão ext4) possa reiniciar com segurança um unlink após uma falha, ele realmente zera os ponteiros de bloco no inode , enquanto o ext2 apenas marca esses blocos como não utilizados nos bitmaps de bloco e marca o inode como" excluído "e deixa o inode ponteiros de bloco sozinho. Mesmo assim, como o sistema de arquivos precisa ser montado como leitura-gravação para criar o link físico, os blocos reservados para o arquivo excluído podem já ter sido realocados.

Antes da versão 2.6.39 do kernel, costumava ser que a ln -L|--logical opção introduzida no GNU coreutils v8.0 poderia ser usado para recuperar um arquivo desvinculado através de um descritor de arquivo aberto em /proc/[pid]/fd/[n] se tanto o arquivo desvinculado quanto o novo hardlink residiam em um tmpfs sistema de arquivos. Esta capacidade tem sido desde desativado , devido a, como Gilles apontou, as considerações de segurança envolvidas em permitir a criação de link físico diretamente de um descritor de arquivo.

    
por 29.09.2013 / 09:59
8

Os comandos 'ln' e 'rm' funcionam exatamente assim em todos os sistemas de arquivos UNIX desde o início dos anos 70. O Mac OSX, o BSD e o Linux herdaram este design original.

Por si só, um arquivo UNIX não tem nome, apenas um número inode ou inum. Mas você só pode acessá-lo através de uma entrada em um arquivo "diretório" especial que associa um nome ao inum em questão; você não pode especificar o inum diretamente.

Um diretório é ele mesmo um arquivo, então você também deve acessar ele através de (outro) diretório e assim por diante, através de uma série de nomes de diretório delimitados por barras /) conhecido como "nome do caminho". Um caminho é iniciado no "diretório de trabalho atual" do processo, a menos que o nome comece com "/" e, nesse caso, ele inicia com o diretório raiz do sistema de arquivos. Por exemplo, se o nome do caminho não contiver caracteres "/", espera-se que seja uma entrada no diretório atual.

Um arquivo não-diretório pode ter qualquer número de nomes de caminho, conhecido como "links físicos", e continuará existindo até que todos de seus nomes de caminho tenham sido removidos e o último processo fechou o arquivo. Em seguida, o arquivo é realmente excluído e seu espaço marcado como disponível para reutilização. Isto é, você pode criar () ou abrir () um arquivo unicamente vinculado e, em seguida, unlink () para que ele não apareça mais no espaço de nome do sistema de arquivos, mas o arquivo continuará a existir até que você o feche. Isso é útil para arquivos temporários temporários que não serão lidos por nenhum outro programa.

Embora os diretórios tenham números de inode, a maioria dos sistemas de arquivos não permite links físicos para eles; eles podem aparecer em apenas um outro diretório. (Uma exceção incomum é o sistema de arquivos HFS + do Mac OSX; isso permite que os backups do Time Machine funcionem.) Você ainda pode criar "soft links" para diretórios (ou qualquer outro arquivo). Um link suave se assemelha a uma entrada de diretório, exceto pelo fato de conter outro nome de caminho, em vez de um inum.

Todo arquivo UNIX possui permissões de proprietário, grupo e acesso. É necessário, mas não suficiente, permitir que você abra o arquivo; você também deve ter pelo menos permissão de execução para cada diretório no caminho que você usa para se referir a ele. É por isso que não há uma maneira padrão de abrir um arquivo UNIX pelo seu número de inode; que contornaria um mecanismo de segurança importante e amplamente utilizado.

Mas isso não explica porque não pode haver uma maneira padrão para um usuário root (privilegiado) abrir um arquivo por número de inode, já que a verificação de permissões é ignorada de qualquer maneira. Isso seria muito útil para determinadas funções de gerenciamento do sistema, como backups. Pelo que sei, tais mecanismos existem, mas são todos específicos do sistema de arquivos; não existe uma maneira geral de fazer isso para qualquer sistema de arquivos UNIX.

    
por 30.09.2015 / 05:35
2

A questão pode ser tomada teoricamente (o que pode ser alcançado com debugfs ) ou pragmaticamente (situação de emergência). No último caso, presumo que a intenção é salvar o dia e restaurar o conteúdo do arquivo, possivelmente com urgência (que é como eu cheguei a essa pergunta, então acho que ainda é relevante e útil).

Como não há API do kernel, debugfs não deve ser executado em um sistema de arquivos ativo, pois manipula diretamente a estrutura do FS. Portanto, para fazer isso ao vivo, você tem que se apossar de outro nome de arquivo. Supondo que o arquivo ainda esteja aberto por algum processo (qualquer processo), pode-se obter os descritores de arquivo sempre convenientes em /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

Dicas:

  • se tiver alguma dúvida sobre o direito fd, pode executar comandos como file
  • se houver um processo gravando no arquivo, interrompa o processo o mais rápido possível ou você não receberá os dados mais recentes. Um truque (não testado) pode ser abrir o arquivo somente leitura através do fd com algum outro processo (tente tail -f > /proc/$pid/fd/$fd > /dev/null , saia do processo de gravação para que ele saia de forma limpa e use o fd do novo processo.
por 07.08.2017 / 09:53