APUE diz
Cada processo também possui um diretório raiz que é usado para resolução de nomes de caminhos absolutos. Este diretório raiz pode ser alterado com a função chroot.
Eu pensei que apenas nomes de caminhos relativos precisavam de resolução. Então eu estava me perguntando
o que significa resolução de nomes de caminhos absolutos?
como
chroot
usar um diretório raiz para resolução de nomes de caminho absolutos? Obrigado.
Quando o kernel resolve, por exemplo
/usr/share/man/man1/cat.1.gz
, para um inode, ele terá que começar da raiz/
e descer atécat.1.gz
. No caso de um nome de caminho relativo, basta procurar o arquivo no diretório atual.Talvez você estivesse pensando em como obter o caminho absoluto para o diretório de trabalho atual? Para determinar o caminho, você terá que trabalhar desde o diretório atual, passando por todos os diretórios intermediários até a raiz. (Mas observe que o kernel não faz isso quando recebe um caminho relativo para um arquivo, por exemplo, como um parâmetro para o
open
syscall.)Todos os nomes de caminho precisam de resolução. Obviamente, os processos passam nomes de caminho para o kernel como argumentos para chamadas de sistema como:
creat
ouopen
,link
ourename
,unlink
ourmdir
,chmod
ouchown
,chdir
ouchroot
,execve
,etc. Considere um nome de caminho que se pareça com
A maneira como o kernel interpreta isso é:
Observe a ofuscação no início do nome do caminho e na primeira linha do algoritmo. É simples: se o caminho começa com uma barra (ou seja, é um “caminho absoluto”, por exemplo,
/a/b/c
), a busca começa no diretório raiz do processo, e se o caminho começa com qualquer outra coisa (ou seja, é um caminho relativo, por exemplo ,a/b/c
), a pesquisa começa no diretório de trabalho atual do processo.Você pode perguntar "Como isso é alcançado?" Bem, é claro, o kernel mantém muitas informações sobre cada processo, incluindo
e mais. Deixei de fora muitas coisas porque são irrelevantes para esta questão. Deixei de fora as variáveis de ambiente porque elas não são mantidas pelo kernel; eles são mantidos por programas de espaço do usuário. Tudo o que o kernel faz é oferecer suporte a um mecanismo para passar variáveis de ambiente de um programa para outro por meio de arquivos
execve
.Duas coisas que deixei de fora da lista acima para fins dramáticos são:
Estes são ponteiros para inodes. Espero que todos que chegaram até aqui entendam como o diretório de trabalho atual do processo é definido — o processo chama
chdir
, passando um nome de caminho como argumento; o kernel interpreta o nome do caminho (o resolve para um inode) seguindo o procedimento descrito acima e, após o sucesso, define o ponteiro do diretório atual para apontar para esse inode.O diretório raiz do processo é definido da mesma forma, exceto com a
chroot
chamada do sistema.(Observe que, em ambos os casos, se o argumento do nome do caminho começar com
/
, a resolução do nome do caminho começará no diretório raiz do processo em vigor quando a chamada do sistema for invocada . )Alguns exemplos:
/home/tim
(e o diretório raiz do processo for a raiz do sistema de arquivos), então/etc/services
, você receberá/etc/services
,.bashrc
, você receberá/home/tim/.bashrc
.chroot /filesystem/tim
(supondo que exista um diretório com esse nome e você tenha acesso a ele e tenha o privilégio necessário parachroot
), então/etc/services
, você receberá/filesystem/tim/etc/services
,/
, você vai conseguir/filesystem/tim
, entãochroot /
, nada mudará;chroot /filesystem/john
, ele tentará .chroot
/filesystem/tim/filesystem/john
Como o diretório raiz e o diretório atual são armazenados como ponteiros para inodes, o sistema não precisa “localizá-los”.
2 para o último segmento do nome do caminho, não importa que tipo de arquivo seja; pode ser um diretório, um arquivo simples, um pipe nomeado, um link simbólico, um dispositivo, … qualquer coisa. 3 se o último segmento do nome do caminho não for encontrado, mas a chamada do sistema for ou (equivalente) , ou qualquer outra coisa que não possa criar uma entrada de diretório, a operação não falhará.__________
1 ou seja, procure uma entrada de diretório que aponte para um inode cujo modo indica que é um diretório, ou seja,
(i_mode & IFMT) == IFDIR
.creat(file, mode)
open(file, O_CREAT, mode)