Como compilar o compilador C do zero e compilar o Unix / Linux do zero

64

Digamos que eu trabalhe para uma grande organização de serviços fora dos EUA / Reino Unido. Usamos servidores UNIX e Linux extensivamente.

Lendo este artigo, ele menciona que seria fácil inserir uma backdoor em um compilador C; qualquer código compilado com esse compilador também conteria uma backdoor. Agora, devido a vazamentos recentes sobre o mandato da NSA / GCHQ de colocar backdoors / pontos fracos em todos os métodos de criptografia, hardware e software, o compilador é agora um ponto crítico de falha. Potencialmente, todas as distribuições UNIX / Linix padrão podem ser comprometidas. Não podemos permitir que nossos sistemas, dados e dados de nossos clientes sejam comprometidos por governos invasores.

Dadas essas informações, eu gostaria de construir um compilador confiável a partir do zero, então tenho uma base segura para poder construir o sistema operacional e os aplicativos a partir do código-fonte usando esse compilador.

Pergunta, questão

Qual é a maneira correta (e segura) de compilar um compilador a partir do código-fonte (um cenário aparentemente interessante) e depois compilar uma distribuição Unix / Linux confiável do zero?

Você pode assumir que eu ou outros temos a capacidade de ler e entender o código-fonte para falhas de segurança; portanto, o código-fonte será examinado primeiro antes da compilação. O que realmente desejo é um guia de trabalho para produzir esse compilador do zero com segurança e pode ser usado para compilar o kernel, outras partes do sistema operacional e aplicativos.

A pilha de segurança deve iniciar no nível base para que possamos ter confiança no sistema operacional ou nos aplicativos em execução nessa pilha. Sim, eu entendo que pode haver backdoors de hardware que podem inserir algum microcódigo no compilador enquanto ele está sendo construído. No momento, não podemos fazer muito a respeito, exceto talvez usar chips não projetados nos EUA. Vamos classificar essa camada para começar e supor que eu possa construí-la em um computador antigo potencialmente antes que qualquer backdoors seja inserido.

Como Bruce Schneier diz: "Para os engenheiros, digo o seguinte: construímos a Internet e alguns de nós ajudamos a subvertê-la. Agora, aqueles que amam a liberdade precisam corrigi-la".

Links extras:

David J
fonte
7
Porra, essa é uma pergunta muito interessante e eu não quero migrá-la, mas realmente não acho que esteja no tópico aqui. É mais adequado para o stackoverflow.com, já que sua pergunta básica é sobre como compilar um compilador do zero, o que é praticamente independente do SO e uma questão de programação. Se você não receber uma resposta aqui depois de um tempo, considere usar o link "sinalizador" sob as tags da sua pergunta e pedir a um moderador para mudar isso para SO.
terdon
2
@terdon Na verdade, pode ser um ajuste melhor para Programmers.SE, já que se trata mais de questões gerais de programação do que de um problema específico de desenvolvimento. De fato, pode ser uma duplicata lá .
um CVn
2
O GCC é de código aberto, como qualquer backdoor seria inserido?
Michael Pankov 09/09
2
Lembre-se de que a exploração estável da Thompson requer código que possa reconhecer quando o programa de login ou o compilador estiver sendo compilado. Se você puder transformar manualmente a fonte em um formulário que não seja reconhecível pelo compilador como um desses programas, o backdoor não será propagado.
Russell Borogove
2
@Constantius - leia o artigo da Thompson vinculado na primeira linha. Quem compila o compilador?
Russell Borogove

Respostas:

30

O AFAIK, a única maneira de ter certeza absoluta da segurança, seria escrever um compilador em linguagem assembly (ou modificar o disco diretamente você mesmo ). Somente então você poderá garantir que seu compilador não esteja inserindo um backdoor - isso funciona porque você está realmente eliminando o compilador completamente.

A partir daí, você pode usar seu compilador do zero para inicializar, por exemplo, a cadeia de ferramentas GNU. Então você poderia usar sua cadeia de ferramentas personalizada para compilar um sistema Linux From Scratch .

Observe que, para facilitar as coisas, você pode ter um segundo compilador intermediário, escrito em C (ou qualquer outro idioma). Então, você escreveria o compilador A no assembly e, em seguida, reescreveria esse compilador em C / C ++ / Python / Brainfuck / o que quer que fosse o compilador B, que você compilaria usando o compilador A. Em seguida, usaria o compilador B para compilar o gcc e os amigos.

strugee
fonte
13
Mesmo assim, isso ainda protege apenas contra um compilador malicioso. Você ainda precisa confiar no sistema em que o compilador executa. Nenhum software existe isoladamente.
um CVn 9/09/13
3
Qualquer coisa autônoma é inerentemente perigosa. Você está efetivamente propondo um compilador de cadeias de ferramentas (embora estranho), o que significa que provavelmente pode ser modificado exatamente da maneira que você está tentando evitar. Melhor ainda, poderia ser modificado em trânsito via MitM.
strugee
11
Vocês têm que perceber que essa resposta vem de uma pessoa de 15 anos. Continue indo strugee!
Mtahmed 28/05
3
Não se esqueça de escrever também um editor de código do zero - quem sabe se o seu <code> vim </code> pré-compilado ou o <code> vim </code> você compila com o seu bom compilador da fonte que você auditou apenas usando o infectado <code> vim </code> é confiável?
Hagen von Eitzen
11
Nunca se esqueça, a menos que você tenha escrito pessoalmente o primeiro código de máquina (não a montagem. Código de máquina real) e seja especialista em reconhecer falhas de segurança ocultas, e leia e verifique todas as linhas de código que você está compilando ... ou pelo menos saiba a pessoa que fez isso pessoalmente , e confie nele para fazer isso…. nada disso vai ajudar em nada. É por isso que tentar fazer isso com o Kickstarter está arruinando tudo. Qual é: Alta confiabilidade.
Evi1M4chine
22

Uma maneira possível, embora demorasse muito tempo na prática, seria voltar às raízes. O desenvolvimento do GNU começou em 1984, e a versão original do Minix (usada durante o desenvolvimento inicial do Linux para fins de inicialização) foi lançada em 1987.

Esta resposta inteira é baseada na sua premissa de que "[você] ou outras pessoas têm a capacidade de ler e entender o código-fonte quanto a falhas de segurança, para que o código-fonte seja examinado primeiro antes da compilação" e que você pode confiar no resultado dessa análise . Sem isso, essa resposta provavelmente é pior do que inútil, pois você estará gastando uma quantidade enorme de tempo sem absolutamente nenhum benefício.

Se você puder encontrar uma cópia do livro original do Minix com o código-fonte, poderá digitá-la no livro. Compile-o e, em seguida, use um descompilador diferente em um sistema diferente para verificar se o compilador gera a saída binária da linguagem de máquina esperada. (O código tem apenas 12.000 linhas, presumivelmente C, portanto, isso leva tempo, mas ainda está dentro do razoável, se você levar a sério esse projeto.) Você pode até escrever seu próprio desmontador; isso não deve ser muito difícil.

Pegue as versões mais antigas dos utilitários GNU em que você pode ter as mãos (como presumivelmente possuem menos código e menos dependências de bibliotecas externas), analise o código e construa-o para o Minix (isso pode levar algum trabalho; absolutamente querer evitar é fazer ajustes no código-fonte, porque isso tornará a adição de patches mais tarde propensa a erros) e passará por um ciclo semelhante de desmontagem-verificação para as ferramentas GNU. Nesse ponto, você confia no sistema operacional e na cadeia de ferramentas, portanto, você só precisa passar pelo código-fonte no conjunto de patches (qualquer coisa que não esteja no conjunto de patches já é confiável), mas as ferramentas ainda serão muito primitivas e grosseiras em comparação com o que você está usando para hoje. Não espere nada além da funcionalidade mais básica das ferramentas do sistema, por exemplo.Leia muitos XKCD.

Em algum momento, você terá um sistema que pode compilar e inicializar uma versão inicial do kernel Linux, como foi feito no início dos anos 90, quando o Linux começou a ganhar força entre os hackers. Eu sugiro migrar para o Linux nesse ponto (reconstruir as bibliotecas do sistema e o conjunto de ferramentas contra o Linux, criar o kernel do Linux, inicializar no Linux e, possivelmente, reconstruir o kernel do Linux e o conjunto de ferramentas GNU no Linux; o último prova que o sistema agora é auto- hospedagem), mas isso depende muito de você. Continue verificando as correções, corrigindo o kernel, as bibliotecas e as ferramentas básicas do GNU e reconstruindo até chegar às versões modernas.

É quando você tem um sistema operacional e um compilador básicos confiáveis ​​que podem ser usados ​​para criar software moderno. Até então, você pode seguir, por exemplo, os guias Linux From Scratch para criar um sistema capaz de executar tarefas úteis .

Em nenhum momento o sistema "compilador" pode ser conectado a uma rede de forma alguma (inclusive como uma VM em um host em rede); você arriscaria a penetração através de qualquer componente com capacidade de rede, incluindo o kernel. Se você estiver preocupado com um ataque do compilador Thompson , seria de esperar que qualquer host de VM também seja comprometido. Use o sneakernet para obter o código-fonte e os binários do host físico em que você está compilando as coisas. Espere problemas ao conectar e desconectar arquivos do sistema pelo menos antes de chegar ao ponto em que o suporte ao armazenamento em massa USB foi implementado. Se você é realmente paranóico, listagens de código fonte de impressão e digitá-los com a mão (e espero que o driver da impressora ea impressora não tem um código semelhante em -los) ou leia o código em um monitor de computador e digite-o em outro computador fisicamente próximo a, mas não conectado a ele.

Sim, isso levará muito tempo. Mas a vantagem dessa abordagem é que cada etapa é incremental, o que significa que seria muito mais difícil escapar qualquer coisa maliciosa, a menos que seja introduzida gradualmente durante um período de várias versões; isso porque o conjunto de alterações em cada etapa é comparativamente pequeno e, portanto, muito mais fácil de examinar. Compare o conjunto de patches com o changelog e verifique se você pode determinar exatamente qual entrada do changelog corresponde a cada alteração no código-fonte. Novamente, isso pressupõe que você tem a capacidade (possivelmente através de alguém em quem confia) de verificar se essas alterações não foram infiltradas na base de código, mas deve aproximar você de um sistema confiável como um software somente, exceto: abordagem de firmware pode.

um CVn
fonte
O método de desmontar-verificação é muito falho, pois ainda pressupõe que a máquina de verificação é totalmente confiável. A menos que você construa essa máquina e seu software a partir do zero, ou conheça a pessoa que fez pessoalmente e confie nela, isso não vai acontecer. Então, isso ainda é inseguro. Desculpa. …… Além disso, nessas questões “o mais próximo de…” ainda significa “inseguro”, pois requer apenas um único ponto não confiável para arruinar todo o ponto.
Evi1M4chine 26/01
9

Se você precisar de um compilador confiável, poderá ver o trabalho acadêmico, como o projeto compcert . É um compilador construído pelo INRIA (um laboratório público de TI francês) projetado para ser '' certificado '', ou seja, para produzir um executável semanticamente perfeitamente equivalente ao código (e, é claro, foi matematicamente comprovado).

lgeorget
fonte
11
Todo mundo precisa de um compilador confiável. Como a matemática funciona para que eles possam produzir um compilador "confiável"?
David J
@DavidJ Bootstrapping, provavelmente. Crie um pedacinho que você possa verificar e provar completamente correto e use-o como base para criar compiladores mais complexos.
um CVn 09/09/13
11
"" "O que diferencia o CompCert C de qualquer outro compilador de produção é que ele é formalmente verificado, usando provas matemáticas assistidas por máquina, para ficar isento de problemas de compilação incorreta." "" Compcert.inria.fr/compcert-C.html Compilação não é tão empírico como costumava ser.
precisa saber é o seguinte
11
@ MichaelKjörling que provavelmente não leva em conta que o kernel pode estar comprometido ao incluir um backdoor na fonte do compilador quando lido por um compilador
catraca anormal
11
Eu também encontrei este link que poderia funcionar também.
David J
2

Embora a criação manual de seu próprio compilador como ponto de partida seja a mais segura, outra opção é instalar um sistema a partir de um CD de instalação com 5 (ou 10) anos em que você confia que foi criado antes que essas explorações existissem. Em seguida, use isso como base para compilar a nova fonte auditada.

sambler
fonte
5
O ataque é conhecido publicamente desde 1984. Presumivelmente, Thompson não foi o primeiro a pensar sobre a possibilidade. Voltar tão longe significa que a maioria das coisas que hoje garantimos não existia; considere o que os computadores foram capazes de fazer há 20 anos e compare-o com o estado atual. Até o Minix, o sistema de bootstrap original do Linux, não foi lançado até 87 , e o desenvolvimento do GNU começou em 84. Portanto, enquanto na teoria isso pode responder à pergunta, na prática é amplamente inútil como resposta.
um CVn 09/09/13
2
O primeiro computador em que eu poderia colocar minhas mãos seria um 286. Vou ter que ver se meus avós ainda o têm.
David J
11
Pontos de bônus por realmente considerar isso :-). @DavidJ
11684 09/09
@ MichaelKjörling: Na verdade não; pois isso só aumenta sua cadeia de inicialização. Mas talvez não contanto que você escreva seu próprio compilador do zero em linguagem de máquina.
Evi1M4chine 26/01