1 pontos por GN⁺ 2024-09-30 | 1 comentários | Compartilhar no WhatsApp

Os riscos da transição para time_t de 64 bits

  • O uso do tipo time_t de 32 bits pode fazer com que aplicações de 32 bits apresentem erros em 2038
  • Alterar time_t para um tipo de 64 bits é apresentado como a solução
  • O Musl já concluiu a transição, o glibc oferece suporte como opção, e várias distribuições como o Debian já concluíram a migração
  • Distribuições baseadas em código-fonte, como o Gentoo, têm mais dificuldade para fazer a transição

Voltando ao Large File Support

  • Arquiteturas de 32 bits usam off_t, que indica o deslocamento de arquivo, e ino_t, que indica o número do inode, como tipos de 32 bits
  • Por causa disso, não é possível abrir arquivos maiores que 2 GiB, nem arquivos cujo número de inode ultrapasse o intervalo de 32 bits
  • A introdução do Large File Support resolveu esse problema, mas no glibc isso ainda continua sendo opcional
  • O uso de LFS é necessário para o suporte a time64

Qual ABI está sendo usada?

  • Existem três sub-ABIs possíveis:
    1. A ABI original que usa tipos de 32 bits
    2. LFS com off_t e ino_t de 64 bits e time_t de 32 bits
    3. time64 usando LFS + time_t de 64 bits
  • Um build do glibc pode ser compatível com as três variações, mas bibliotecas que usam esses tipos na API não são compatíveis entre si

Por que mudar a ABI é ruim?

  • Substituir tipos de 32 bits por tipos de 64 bits quebra a compatibilidade
  • No caso de structs, se houver time_t incluído, a posição dos campos muda e isso pode fazer com que campos errados sejam lidos ou escritos
  • No caso de parâmetros de função, a posição dos parâmetros passados na pilha muda, o que pode fazer com que parâmetros errados sejam lidos ou escritos
  • Esses problemas podem causar erros em tempo de execução e falhas de segurança

Como tornar isso seguro?

  • Três ideias:
    1. Alterar a tupla de plataforma (CHOST) para distinguir a nova ABI
    2. Alterar o libdir para a nova ABI
    3. Introduzir uma distinção de ABI no nível binário para impedir que binários com sub-ABIs diferentes sejam linkados

Alterando a tupla de plataforma

  • A tupla de plataforma identifica a plataforma alvo da toolchain
  • Para introduzir a nova ABI, é possível alterar o campo do fornecedor ou adicionar uma especificação extra de ABI no campo da libc
  • Exemplos: i686-gentoo_t64-linux-gnu, i686-pc-linux-gnut64

Alterando o libdir

  • libdir é o nome padrão do diretório de instalação de bibliotecas
  • Para a variante time64, altera-se o valor de libdir para instalar as bibliotecas time64 em um novo diretório
  • Isso impede que executáveis time64 façam link com bibliotecas time32
  • O recurso preserved-libs do Portage pode ser usado para preservar bibliotecas existentes

Garantindo compatibilidade binária

  • Não é possível misturar binários que usam ABIs diferentes
  • Classe ELF, identificador de máquina, campo de flags etc. podem ser usados para verificar compatibilidade
  • Também se considera adicionar uma nova seção de notas ELF para distinguir sistemas time32 e time64

Aplicações pré-compiladas antigas

  • Aplicações pré-compiladas antigas enfrentam problemas de compatibilidade com bibliotecas do sistema e também o problema do y2k38
  • Um layout multilib pode resolver os problemas de compatibilidade
  • O problema do y2k38 pode ser contornado manipulando a hora do sistema ou usando uma VM

Resumo do GN⁺

  • Aplicações que usam time_t de 32 bits podem apresentar erros após 2038
  • A transição para time_t de 64 bits é necessária, mas envolve uma mudança de ABI que gera problemas complexos
  • Alterar a tupla de plataforma, mudar o libdir e garantir a compatibilidade binária podem oferecer um caminho de transição seguro
  • Aplicações pré-compiladas antigas exigem tratar separadamente os problemas de compatibilidade e do y2k38

1 comentários

 
GN⁺ 2024-09-30
Comentários do Hacker News
  • O Gentoo carece de uma opção para compilar sem instalar o pacote

    • No Gentoo, a compilação e a instalação do pacote acontecem em uma única etapa
    • Em mudanças de ABI, o sistema pode quebrar facilmente durante a atualização
    • O problema do time_t de 64 bits é um exemplo amplamente conhecido de mudança de ABI
  • Como lidar com mudanças de ABI por meio de versionamento de .so

    • Arquivos .so incluem números de versão
    • O próprio pacote gerencia internamente os números de versão
    • Para dar suporte a time_t de 64 bits, é necessário um componente adicional que permita controlar a ABI herdada
  • Como o Mac OS X lidou com off_t e ino_t

    • As chamadas e estruturas existentes foram mantidas
    • O sufixo 64 foi adicionado a novas chamadas e tipos
    • Na compilação, é possível definir a versão mínima do sistema operacional em que o binário compilado poderá rodar
  • O Debian teve dificuldades para migrar para time_t de 64 bits

    • Distribuições baseadas em código-fonte passam por um processo de transição ainda mais difícil
  • Experiência de substituir time_t por unsigned de 32 bits em sistemas Unix de 32 bits

    • Isso permitiu usar o sistema por mais 68 anos após 2038
    • Não é possível representar datas anteriores à época Unix
  • Experiência de introduzir time_t de 64 bits ao fazer o port para amd64 no FreeBSD

    • Argumentos de função de 32 bits são convertidos automaticamente para 64 bits
    • O uso de time_t de 64 bits desde o início evitou problemas
    • Houve alguns problemas porque o tzcode não era seguro para 64 bits
  • A piada na seção "Bugs" das páginas de manual do BSD

    • "You can tune a file system, but you can't tune a fish."
  • Opinião de que seria melhor migrar de uma distribuição baseada em código-fonte para uma distribuição não baseada em código-fonte, como o Debian

  • Diferença nos offsets de estrutura entre time_t de 32 bits e time_t de 64 bits

    • No tipo de 64 bits, b exige alinhamento de 64 bits, então padding é adicionado
  • A ideia de que aliases de tipo em C permitiriam mudanças futuras, mas na prática isso não acontece

  • Opinião de que é melhor resolver o problema rapidamente

    • O OpenBSD usa time_t de 64 bits em todas as arquiteturas