All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: "Thomas Weißschuh" <thomas.weissschuh@linutronix.de>,
	"Alexandre Ghiti" <alex@ghiti.fr>
Cc: Paul Walmsley <paul.walmsley@sifive.com>,
	Palmer Dabbelt <palmer@dabbelt.com>,
	Albert Ou <aou@eecs.berkeley.edu>,
	Nathan Chancellor <nathan@kernel.org>,
	Nick Desaulniers <nick.desaulniers+lkml@gmail.com>,
	Bill Wendling <morbo@google.com>,
	Justin Stitt <justinstitt@google.com>,
	Andy Lutomirski <luto@kernel.org>,
	Vincenzo Frascino <vincenzo.frascino@arm.com>,
	linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org,
	llvm@lists.linux.dev
Subject: Re: [PATCH v3 3/3] vdso: Reject absolute relocations during build
Date: Sat, 21 Jun 2025 17:42:20 +0200	[thread overview]
Message-ID: <87cyaxp0df.ffs@tglx> (raw)
In-Reply-To: <20250612155635-ecade4e1-0235-464a-bcb3-293f7452510a@linutronix.de>

On Thu, Jun 12 2025 at 16:21, Thomas Weißschuh wrote:
> On Thu, Jun 12, 2025 at 10:31:20AM +0200, Alexandre Ghiti wrote:
> We could introduce per-architecture configuration. Essentially reverting parts
> of commit aff69273af61 ("vdso: Improve cmd_vdso_check to check all dynamic relocations").
> The final logic for the intermediary objects still needs to be more complicated
> than for the final .so as those contain relocations in the debug information.
>
> Or we could add a C hostprog for validation.
> That would be much more flexible than the inline shell command.
> It would then also be easier to use an allow-list than the brittle deny-list.
>
> Or we don't do anything, relying on the selftests to detect miscompilations.

That's a bad idea :)

> I'll run this by tglx. If somebody else has any opinions, I'm all ears.

This is all a mess because the relocation type numbers and their R_*
names are not uniform accross architectures. Neither are the valid
relocation types which are suitable for VDSO.

I don't think you can reasonably cover all of it with readelf and
grep. I did some unrelated relocation analysis some time ago and I just
modified the python script (yes, I hate to use libelf) to show case how
insane this gets. This is just as much as I needed to analyse files
compiled with some random cross gcc I had handy. But you surely get the
idea.

Thanks,

        tglx
---
#!/usr/bin/env python3

import sys

from argparse import ArgumentParser
from elftools.elf.elffile import ELFFile
from elftools.elf.relocation import RelocationSection
from elftools.elf.enums import ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64
from elftools.elf.enums import ENUM_RELOC_TYPE_ARM, ENUM_RELOC_TYPE_AARCH64
from elftools.elf.descriptions import describe_reloc_type

class relocs(object):
    def __init__(self, arch, sections, types):
        self.arch = arch
        self.sections = sections
        self.types = types

i386_relocs = relocs('EM_386',
                     [ '.rel.text' ],
                     [ ENUM_RELOC_TYPE_i386['R_386_NONE'],
                       ENUM_RELOC_TYPE_i386['R_386_PC32'],
                       ENUM_RELOC_TYPE_i386['R_386_GOTPC'],
                       ENUM_RELOC_TYPE_i386['R_386_GOTOFF'],
                      ])

x86_64_relocs = relocs('EM_X86_64',
                       [ '.rela.text' ],
                       [ ENUM_RELOC_TYPE_x64['R_X86_64_NONE'],
                         ENUM_RELOC_TYPE_x64['R_X86_64_PC32'],
                        ])

arm_relocs = relocs('EM_ARM',
                       [ '.rela.text' ],
                       # Probably incomplete
                       [ ENUM_RELOC_TYPE_ARM['R_ARM_NONE'],
                         ENUM_RELOC_TYPE_ARM['R_ARM_REL32'],
                        ])

arm64_relocs = relocs('EM_AARCH64',
                       [ '.rela.text' ],
                       # Probably incomplete
                       [ ENUM_RELOC_TYPE_AARCH64['R_AARCH64_NONE'],
                         ENUM_RELOC_TYPE_AARCH64['R_AARCH64_ADR_PREL_LO21'],
                        ])

# Minimal set for an example VDSO build
ENUM_RELOC_TYPE_RISCV = dict(
    R_RISCV_BRANCH        = 0x10,
    R_RISCV_PCREL_HI20    = 0x17,
    R_RISCV_PCREL_LO12_I  = 0x18,
    R_RISCV_RVC_BRANCH    = 0x2c,
    R_RISCV_RVC_JUMP      = 0x2d,
    R_RISCV_RELAX         = 0x33,
)

riscv_relocs = relocs('EM_RISCV',
                       [ '.rela.text' ],
                       [ ENUM_RELOC_TYPE_RISCV['R_RISCV_BRANCH'],
                         ENUM_RELOC_TYPE_RISCV['R_RISCV_PCREL_HI20'],
                         ENUM_RELOC_TYPE_RISCV['R_RISCV_PCREL_LO12_I'],
                         ENUM_RELOC_TYPE_RISCV['R_RISCV_RVC_BRANCH'],
                         ENUM_RELOC_TYPE_RISCV['R_RISCV_RVC_JUMP'],
                         ENUM_RELOC_TYPE_RISCV['R_RISCV_RELAX'],
                        ])
supported_archs = {
    'i386'      : i386_relocs,
    'x86_64'    : x86_64_relocs,
    'arm'       : arm_relocs,
    'arm64'     : arm64_relocs,
    'riscv'     : riscv_relocs,
}

# Probably incomplete
invalid_relocs = [ '.rela.dyn', '.rela.plt' ]

def check_relocations(file, arch):
    elf = ELFFile(file)
    res = 0

    if elf.header['e_machine'] != arch.arch:
        print(elf.header['e_machine'], arch.arch)
        raise Exception('Architecture mismatch')

    for section in elf.iter_sections():
        if not isinstance(section, RelocationSection):
            continue

        if section.name in invalid_relocs:
            print('Invalid VDSO relocation section: %s' %section.name)
            res += 1
            continue

        if section.name not in arch.sections:
            continue

        for reloc in section.iter_relocations():
            if reloc['r_info_type'] in arch.types:
                continue
            res += 1

            symt = elf.get_section(section['sh_link'])
            sym = symt.get_symbol(reloc['r_info_sym'])

            type = describe_reloc_type(reloc['r_info_type'], elf)

            print("Invalid VDSO relocation: %s %s" %(type, sym.name))

    return res

if __name__ == '__main__':
    parser = ArgumentParser(usage = 'usage: %(prog)s arch elf-file',
                            description = 'magic VDSO section checker',
                            prog = 'vdsoreloc')

    parser.add_argument('arch',
                        choices = supported_archs.keys(),
                        help = 'Target architecture')
    parser.add_argument('file', help = 'ELF file to parse')
    args = parser.parse_args()

    with open(args.file, 'rb') as file:
        try:
            res = check_relocations(file, supported_archs[args.arch])
            sys.exit(res)
        except Exception as ex:
            # Do something sensible here
            print(ex)
            sys.exit(1)



_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

WARNING: multiple messages have this Message-ID (diff)
From: Thomas Gleixner <tglx@linutronix.de>
To: "Thomas Weißschuh" <thomas.weissschuh@linutronix.de>,
	"Alexandre Ghiti" <alex@ghiti.fr>
Cc: Paul Walmsley <paul.walmsley@sifive.com>,
	Palmer Dabbelt <palmer@dabbelt.com>,
	Albert Ou <aou@eecs.berkeley.edu>,
	Nathan Chancellor <nathan@kernel.org>,
	Nick Desaulniers <nick.desaulniers+lkml@gmail.com>,
	Bill Wendling <morbo@google.com>,
	Justin Stitt <justinstitt@google.com>,
	Andy Lutomirski <luto@kernel.org>,
	Vincenzo Frascino <vincenzo.frascino@arm.com>,
	linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org,
	llvm@lists.linux.dev
Subject: Re: [PATCH v3 3/3] vdso: Reject absolute relocations during build
Date: Sat, 21 Jun 2025 17:42:20 +0200	[thread overview]
Message-ID: <87cyaxp0df.ffs@tglx> (raw)
In-Reply-To: <20250612155635-ecade4e1-0235-464a-bcb3-293f7452510a@linutronix.de>

On Thu, Jun 12 2025 at 16:21, Thomas Weißschuh wrote:
> On Thu, Jun 12, 2025 at 10:31:20AM +0200, Alexandre Ghiti wrote:
> We could introduce per-architecture configuration. Essentially reverting parts
> of commit aff69273af61 ("vdso: Improve cmd_vdso_check to check all dynamic relocations").
> The final logic for the intermediary objects still needs to be more complicated
> than for the final .so as those contain relocations in the debug information.
>
> Or we could add a C hostprog for validation.
> That would be much more flexible than the inline shell command.
> It would then also be easier to use an allow-list than the brittle deny-list.
>
> Or we don't do anything, relying on the selftests to detect miscompilations.

That's a bad idea :)

> I'll run this by tglx. If somebody else has any opinions, I'm all ears.

This is all a mess because the relocation type numbers and their R_*
names are not uniform accross architectures. Neither are the valid
relocation types which are suitable for VDSO.

I don't think you can reasonably cover all of it with readelf and
grep. I did some unrelated relocation analysis some time ago and I just
modified the python script (yes, I hate to use libelf) to show case how
insane this gets. This is just as much as I needed to analyse files
compiled with some random cross gcc I had handy. But you surely get the
idea.

Thanks,

        tglx
---
#!/usr/bin/env python3

import sys

from argparse import ArgumentParser
from elftools.elf.elffile import ELFFile
from elftools.elf.relocation import RelocationSection
from elftools.elf.enums import ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64
from elftools.elf.enums import ENUM_RELOC_TYPE_ARM, ENUM_RELOC_TYPE_AARCH64
from elftools.elf.descriptions import describe_reloc_type

class relocs(object):
    def __init__(self, arch, sections, types):
        self.arch = arch
        self.sections = sections
        self.types = types

i386_relocs = relocs('EM_386',
                     [ '.rel.text' ],
                     [ ENUM_RELOC_TYPE_i386['R_386_NONE'],
                       ENUM_RELOC_TYPE_i386['R_386_PC32'],
                       ENUM_RELOC_TYPE_i386['R_386_GOTPC'],
                       ENUM_RELOC_TYPE_i386['R_386_GOTOFF'],
                      ])

x86_64_relocs = relocs('EM_X86_64',
                       [ '.rela.text' ],
                       [ ENUM_RELOC_TYPE_x64['R_X86_64_NONE'],
                         ENUM_RELOC_TYPE_x64['R_X86_64_PC32'],
                        ])

arm_relocs = relocs('EM_ARM',
                       [ '.rela.text' ],
                       # Probably incomplete
                       [ ENUM_RELOC_TYPE_ARM['R_ARM_NONE'],
                         ENUM_RELOC_TYPE_ARM['R_ARM_REL32'],
                        ])

arm64_relocs = relocs('EM_AARCH64',
                       [ '.rela.text' ],
                       # Probably incomplete
                       [ ENUM_RELOC_TYPE_AARCH64['R_AARCH64_NONE'],
                         ENUM_RELOC_TYPE_AARCH64['R_AARCH64_ADR_PREL_LO21'],
                        ])

# Minimal set for an example VDSO build
ENUM_RELOC_TYPE_RISCV = dict(
    R_RISCV_BRANCH        = 0x10,
    R_RISCV_PCREL_HI20    = 0x17,
    R_RISCV_PCREL_LO12_I  = 0x18,
    R_RISCV_RVC_BRANCH    = 0x2c,
    R_RISCV_RVC_JUMP      = 0x2d,
    R_RISCV_RELAX         = 0x33,
)

riscv_relocs = relocs('EM_RISCV',
                       [ '.rela.text' ],
                       [ ENUM_RELOC_TYPE_RISCV['R_RISCV_BRANCH'],
                         ENUM_RELOC_TYPE_RISCV['R_RISCV_PCREL_HI20'],
                         ENUM_RELOC_TYPE_RISCV['R_RISCV_PCREL_LO12_I'],
                         ENUM_RELOC_TYPE_RISCV['R_RISCV_RVC_BRANCH'],
                         ENUM_RELOC_TYPE_RISCV['R_RISCV_RVC_JUMP'],
                         ENUM_RELOC_TYPE_RISCV['R_RISCV_RELAX'],
                        ])
supported_archs = {
    'i386'      : i386_relocs,
    'x86_64'    : x86_64_relocs,
    'arm'       : arm_relocs,
    'arm64'     : arm64_relocs,
    'riscv'     : riscv_relocs,
}

# Probably incomplete
invalid_relocs = [ '.rela.dyn', '.rela.plt' ]

def check_relocations(file, arch):
    elf = ELFFile(file)
    res = 0

    if elf.header['e_machine'] != arch.arch:
        print(elf.header['e_machine'], arch.arch)
        raise Exception('Architecture mismatch')

    for section in elf.iter_sections():
        if not isinstance(section, RelocationSection):
            continue

        if section.name in invalid_relocs:
            print('Invalid VDSO relocation section: %s' %section.name)
            res += 1
            continue

        if section.name not in arch.sections:
            continue

        for reloc in section.iter_relocations():
            if reloc['r_info_type'] in arch.types:
                continue
            res += 1

            symt = elf.get_section(section['sh_link'])
            sym = symt.get_symbol(reloc['r_info_sym'])

            type = describe_reloc_type(reloc['r_info_type'], elf)

            print("Invalid VDSO relocation: %s %s" %(type, sym.name))

    return res

if __name__ == '__main__':
    parser = ArgumentParser(usage = 'usage: %(prog)s arch elf-file',
                            description = 'magic VDSO section checker',
                            prog = 'vdsoreloc')

    parser.add_argument('arch',
                        choices = supported_archs.keys(),
                        help = 'Target architecture')
    parser.add_argument('file', help = 'ELF file to parse')
    args = parser.parse_args()

    with open(args.file, 'rb') as file:
        try:
            res = check_relocations(file, supported_archs[args.arch])
            sys.exit(res)
        except Exception as ex:
            # Do something sensible here
            print(ex)
            sys.exit(1)



  reply	other threads:[~2025-06-21 15:42 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-11  9:22 [PATCH v3 0/3] vdso: Reject absolute relocations during build Thomas Weißschuh
2025-06-11  9:22 ` Thomas Weißschuh
2025-06-11  9:22 ` [PATCH v3 1/3] riscv: vdso: Deduplicate CFLAGS_REMOVE_* variables Thomas Weißschuh
2025-06-11  9:22   ` Thomas Weißschuh
2025-06-11 18:40   ` Nathan Chancellor
2025-06-11 18:40     ` Nathan Chancellor
2025-06-12  8:13     ` Alexandre Ghiti
2025-06-12  8:13       ` Alexandre Ghiti
2025-06-11  9:22 ` [PATCH v3 2/3] riscv: vdso: Disable LTO for the vDSO Thomas Weißschuh
2025-06-11  9:22   ` Thomas Weißschuh
2025-06-11 18:41   ` Nathan Chancellor
2025-06-11 18:41     ` Nathan Chancellor
2025-06-11  9:22 ` [PATCH v3 3/3] vdso: Reject absolute relocations during build Thomas Weißschuh
2025-06-11  9:22   ` Thomas Weißschuh
2025-06-11 18:57   ` Nathan Chancellor
2025-06-11 18:57     ` Nathan Chancellor
2025-06-12  5:48     ` Thomas Weißschuh
2025-06-12  5:48       ` Thomas Weißschuh
2025-06-12  8:31   ` Alexandre Ghiti
2025-06-12  8:31     ` Alexandre Ghiti
2025-06-12 14:21     ` Thomas Weißschuh
2025-06-12 14:21       ` Thomas Weißschuh
2025-06-21 15:42       ` Thomas Gleixner [this message]
2025-06-21 15:42         ` Thomas Gleixner
2025-06-23  7:25         ` Thomas Weißschuh
2025-06-23  7:25           ` Thomas Weißschuh
2025-06-12 20:05     ` Palmer Dabbelt
2025-06-12 20:05       ` Palmer Dabbelt
2025-06-13  1:08       ` Jessica Clarke
2025-06-13  1:08         ` Jessica Clarke

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87cyaxp0df.ffs@tglx \
    --to=tglx@linutronix.de \
    --cc=alex@ghiti.fr \
    --cc=aou@eecs.berkeley.edu \
    --cc=justinstitt@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=llvm@lists.linux.dev \
    --cc=luto@kernel.org \
    --cc=morbo@google.com \
    --cc=nathan@kernel.org \
    --cc=nick.desaulniers+lkml@gmail.com \
    --cc=palmer@dabbelt.com \
    --cc=paul.walmsley@sifive.com \
    --cc=thomas.weissschuh@linutronix.de \
    --cc=vincenzo.frascino@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.