Por que a fonte de Bash não precisa do bit de execução?

55

Com o source do Bash, é possível executar um script sem um conjunto de bits de execução. Isso é um comportamento documentado e esperado, mas isso não é contra o uso de um bit de execução?

Eu sei que source não cria um subnível.

    
por Motte001 22.06.2016 / 17:30

8 respostas

33

Bash é um intérprete; aceita entrada e faz o que quiser. Não precisa prestar atenção ao bit executável. Na verdade, o Bash é portátil e pode ser executado em sistemas operacionais e sistemas de arquivos que não possuem nenhum conceito de bit executável.

O que importa sobre o bit executável é o kernel do sistema operacional. Quando o kernel Linux executa exec , por exemplo, verifica se o sistema de arquivos não está montado com a opção noexec , verifica o bit executável do arquivo de programa e aplica quaisquer requisitos impostos pelos módulos de segurança (como o SELinux ou AppArmor).

Observe que o bit executável é um tipo de controle bastante discricionário. Em um sistema Linux x86-64, por exemplo, você pode ignorar a verificação do kernel do bit executável explicitamente chamando /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 como o intérprete :

cp /bin/ls /tmp/
chmod -x /tmp/ls
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /tmp/ls

Isso é um pouco análogo à origem do código-fonte Bash no Bash, exceto que ld.so é o interpretador e o código que ele executa é código de máquina no formato ELF.

    
por 23.06.2016 / 07:46
56

source ou o ponto . equivalente, mas não executado o script, mas leia os comandos do arquivo de script e execute-os, linha por linha, no ambiente shell atual.

Não há nada contra o uso do bit de execução, porque o shell só precisa da permissão read para ler o conteúdo do arquivo.

O bit de execução só é necessário quando você executa o script. Aqui, o shell processará fork() new e, em seguida, usará a função execve() para criar uma nova imagem do processo do script, que é necessário para ser um arquivo executável regular.

    
por 22.06.2016 / 17:45
20

O bit executável (diferente do resto) em arquivos não-escuros e não-detectáveis não é um mecanismo de segurança. Qualquer coisa que você possa ler, você pode rodar indiretamente, e o Linux permitirá que você leia indiretamente qualquer coisa que você possa executar, mas não leia diretamente (o que deve ser suficiente para abrir um buraco no conceito de x-bit não definido). medida de segurança).

É mais uma coisa de conveniência: deixar o sistema executá-lo para mim diretamente se o bit estiver definido, caso contrário, preciso fazê-lo indiretamente ( bash the_script; ou algum hacking para obter a imagem da memória de um executável sem permissão de leitura ).

Você pode configurá-lo por conveniência, se você pretende tanto na fonte e executar o seu insourcable.

Aparentemente, no entanto, muitos implementadores de bibliotecas compartilhadas compartilham seu pensamento e, conseqüentemente, muitos sistemas exigem que bibliotecas compartilhadas, que são essencialmente o equivalente nativo de insourcables de shell, sejam marcadas como executáveis para serem utilizáveis. Consulte Por que as bibliotecas compartilhadas são executáveis? .

    
por 22.06.2016 / 18:01
9

Essa é uma boa pergunta! O Unix usa o bit executável para distinguir entre programas e dados. O sistema operacional não requer o bit de execução, pois um script de origem não é passado para o sistema operacional para execução como um novo processo. Mas o shell trata um script de origem como um programa e procurará em $PATH o arquivo que você deseja procurar. Assim, o próprio shell poderia ter exigido permissão de execução para arquivos originados; mas isso não aconteceu.

A pergunta deve ter surgido há muito tempo. O design do shell Bourne foi o resultado de "uma longa seqüência de modificação, diálogo, discussão " entre os habitantes do Bell Labs, e muitas decisões de design foram discutidas por SR Bourne e outros ao longo dos anos. Infelizmente, minha rápida olhada não encontrou nenhuma discussão sobre o recurso de origem (em minha defesa, é difícil procurar no Google por isso). O que eu encontrei é que o "." comando não aparece em esta introdução inicial ao shell pelo próprio Bourne, mas está presente na versão mais madura Versão 7 .

Autoridade ausente, aqui está minha própria interpretação:

  1. O comando . , também conhecido como source , está em vigor na inclusão textual (como #include no pré-processador C) no código-fonte do script em execução ou da sessão interativa. Como tal, o arquivo incluído é indiscutivelmente não "executado".

  2. A filosofia do Unix sempre foi dar corda suficiente aos programadores para se enforcarem. Muitas restrições arbitrárias e arbitrárias apenas atrapalham. É apenas recentemente que algumas distribuições fizeram rm -r / recusar-se a fazer o que você pede. (Este comando diz rm para excluir tudo no seu computador. Não tente fazê-lo como root! Ou melhor ainda, não de todo.) Então, talvez Bourne, al. apenas decidiu que, quando você tenta obter um arquivo, presume-se que sabe o que está fazendo. Isso também evita trabalho desnecessário, e os ciclos eram muito importantes naquela época.

por 22.06.2016 / 19:17
4

No que diz respeito ao SO, um arquivo contendo shell script é apenas um dado. Se você passar o nome de tal arquivo de dados para o comando source ou passá-lo na linha de comando para uma invocação do shell bash, tudo o que o SO vê é uma cadeia que coincide com o nome de um arquivo contendo dados .

Como o bit de execução seria relevante nesse caso?

    
por 23.06.2016 / 04:23
3

A distinção é importante porque você pode ter um arquivo de comandos shell que não é útil como um executável, mas apenas útil quando originado. Para este arquivo, você pode desativar o bit de execução e, em seguida, ele nunca será acessado, a menos que explicitamente em um comando de origem. A razão para tal coisa é ter efeitos colaterais no shell que é executado. Para um exemplo específico, tenho um script chamado fix_path que analisa e modifica o caminho.

    
por 22.06.2016 / 20:04
1

Caso alguém esteja interessado em mais estudos e / ou esclarecimentos: Em um shell quase compatível com POSIX implementado há algum tempo atrás, o funcionamento interno das funções 'exec_program ()' e 'builtin_source ()' são muito exemplares. Nessas funções, você vê exatamente qual é a diferença entre elas:

link

link

basicamente sourcing pode ser visto como o shell temporariamente redirecionando seu descritor de arquivo interno onde analisa o shell script (o terminal no modo interativo). Por isso, é muito semelhante a outros redirecionamentos, como <input_file.txt e >>append_to_something.list , e eles precisam abrir e fechar arquivos.

, portanto, a execução é tratada pela chamada de sistema execve() para a qual o bit de execução é obrigatório.

Eu me lembro de ter visto alguns sistemas que permitem a execução de binários ELF / a.out, mas através da execução de "/lib/ld-dynamic-linker.so" e com o programa binário (sem exec bit) como primeiro argumento. Eu acredito que foi em algumas máquinas DEC Alpha ou VAX (poderia ter sido SCO Unix?)

    
por 25.06.2016 / 16:04
-2

Outro ponto de vista:

O script de origem consiste basicamente em builtins de shell e chamadas de programa. Os builtins de shell (com source entre eles) são partes do shell e o shell deve ser executável em primeiro lugar. Todo programa chamado (sendo ELF, outro script com shebang, qualquer que seja) tem que ter o bit de execução definido, caso contrário ele não será executado.

Portanto, não é contra o uso de um bit de execução, porque nada sem bit de execução será executado. A validação não ocorre para o script de origem como um todo; é executado para cada parte separadamente, mas é.

    
por 22.06.2016 / 19:38