Leitura e escrita fora dos limites em `qsort()` da glibc
Uma leitura/escrita fora dos limites recentemente identificada em `qsort()` da glibc surge apenas quando programas lhe passam uma função de comparação “ruim”, como uma que transborda ao subtrair inteiros ou viola regras de ordenação com floats e NaNs. Comentadores debatem se isso é realmente uma vulnerabilidade de segurança na glibc ou apenas comportamento indefinido causado por código incorreto do chamador, e se merece um CVE dada a raridade e a dificuldade de exploração. A discussão se amplia para uma comparação entre culturas de segurança em C/C++ e Rust, além de outras linguagens, argumentando sobre quanta responsabilidade bibliotecas devem assumir para se defender contra uso incorreto versus preservar desempenho e simplicidade.
Natureza do bug do qsort
- O bug é uma leitura/escrita fora dos limites no
qsortda glibc quando o chamador fornece uma função de comparação não transitiva (com defeito). - Muitos veem isso como “erro do usuário” (parâmetro inválido), análogo a chamar
memcpycom ponteiros ruins, mas ainda assim concordam que corrigir verificações de limites é uma boa prática defensiva. - Outros enfatizam que a implementação “óbvia” do comparador (
a - b) está sutilmente errada devido a overflow de inteiros, então isso não é puramente um caso extremo exótico.
“Segurando errado” vs vulnerabilidade de segurança
- Uma corrente argumenta que isso é principalmente um bug no código da aplicação, já que os padrões exigem explicitamente uma ordenação total; o comportamento indefinido é responsabilidade do chamador.
- Outra corrente diz que, se um uso comum pode causar corrupção de memória, isso é um problema legítimo de segurança e merece um CVE também para a implementação da biblioteca.
- Há críticas à postura de “é UB então vale tudo” da cultura de C/C++, em contraste com normas mais defensivas em outros lugares.
Comparadores, NaNs e ponto flutuante
- Ordenar floats com NaNs ou infinitos mal tratados pode violar os requisitos do comparador, causando travamentos ou comportamento incorreto.
- Exemplos mostram como NaNs quebram reflexividade e transitividade, confundindo algoritmos de ordenação. Alguns sugerem que tentar ordenar NaNs já costuma ser um bug de lógica.
Culturas de segurança de linguagem e overflow de inteiros
- Rust é citado como tratando casos de “você está segurando errado” como questões de segurança: comparadores ruins podem dar resultados errados, mas não UB; traits como
Ordsão seguras, com “unsafe traits” separados para invariantes que podem causar UB se violados. - Discussão sobre tratamento de overflow:
- operações verificadas/saturadas/por wrap de Rust e comportamento debug vs release.
- overflow com sinal em C/C++ como UB; wraparound sem sinal muitas vezes não é o que programadores pretendem.
- Ada, Pascal e WUFFS como exemplos de linguagens ou DSLs que codificam intervalos/refinamentos para mais segurança.
Desempenho e alternativas ao qsort
qsorté descrito como relativamente lento; para código de alto desempenho, pessoas recomendamstd::sortde C++ ou bibliotecas especializadas, às vezes via um wrapper fino em C++ chamável de C.- Alguns se preocupam com o custo de desempenho de verificações extras de segurança; outros argumentam que o custo geralmente é negligenciável.
Explorabilidade, CVEs e pontuação
- A explorabilidade é debatida: exige um comparador já defeituoso e muitas vezes um contexto privilegiado (por exemplo, setuid-root); nenhum exploit em ambiente real é conhecido na discussão.
- Há opiniões divididas sobre emitir ou não um CVE:
- A favor: incentiva usuários a auditar comparadores e atualizar.
- Contra: CVEs são custosos para ambientes regulados e devem ser reservados para problemas claramente exploráveis.
- Frustração mais ampla com as pontuações CVSS: alguns bugs graves e facilmente exploráveis recebem nota baixa, enquanto bugs impraticáveis do tipo DoS recebem pontuações altas, tornando a priorização difícil.