Um arquivo pode ser recuperado por seu inode?

27

Eu executei 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í neste teste que o comando rmrealmente remove apenas o nome do arquivo ( aneste teste) em vez do arquivo, pois o inode ainda existe e pode ser recuperado por outro nome de arquivo ( b).

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

user43312
fonte
Parece SO específico para mim.
Ignacio Vazquez-Abrams
@Ignacio Vazquez-Abrams. Você quer dizer que depende da versão?
user43312
Não, quero dizer, depende do sistema operacional. Cada um tem maneiras diferentes (se houver ) de acessar o VFS.
Ignacio Vazquez-Abrams
@Ignacio Vazquez-Abrams Você tem alguma idéia sobre RHL ou RHEL?
user43312
11
@BruceEdiger Os X meio que faz isso. Você pode acessar um objeto de sistema de arquivos usando uma "URL de referência de arquivo", que é fundamentalmente criada a partir do número do sistema de arquivos e do número do nó. No entanto, não é oficialmente suportado para criar você mesmo. Em vez disso, você obtém uma "URL de referência de arquivo" para um arquivo e, em seguida, o usa em vez do nome do caminho para acessos subseqüentes na mesma sessão de tempo de execução, para que seu aplicativo fique alheio ao movimento do arquivo para outro local no mesmo volume.
Arquivo analógico

Respostas:

29

Se você tentar abrir um arquivo via seu inode, isso ignora qualquer passagem de diretório. O percurso do diretório é necessário para determinar as permissões do arquivo e dos diretórios que o conduzem. 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 do 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 teria sido extremamente difícil .

No Linux (e provavelmente em outras variantes do 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, não será possível adicioná-lo novamente.¹ Você pode abrir um arquivo excluído. arquivo, 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 girando os bytes diretamente no sistema de arquivos de uma maneira dependente do sistema de arquivos, por exemplo, com debugfsext2 / ext3 / ext4. Isso requer acesso ao dispositivo no qual o sistema de arquivos está montado (ou seja, normalmente apenas o root pode tentar). No entanto, embora os debugfs possam 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 a execução de debugfs no modo de leitura e gravação em um sistema de arquivos montado é uma receita para desastre.

Gilles 'SO- parar de ser mau'
fonte
11

No Linux, debugfso depurador interativo do sistema de arquivos ext2 / ext3 / ext4 fornece um lncomando que pode receber um número de inode filespece criar um novo link físico para o arquivo correspondente. Na prática, porém, isso requer que o arquivo desvinculado seja mantido aberto por um processo , mantendo um descritor de arquivo aberto em /proc/[pid]/fd/[n]. Tentar fazer isso em um arquivo excluído provavelmente levará à corrupção do sistema de arquivos.

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

Antes da versão 2.6.39 do kernel, costumava ser que a opção introduzida no GNU coreutils v8.0 pudesse ser usada para recuperar um arquivo desvinculado através de um descritor de arquivo aberto, se o arquivo desvinculado e o novo hardlink residissem em um sistema de arquivos tmpfs . Esse recurso foi desativado devido a, como Gilles apontou, as considerações de segurança envolvidas na permissão da criação de links físicos diretamente de um descritor de arquivo.ln -L|--logical/proc/[pid]/fd/[n]

Thomas Nyman
fonte
Eu apenas tentei usar ln -Lpara recuperar um arquivo excluído de / proc e obtive o erro: "Esse arquivo ou diretório não existe", então não acho que ele realmente suporte isso. Eu tenho coreutils 8.21.
Wingedsubmariner
11
ln -Lnão faz o que você diz que faz. Ele diz lnque, se a fonte for um link simbólico, deve vincular o destino com força. Os links simbólicos /proc/$pid/fdsão especiais e a vinculação direta de um (deleted)link não funciona.
Gilles 'SO- stop be evil' em
Também debugfsnão ajudará se o arquivo tiver sido excluído - a menos que você queira correr o risco de executá-lo no modo de leitura e gravação em um sistema de arquivos montado, o que provavelmente destruirá completamente todo o sistema de arquivos.
Gilles 'SO- stop be evil' em
Atualizado a resposta em relação a ln -L. Antes, era possível criar links físicos /proc/[pid]/fd/[n]usando-o em determinadas circunstâncias especiais, mas isso já foi corrigido.
Thomas Nyman
11
debugfsO lnnível é realmente baixo e apenas cria um nome, não atualiza a contagem nem desmarca os blocos como não utilizados, por isso é altamente perigoso . Prefere debugfs's undelque des tudo isso. Aviso: debugfsé para não ser executado em um sistema de arquivos montado a menos que queira ter uma chance na queima de seus FS a cinzas.
Lloeki 7/08
9

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

Por si só, um arquivo UNIX não tem nome, apenas um número de 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 próprio, um arquivo; portanto, você também deve acessá- lo através de (outro) diretório e assim por diante, através de uma série de nomes de diretório delimitados por barras (/) conhecidas como "nome do caminho". Um caminho inicia no "diretório de trabalho atual" do processo, a menos que o nome comece com um "/"; nesse caso, ele começa 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 que não seja de diretório pode ter qualquer número de nomes de caminhos, conhecidos como "links físicos", e continuará existindo até que todos os nomes de caminhos sejam removidos e o último processo feche o arquivo. Na verdade, o arquivo é excluído e seu espaço marcado como disponível para reutilização. Ou seja, é possível criar () ou abrir () um arquivo vinculado individualmente e desvincular () para que ele não apareça mais no espaço de nome do sistema de arquivos, mas o arquivo continuará existindo até você fechá-lo. 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; eles podem aparecer em apenas um outro diretório. (Uma exceção incomum é o sistema de arquivos Mac OSX HFS +; isso permite que os backups do Time Machine funcionem.) Ainda é possível criar "links flexíveis" para diretórios (ou qualquer outro arquivo). Um link simples se assemelha a uma entrada de diretório, exceto que ele contém 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, que eles permitam abrir o arquivo; você também deve ter pelo menos permissão de execução para cada diretório no nome do caminho usado para se referir a ele. É por isso que não existe uma maneira padrão de abrir um arquivo UNIX por seu número de inode; isso contornaria um importante mecanismo de segurança amplamente usado.

Mas isso não explica por que não pode haver uma maneira padrão de um usuário root (privilegiado) abrir um arquivo por número de inode, pois a verificação de permissões é ignorada de qualquer maneira. Isso seria muito útil para determinadas funções de gerenciamento do sistema, como backups. Que eu saiba, esses 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.

Phil Karn
fonte
11
O avanço /é silencioso, portanto é pronunciado "barra".
CTRL-ALT-DELOR
4

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, suponho que a intenção é salvar o dia e restaurar o conteúdo do arquivo, possivelmente com urgência (que foi como eu cheguei nessa questão, por isso acho que ainda é relevante e útil).

Como não há API do kernel, debugfsnão deve ser executado em um sistema de arquivos ao vivo, pois manipula a estrutura do FS diretamente. Portanto, para torná-lo ativo, você precisa se apossar de outro nome de arquivo. Supondo que o arquivo ainda esteja aberto por algum processo (qualquer processo), pode-se procurar 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 você tiver alguma dúvida sobre o comando certo, pode executar comandos como filenele
  • se houver um processo gravado no arquivo, interrompa o processo o mais rápido possível ou você não obterá os dados mais recentes. Um truque (não testado) pode ser abrir o arquivo lido apenas 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 corretamente e use o fd do novo processo.
Lloeki
fonte
2
Isso deve estar tail -f < /proc/...na segunda dica.
Murray Jensen
Ou use-o tail -c +0 -f para copiá-lo em primeiro lugar, em vez de cat, se o processo de gravação for apenas anexado (sem procurar novamente e reescrever). Saia do outro processo antes taile aguarde tailaté o final do arquivo.
Peter Cordes