Existe um arquivo que sempre existe e um usuário 'normal' não pode demonstrá-lo?

14

Eu preciso disso para um teste de unidade. Há uma função que lstat no caminho do arquivo passado como parâmetro. Eu tenho que acionar o caminho do código em que a lstatfalha (porque a cobertura do código deve atingir 90%)

O teste pode ser executado apenas em um único usuário, portanto, eu queria saber se sempre existe um arquivo no Ubuntu, mas os usuários normais não têm acesso de leitura a ele ou a sua pasta. (Portanto lstat, falharia com ele, a menos que seja executado como root.)

Um arquivo inexistente não é uma solução, porque existe um caminho de código separado para isso, que eu já estou acionando.

EDIT: A falta de acesso de leitura apenas ao arquivo não é suficiente. Com isso lstatainda pode ser executado. Consegui acioná-lo (na minha máquina local, onde tenho acesso root), criando uma pasta em / root e um arquivo nela. E definindo a permissão 700 na pasta. Então, eu estou procurando por um arquivo que está em uma pasta que só é acessível pela raiz.

Gatinho agachado
fonte
6
IMHO/etc/shadow
Romeo Ninov
3
Você não pode assumir a existência de nenhum arquivo, porque seu programa pode ser executado em um chroot ou em um espaço para nome separado. Se supor que / proc está montado está OK e o init não é nada de especial, /proc/1/fd/0deve fazer.
mosvy
1
@mosvy Obrigado que funciona na minha máquina local. Hmm, então eu vou experimentá-lo também no pool de controle de qualidade e preparação.
Crouching Kitten
2
Por que você está vinculando seu código de teste a um tipo específico de sistema operacional quando você pode apenas criar um arquivo descartável e remover seu próprio acesso de leitura?
Kilian Foth
4
Eu diria que não é realmente um teste de unidade , uma vez que começa dependendo de um sistema de arquivos real, em vez de zombado.
Toby Speight

Respostas:

21

Nos sistemas Linux modernos, você deve poder usar /proc/1/fdinfo/0(informações para o descritor de arquivo 1 (stdout) do processo do id 1 ( initno espaço para nome raiz pid que deve estar sendo executado como root)).

Você pode encontrar uma lista com (como usuário normal):

sudo find /etc /dev /sys /proc -type f -print0 |
  perl -l -0ne 'print unless lstat'

(remova -type fse você não deseja restringir a arquivos regulares).

/var/cache/ldconfig/aux-cacheé outro candidato em potencial se você precisar apenas considerar os sistemas Ubuntu. Ele deve funcionar na maioria dos sistemas GNU, pois /var/cache/ldconfigé criado como read + write + searchable para root somente pelo ldconfigcomando que acompanha a GNU libc.

Stéphane Chazelas
fonte
1
Obrigado! Se /proc/1/fdinfo/0funcionar no Ubuntu 16.04 e 18.04, é mais do que suficiente.
Crouching Kitten
1
O uso /proc/1/fdinfo/0não necessariamente funciona em um contêiner (por exemplo, um contêiner do Docker) e, geralmente, são executados testes de unidade nesses contêineres no IC.
Philipp Wendler
@ PhilippWendler, eu já mencionei o espaço para nome root pid . O OP não está perguntando sobre contêineres, mas sobre arquivos que estão garantidos no layout do sistema de arquivos de um sistema Ubuntu. Como os contêineres podem conter qualquer layout de arquivo e diretório, essa pergunta não pode ser respondida lá.
Stéphane Chazelas
12

Olhando a página de manual lstat (2) , você pode obter alguma inspiração sobre casos que podem causar falhas com erros diferentes de ENOENT (o arquivo não existe).

O mais óbvio é:

A permissão de pesquisa do EACCES é negada para um dos diretórios no prefixo do caminho .

Então você precisa de um diretório do qual não possa pesquisar.

Sim, você pode procurar por um que já esteja em seu sistema (talvez /var/lib/privatese ele existir?) Mas é melhor criar um você mesmo, com o equivalente a:

$ mkdir myprivatedir
$ touch myprivatedir/myunreachablefile
$ chmod 0 myprivatedir
$ ls -l myprivatedir/myunreachablefile

A operação lstat (2) falhará com o EACCES aqui. (A remoção de todas as permissões do diretório garante isso. Talvez você nem precise muito disso e a chmod -xremoção de permissões de execução seria suficiente, pois são necessárias permissões de execução em um diretório para acessar arquivos nele.)

Existe outra maneira criativa de fazer com que o lstat (2) falhe, olhando para a página de manual:

ENOTDIR Um componente do prefixo do caminho não é um diretório.

Portanto, tentar acessar um arquivo como /etc/passwd/nonexistentdeve acionar esse erro, que novamente é diferente de ENOENT ("Não existe esse arquivo ou diretório") e pode atender às suas necessidades.

Outro é:

O caminho ENAMETOOLONG é muito longo.

Mas você pode precisar de um nome realmente longo para este (acredito que 4.096 bytes é o limite típico, mas seu sistema / sistema de arquivos pode ter um mais longo.)

Finalmente, é difícil dizer se algum deles será realmente útil para você. Você diz que deseja algo que não aciona o cenário "o arquivo não existe". Embora normalmente isso signifique um erro ENOENT, na prática muitas verificações de nível superior simplesmente interpretam quaisquer erros do lstat (2) como "não existe". Por exemplo, test -eou o equivalente [ -e ...]do shell pode simplesmente interpretar todos os itens acima como "não existe", especialmente porque ele não tem uma boa maneira de retornar uma mensagem de erro diferente e não retornar um erro implicaria a existência do arquivo, o que certamente não é o caso.

filbranden
fonte
@StephaneChazelas Great point! Atualizada.
filbranden
6

Você pode fazer findisso sozinho.

Usando /etc- o diretório dos arquivos de configuração como ponto de partida:

sudo find /etc -type f -perm 0400 -user root

No meu sistema, isso não retorna nada.

Você pode ser um grupo menos restritivo e permitir root(apenas o usuário rootdeve ser um membro do grupo root) e procurar uma permissão para 440:

sudo find /etc -perm 0440 -user root -group root

No meu sistema, isso retorna:

/etc/sudoers.d/README
/etc/sudoers

Editar:

Com base na sua edição, você está procurando um diretório que não tenha permissão suficiente para o usuário que está invocando para impedir a listagem de diretórios:

sudo find / -perm o-rwx -type d -user root -group root 

aqui estou procurando diretórios ( -type d) que não possuem os bits de permissão de leitura-gravação-execução para outros ( o-rwx) e pertencem a root:root.

Tecnicamente, apenas a ausência do xbit execute ( ) impediria uma listagem de diretório ( lstat(2)) no diretório.

Na saída que encontrei /run/systemd/inaccessible/no meu sistema baseado em init do Systemd.

Em relação a arquivos em /proc, /sys, /dev:

  • Esses sistemas de arquivos são FS virtuais, ou seja, residem na memória, não no disco

  • Se você planeja confiar /proc, use, /proc/1/ou seja, conte com algo sob o PID 1, e nenhum PID posterior tenha confiabilidade / consistência, pois não é garantido que os PIDs (processos) posteriores existam.

heemail
fonte
Obrigado, acho que minha pergunta está errada. Ainda posso lstat arquivos sem acesso de leitura a eles. Talvez o acesso à pasta precise ser limitado? (Modifiquei o título)
Crouching Kitten
Obrigado. Com find / -type d -perm 0400 -user rooteu encontrei o diretório /proc/20/map_files/, se eu me referir a um nome de arquivo inventado dentro dessa pasta, como /proc/20/map_files/asdasd, então ele sempre falha. Essa pasta sempre existe no Ubuntu?
Crouching Kitten
@CrouchingKitten, os diretórios /proc/1/podem ser mais seguros, pois o init sempre existe. Mas isso procnão é um sistema de arquivos comum, caso isso importe.
Ilkkachu
Obrigado, eu dei um voto positivo, mas aceitei a outra resposta, porque ele disse que é garantido que /proc/1/fdinfo/0funciona no Ubuntus moderno.
Crouching Kitten
-perm o-rwxé como -perm 0, todos os bits estão desativados para começar. Aqui você gostaria ! -perm -1.
Stéphane Chazelas