Pular para o conteúdo

Rust teve um bug de segurança de memória por 11 anos

Ver no idioma original →

Autoria: Better Stack · Assistir no YouTube

Vídeo de autoria do canal indicado, não da IANIA; todos os direitos pertencem ao criador. Transcrição, resumo e tradução gerados automaticamente; o conteúdo no idioma original é preservado na versão em idioma original.

Idioma original: inglês

Vídeo original: Rust Had a Memory Safety Bug for 11 Years #rust #programming #security · Canal: Better Stack · 01:36 · Assistir no YouTube

Tópicos: Cibersegurança e segurança de software, Engenharia de software com IA

O vídeo apresenta um bug de segurança de memória em Rust que permitia acessar memória depois que ela era liberada, mesmo usando código considerado seguro. O problema estava relacionado a uma atribuição que não verificava a regra de tempo de vida de uma struct com limite 'static. Um código de descarte que abusasse dessa falha podia passar uma referência inválida para uma thread. A falha existia desde o Rust 1.4, lançado em 2015, mas, segundo o vídeo, seria difícil encontrá-la por acidente.

  • Uma issue no repo do Rust recebeu o rótulo unsound, indicando uma falha grave de segurança do compilador.
  • O exemplo usa uma struct cujo conteúdo deveria viver por 'static.
  • O compilador não verifica a regra de tempo de vida da struct durante a atribuição de uma referência ao campo.
  • Uma função drop que confie nessa referência pode permitir o acesso a memória já liberada.
  • Uma variante do exemplo passa a referência para uma thread, que a imprime depois que a memória foi liberada.
  • Um colaborador do compilador encontrou a falha no Godbolt e concluiu que ela existia desde o Rust 1.4, em 2015.
  • O vídeo afirma que o bug exige código de descarte escrito deliberadamente para abusar da falha.
  • O caso ilustra que a segurança de memória prometida por um compilador depende de código, que também pode conter bugs.
Início Capítulo Resumo
00:00 A falha de segurança de memória O vídeo apresenta a falha no compilador do Rust e explica o uso de uma struct com limite 'static.
00:31 Como o bug permite acessar memória liberada A atribuição passa sem que o compilador verifique o tempo de vida, e o código de descarte pode levar a uma referência inválida.
01:05 A falha existia desde 2015 A investigação aponta que o bug remonta ao Rust 1.4, e o vídeo observa que é necessário abusar dele deliberadamente.

Por 11 anos, dava para fazer exatamente isso em cerca de 10 linhas de Rust seguro. — 00:00

O compilador deveria rejeitar isso. Não rejeita. — 00:31

Como é que isso não foi descoberto antes? — 01:05

A segurança de memória é uma promessa feita por um compilador, e compiladores também são código. — 01:05

  • Rust (ferramenta): Linguagem de programação cujo compilador é apresentado no vídeo como tendo uma falha de segurança de memória.
  • Rust repo (repo): Repositório do Rust onde a issue 164250 foi aberta.
  • issue 164250 (conceito): Issue do repo do Rust que recebeu o rótulo unsound por relatar uma falha no compilador.
  • static bound (conceito): Limite de tempo de vida que exige que o valor referenciado possa viver por toda a duração do programa.
  • drop (conceito): Função executada quando um valor é descartado; no exemplo, ela confia em uma referência que deveria viver por 'static.
  • Godbolt (ferramenta): Serviço usado por um colaborador do compilador para executar o exemplo e investigar há quanto tempo a falha existia.
  • Rust 1.4 (modelo): Versão do Rust que, segundo a investigação mencionada no vídeo, já apresentava a falha em 2015.

00:00 A ideia central do Rust é que o compilador não deixa você acessar a memória depois que ela é liberada. Mas, durante 11 anos, era possível fazer exatamente isso com cerca de 10 linhas de Rust seguro. Deixe-me explicar. Na semana passada, alguém abriu a issue 164250 no repo do Rust, e ela recebeu o rótulo “não sólido”. Esse é o pior tipo de bug que um compilador pode ter. Veja como funciona. Você cria uma struct que diz: “Tudo o que eu armazenar precisa viver para sempre”. Esse é o limite ’static. Depois, você escreve uma função drop que confia nessa promessa.

00:31 Agora, na função main, você cria uma string normal que só vive por algumas linhas. Cria a struct vazia e, em seguida, atribui uma referência a essa string ao campo dela. O compilador deveria rejeitar isso. Mas não rejeita. Ele nunca verifica a regra de tempo de vida da struct nessa atribuição. Então, quando a struct é descartada, seu código drop está segurando uma referência que vive para sempre dentro de uma string que está prestes a ser liberada. Uma versão passa essa referência para uma thread, que a imprime um segundo depois, e aí você está lendo memória liberada. E aqui está

01:05 a parte mais louca. Uma pessoa que contribui com o compilador executou o código no Godbolt e descobriu que ele não é sólido desde o Rust 1.4, lá em 2015. A pessoa que encontrou o bug escreveu, literalmente: “Como é que isso ainda não tinha sido encontrado?”. A boa notícia é que você não vai se deparar com isso por acidente. Você teria que escrever um drop que abusasse disso de propósito, e é por isso que o bug foi marcado como de alta prioridade, não crítico. Segurança de memória é uma promessa feita pelo compilador, e compiladores também são código. Se você quiser

01:36 mais dicas e truques de programação como este, não deixe de se inscrever no canal da Better Stack.

Transcrição original

[00:00] Rust’s whole deal is that the compiler won’t let you touch memory after it’s freed. But for 11 years, you could do exactly that in about 10 lines of safe Rust. Let me explain. Last week, someone opened issue 164250 on Rust repo, and it got the unsound label. That’s the worst kind of bug a compiler can have. Here’s how it works. You make a struct that says, “Whatever I hold has to live forever.” That’s the static bound. Then you write a drop

[00:31] function that trusts that promise. Now, in main, you create a normal string that only lives for a few lines. You create the struct empty, and then you assign a reference to that string into its field. The compiler should reject that. It doesn’t. It never checks the struct’s lifetime rule on that assignment. So, when the struct gets dropped, your drop code is holding a lives forever reference in a string that’s about to be freed. One version hands it to a thread that prints it a second later, and now you’re reading freed memory. And here’s

[01:05] the craziest part. A compiler contributor ran it on a Godbolt and found it’s been unsound since Rust 1.4, back in 2015. The person who found it literally wrote, “How on Earth has this not been found before?” The good news is you won’t hit this by accident. You’d have to write a drop that deliberately abuses it, which is why it’s tagged high priority, not critical. Memory safe is a promise made by a compiler, and compilers are code, too. If you want

[01:36] more coding tips and tricks like this, be sure to subscribe to the Better Stack channel.