O que mudou é que ele /bin/shse tornou bashou permaneceu, dashrecebendo uma bandeira adicional -pimitando o comportamento do bash.
O Bash exige que o -psinalizador não elimine o privilégio setuid, conforme explicado em sua página de manual :
Se o shell for iniciado com o ID do usuário (grupo) efetivo diferente do ID do usuário (grupo) real e a opção -p não for fornecida, nenhum arquivo de inicialização será lido, as funções do shell não serão herdadas do ambiente, os SHELLOPTS As variáveis BASHOPTS, CDPATH e GLOBIGNORE, se aparecerem no ambiente, são ignoradas e o ID do usuário efetivo é definido como o ID do usuário real . Se a opção -p for fornecida na chamada, o comportamento de inicialização será o mesmo, mas o ID do usuário efetivo não será redefinido.
Antes, dashnão se importava com isso e permitia a execução de setuid (sem fazer nada para evitá-lo). Mas a página dashde manual do Ubuntu 16.04 tem uma opção adicional descrita, semelhante a bash:
-p priv
Não tente redefinir o uid efetivo se ele não corresponder ao uid. Isso não está definido por padrão para ajudar a evitar o uso incorreto de programas raiz setuid via system (3) ou popen (3).
Esta opção não existia no upstream (que pode não ter sido reativo a um patch proposto * ) nem no Debian 9, mas está presente no Debian buster que obteve o patch desde 2018.
OBSERVAÇÃO: conforme explicado por Stéphane Chazelas, é tarde demais para invocar "/bin/sh -p", system()porque system()executa qualquer coisa fornecida /bin/she, portanto, o setuid já foi descartado. A resposta de derobert explica como lidar com isso, no código anterior system().
* mais detalhes sobre a história aqui e ali .
system("bash -p")é executadosh -c "bash -p"para que os privilégios já tenham sido eliminados quandobashé executado.