O que está acontecendo aqui é que o processo de "compartilhamento não compartilhado" não tem acesso para gravar nos arquivos setgroups
(e uid_maps
, gid_maps
) no namespace de usuário external .
Nesse namespace, os pseudo-arquivos em /proc/<PID>
serão de propriedade da raiz e, como se o seu uid efetivo ainda fosse seu próprio usuário, você não terá acesso para gravar nesses arquivos.
Você pode visualizar isso facilmente executando um processo em segundo plano (como sleep
) e inspecionando as permissões do arquivo setgroups
enquanto ele está em execução ( uid_maps
e gid_maps
se comportam exatamente da mesma forma.)
Primeiro, com um binário que não tenha recursos adicionais:
$ cp /usr/bin/sleep .
$ ./sleep 10 &
[1] 11209
$ ls -l /proc/11209/setgroups
-rw-r--r--. 1 myuser myuser 0 Jul 31 12:33 /proc/11209/setgroups
[1]+ Done ./sleep 10
$
Então, vamos adicionar alguns recursos de arquivo a ele e ver a alteração de propriedade:
$ sudo setcap cap_net_bind_service=ep sleep
$ ./sleep 10 &
[1] 11220
$ ls -l /proc/11220/setgroups
-rw-r--r--. 1 root root 0 Jul 31 12:34 /proc/11220/setgroups
[1]+ Done ./sleep 10
$
A propriedade dos arquivos em /proc/<PID>
é controlada pelo sinalizador "dumpable" dentro do kernel Linux, que é usado para evitar vazamento de informações de um processo privilegiado para um usuário sem privilégios.
E considerando que você está executando unshare
com recursos adicionais, mas ainda com um eficaz uid não-root, o acesso de gravação a esses pseudo-arquivos que são de propriedade do root é impedido através do acesso normal controles do sistema operacional.
Você pode inspecionar o valor do sinalizador "dumpable" usando o comando PR_GET_DUMPABLE
do prctl (2) syscall.
Na descrição de PR_SET_DUMPABLE
, você também encontrará:
Normally, this flag is set to 1. However, it is reset to the current value contained in the file
/proc/sys/fs/suid_dumpable
(which by default has the value 0), in the following circumstances:[...]
- The process executes (
execve(2)
) a program that has file capabilities (seecapabilities(7)
), but only if the permitted capabilities gained exceed those already permitted for the process.
Qual é exatamente o seu caso, com um binário unshare
que possui recursos de arquivo.
Curiosamente, usar um binário setuid de propriedade root para unshare
não é executado exatamente nesse problema. Sim, limpará os sinalizadores "dumpable" e os arquivos em /proc/<PID>
serão de propriedade de root. Mas considerando seu uid efetivo é também root ao executar um binário setuid, o acesso será permitido.
Nesse caso, você acaba encontrando um problema diferente, que tem a ver com a lógica de unshare
não ser capaz de lidar com essa configuração específica (provavelmente algo a ver com o uid efetivo e o uid real não correspondendo ):
$ cp /usr/bin/unshare .
$ sudo setcap -r unshare
$ sudo chown root:root unshare
$ sudo chmod 4711 unshare
$ ./unshare -r
-bash: cannot set uid to 65534: effective uid 0: Invalid argument
-bash-4.4$
Observe também que a limpeza do sinalizador "dumpable" foi acionada pela execução de um binário com recursos de arquivo definidos. Se você obtiver recursos adicionais de uma maneira diferente, talvez não se depare com esse problema. Por exemplo, usar recursos de "ambiente" é uma boa maneira de obter recursos adicionais fora do espaço de nomes, embora ainda não tenha problemas ao não compartilhar um novo namespace de usuário.
(infelizmente, ainda não há muitas ferramentas em torno dos recursos do ambiente. libcap
envia somente o suporte no git mais recente, a versão passada 2.25, que é atualmente enviada na maioria das distros. capsh
é de nível razoavelmente baixo , por isso não é tão fácil fazer isso certo. Veja aqui para detalhes sobre como usar o mais recente capsh
para adicionar Também tentei systemd-run
, mas realmente não consegui ter recursos de ambiente configurados. De qualquer forma, algo para você pesquisar, se você precisar de recursos, namespaces de usuário e de usuário não-root juntos!)