Existem pelo menos 3 maneiras pelas quais pode ser perigoso:
-
Se
/etc/sudoersnão terminar em um caractere de nova linha (quesudoevisudoallow), por exemplo, se ele terminar em uma linha#includedir /etc/sudoers.dnão finalizada, seu comando fará:#includedir /etc/sudoers.dDefaults insultsque irá quebrá-lo e tornar
sudoinutilizável. -
echopode falhar ao gravar a string completa, por exemplo, se o sistema de arquivos estiver cheio. Por exemplo, pode ser capaz de escreverDefaults in. Que novamente irá quebrar o seu arquivosudoers. - Em uma máquina com vários administradores, se ambos tentarem modificar
/etc/sudoersao mesmo tempo, os dados que eles escreverem poderão ficar entrelaçados.
visudo evita esses problemas porque permite que você edite um arquivo temporário ( /etc/sudoers.tmp ), detecta se o arquivo foi modificado (infelizmente não se o arquivo foi com sucesso modificado como não funciona) t parece estar verificando o status de saída do editor), verifica a sintaxe e executa uma rename (uma operação atômica) para mover o novo arquivo no lugar. Portanto, ele atualizará com êxito o arquivo (desde que seu editor também deixe o arquivo não modificado se falhar em gravar o novo) ou falhe se não puder ou a sintaxe for inválida.
visudo também protege contra várias pessoas que editam os arquivos sudoers ao mesmo tempo.
Agora, confiantemente usando visudo de maneira automática também é complicado. Existem vários problemas com isso:
- Você pode especificar um comando do editor para
visudocom a variável de ambienteVISUAL(tem precedência sobreEDITOR), mas somente se a opçãoenv_editornão tiver sido desativada. - minha versão de
visudo, pelo menos, sob algumas condições, edita todos os/etc/sudoerse todos os arquivos incluídos (executa$VISUALpara todos eles). Portanto, você precisa garantir que seu$VISUALapenas modifique/etc/sudoers. - como visto acima, não verifica o status de saída do editor. Portanto, você precisa ter certeza de que o arquivo que seu editor salva seja gravado com sucesso ou não tenha sido modificado.
- Ele avisa o usuário em caso de problema.
Enfrentar tudo isso é um pouco complicado. Veja como você pode fazer isso:
NEW_TEXT='Defaults insults' \
CODE='
if [ "$2" = /etc/sudoers.tmp ]; then
printf >&2 "Editing %s\n" "$2"
umask 077
{
cat /etc/sudoers.tmp && printf "\n%s\n" "$NEW_TEXT"
} > /etc/sudoers.tmp.tmp &&
mv -f /etc/sudoers.tmp.tmp /etc/sudoers.tmp
else
printf >&2 "Skipping %s\n" "$2"
fi' \
VISUAL='sh -fc IFS=:;$1 sh eval:eval:"$CODE"' visudo < /dev/null
Não funcionará se env_editor não estiver definido.
Em um sistema GNU, uma alternativa melhor seria usar sed -i , o que deve deixar sudoers.tmp não modificada se falhar em gravar a versão mais recente:
Adicione insults :
SED_CODE='
/^[[:blank:]]*Defaults.*insults/,${
/^[[:blank:]]*Default/s/!*\(insults\)//g
$q
}
$a\Defaults insults' \
CODE='
if [ "$2" = /etc/sudoers.tmp ]; then
printf >&2 "Editing %s\n" "$2"
sed -i -- "$SED_CODE" "$2"
else
printf >&2 "Skipping %s\n" "$2"
fi' \
VISUAL='sh -fc IFS=:;$1 sh eval:eval:"$CODE"' visudo < /dev/null
Remova insultos:
SED_CODE='
/^[[:blank:]]*Defaults.*insults/,${
/^[[:blank:]]*Defaults/s/!*\(insults\)/!/g
$q
}
$a\Defaults !insults' \
CODE='
if [ "$2" = /etc/sudoers.tmp ]; then
printf >&2 "Editing %s\n" "$2"
sed -i -- "$SED_CODE" "$2"
else
printf >&2 "Skipping %s\n" "$2"
fi' \
VISUAL='sh -fc IFS=:;$1 sh eval:eval:"$CODE"' visudo < /dev/null