AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 463076
Accepted
sourcejedi
sourcejedi
Asked: 2018-08-17 13:29:15 +0800 CST2018-08-17 13:29:15 +0800 CST 2018-08-17 13:29:15 +0800 CST

Por que usuários sem privilégios não podem aninhar montagens FUSE, mas podem montar FUSE dentro de NFS com root_squash?

  • 772
$ mkdir mnt

$ bindfs /tmp mnt
fusermount: option allow_other only allowed if 'user_allow_other' is set in /etc/fuse.conf

$ bindfs --no-allow-other /tmp mnt

$ mkdir /tmp/mnt2
$ bindfs --no-allow-other /tmp mnt/mnt2
fusermount: bad mount point /home/alan/mnt/mnt2: Permission denied

fusermountfalha porque é executado como um usuário diferente.

$ sudo ls mnt/
ls: cannot open directory 'mnt/': Permission denied

fusermounté set-uid root. Isso é necessário porque usuários sem privilégios não podem usar a mount()chamada do sistema.

$ ls -l $(which fusermount)
-rwsr-xr-x. 1 root root 32848 Feb  7  2018 /usr/bin/fusermount

   ^ set-uid bit

E ainda. É relatado que o FUSE pode ser usado dentro de um diretório inicial do NFS. Mesmo que o diretório inicial tenha o modo 700- acessível apenas pelo usuário proprietário. E o padrão do servidor NFS é root_squash, o que significa que "o usuário root terá o mesmo acesso que o usuário none".

Por que esses dois casos diferem?

Estou testando no Fedora 28. Os relatórios sobre NFS são do Ubuntu 18.04. Essas distribuições são bastante semelhantes em idade, mas pode haver algumas diferenças.

nfs fuse
  • 1 1 respostas
  • 1995 Views

1 respostas

  • Voted
  1. Best Answer
    sourcejedi
    2018-08-17T13:29:15+08:002018-08-17T13:29:15+08:00

    Primeiro, considere a implementação de FUSE no_allow_others.

    Requer que todos os UIDs (IDs de usuário) efetivos, reais e salvos correspondam. (E o mesmo para GID). Isso é deliberadamente para impedir que um programa set-UID acesse a montagem.

    https://github.com/torvalds/linux/blob/v4.18/fs/fuse/dir.c#L1024

    Chamar um sistema de arquivos controlado pelo usuário fornece ao
    daemon do sistema de arquivos recursos semelhantes ao ptrace sobre o processo atual. Isso
    significa que o daemon do sistema de arquivos é capaz de registrar as
    operações exatas do sistema de arquivos executadas e também pode controlar o comportamento
    do processo solicitante de maneiras impossíveis. Por exemplo
    , pode atrasar a operação por um período de tempo arbitrário, permitindo
    DoS contra o solicitante.

    Agora vamos rastrear o que fusermountfaz. Podemos tentar olhar

    strace -f bindfs ...
    

    e

    sudo perf trace -o trace.txt -a sleep 2; sleep 1; bindfs ...
    

    O primeiro atinge um erro fatal "Permissão negada", porque o root set-UID não funciona ao executar em strace. O segundo é bem-sucedido, mas não pode mostrar parâmetros de string, como caminhos. Acho que os dois rastreamentos mostram o mesmo caminho de código geral até o erro fatal. Isso significa que podemos usar os straceresultados para preencher os parâmetros de string ausentes.

    Essa última chamada nos straceresultados é:

    [pid 30609] mount("/home/alan-sysop/mnt", ".", "fuse", MS_NOSUID|MS_NODEV, "default_permissions,fd=5,rootmod"...) = -1 EPERM (Operation not permitted)
    

    Interessante! "."significa o diretório atual. Então fusermountjá deve ter rodado no ponto de montagem... de alguma forma. Esse truque às vezes pode ser usado para acessar um diretório que você não pode acessar atualmente usando seu caminho absoluto.

    Se rolarmos para cima, podemos ver que fusermountrealmente mudou para este diretório. E também estava dançando com algumas chamadas de sistema relacionadas a UID (e relacionadas a GID).

    [pid 30609] getuid()                    = 1000
    [pid 30609] setfsuid(1000)              = 1000
    [pid 30609] getgid()                    = 1000
    [pid 30609] setfsgid(1000)              = 1000
    [pid 30609] openat(AT_FDCWD, "/etc/fuse.conf", O_RDONLY) = 6
    ...
    [pid 30609] lstat("/home/alan-sysop/mnt", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
    [pid 30609] getuid()                    = 1000
    [pid 30609] chdir("/home/alan-sysop/mnt") = 0
    [pid 30609] lstat(".", {st_mode=S_IFDIR|0775, st_size=4096, ...}) = 0
    [pid 30609] access(".", W_OK)           = 0
    [pid 30609] getuid()                    = 1000
    [pid 30609] setfsuid(1000)              = 1000
    [pid 30609] setfsgid(1000)              = 1000
    

    Os resultados do UID estão "errados" na stracesessão. Podemos ver melhor a parte da dança do UID na perf tracesessão. (Removi as colunas mais à esquerda para facilitar a leitura).

    getuid(                                                               ) = 1000
    setfsuid(uid: 1000                                                    ) = 0
    getgid(                                                               ) = 1000
    setfsgid(gid: 1000                                                    ) = 1000
    openat(dfd: CWD, filename: 0xa428e2bc                                 ) = 6
        ...
    close(fd: 6                                                           ) = 0
    lstat(filename: 0xa63882a0, statbuf: 0x7ffe7bd4f6d0                   ) = 0
    getuid(                                                               ) = 1000
    chdir(filename: 0xa63882a0                                            ) = 0
    lstat(filename: 0xa428eca5, statbuf: 0x7ffe7bd4f6d0                   ) = 0
    access(filename: 0xa428eca5, mode: W                                  ) = 0
    getuid(                                                               ) = 1000
    setfsuid(                                                             ) = 1000
    setfsgid(gid: 1000                                                    ) = 1000
    getuid(                                                               ) = 1000
    

    As setfsuid()chamadas estão nas funções drop_privs()e em fusermount.c .restore_privs()

    A chdir()chamada está escondida sorrateiramente na função chamada check_perm().

    Conclusão

    Por que isso funciona no NFS? Resposta: porque o NFS examina o fsuid(e fsgid), que foi definido como o UID não raiz.

    Por que isso não funciona no FUSE, a menos que você tenha allow_others? Resposta: porque o FUSE verifica o UID "real", e não o fsuid.

    • 0

relate perguntas

  • Montagem NFS do WD MyCloud no roteador Asus Merlin: solução de problemas de montagem NFS: "dispositivo inexistente"

  • como consultar o sar(sysstat) para obter mais de um dia de pontos de dados

  • Montar raiz como overlayfs

  • inicialização nfs trava após o início do systemd-networkd

  • Não é possível iniciar o servidor NFS no Alpine Linux LXC

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve