From: Breno Rodrigues Alves <breno3011alves@gmail.com>
To: linux-kernel@vger.kernel.org
Cc: Andy Whitcroft <apw@canonical.com>, Joe Perches <joe@perches.com>,
Dwaipayan Ray <dwaipayanray1@gmail.com>,
Lukas Bulwahn <lukas.bulwahn@gmail.com>,
Breno Rodrigues Alves <breno3011alves@gmail.com>
Subject: [RFC PATCH v2 3/7] scripts: convert extract-sys-certs.pl to Python
Date: Sun, 18 Oct 2026 10:57:18 -0300 [thread overview]
Message-ID: <20261018135722.27410-4-breno3011alves@gmail.com> (raw)
In-Reply-To: <20261018135722.27410-1-breno3011alves@gmail.com>
Faithful re-implementation of extract-sys-certs.pl in Python 3
(stdlib only). Same vmlinux section-table parsing, same symbol
lookup (nm with System.map fallback), same VMA-to-file-offset
translation.
Requires a vmlinux with the system certificate list to fully
test; logic is 1:1 with the Perl version.
Signed-off-by: Breno Rodrigues Alves <breno3011alves@gmail.com>
---
| 132 +++++++++++++++++++++++++++++++++++
1 file changed, 132 insertions(+)
create mode 100755 scripts/extract-sys-certs.py
--git a/scripts/extract-sys-certs.py b/scripts/extract-sys-certs.py
new file mode 100755
index 000000000..92a414eb3
--- /dev/null
+++ b/scripts/extract-sys-certs.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+#
+# extract-sys-certs.py [-s <systemmap-file>] <vmlinux-file> <keyring-file>
+
+import re
+import subprocess
+import sys
+
+RE_SECTION = re.compile(
+ r'\s*([0-9]+)\s+(\S+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+'
+ r'([0-9a-f]+)\s+([0-9a-f]+)\s+2\*\*([0-9]+)')
+RE_SYMBOL = re.compile(r'([0-9a-f]+)\s([a-zA-Z])\s(\S+)')
+
+
+def parse_symbols(lines):
+ syms = {}
+ n = 0
+ for line in lines:
+ m = RE_SYMBOL.search(line)
+ if m:
+ syms[m.group(3)] = int(m.group(1), 16)
+ n += 1
+ return syms, n
+
+
+def main(argv):
+ args = list(argv)
+ sysmap = ''
+ if len(args) == 4 and args[0] == '-s':
+ sysmap = args[1]
+ args = args[2:]
+ elif len(args) != 2:
+ sys.exit(f'Format: {sys.argv[0]} [-s <systemmap-file>] '
+ f'<vmlinux-file> <keyring-file>')
+
+ vmlinux, keyring = args
+
+ try:
+ objdump_out = subprocess.check_output(
+ ['objdump', '-h', vmlinux], text=True)
+ except (subprocess.CalledProcessError, FileNotFoundError) as e:
+ sys.exit(f'{vmlinux}: {e}')
+
+ sections = []
+ for line in objdump_out.splitlines():
+ m = RE_SECTION.search(line)
+ if not m:
+ continue
+ sections.append({
+ 'name': m.group(2),
+ 'len': int(m.group(3), 16),
+ 'vma': int(m.group(4), 16),
+ 'foff': int(m.group(6), 16),
+ })
+
+ print(f'Have {len(sections)} sections')
+
+ try:
+ nm_out = subprocess.check_output(
+ ['nm', vmlinux], text=True, stderr=subprocess.DEVNULL)
+ except (subprocess.CalledProcessError, FileNotFoundError):
+ nm_out = ''
+
+ symbols, nr = parse_symbols(nm_out.splitlines())
+
+ if nr == 0 and sysmap:
+ print(f'No symbols in vmlinux, trying {sysmap}')
+ with open(sysmap) as f:
+ symbols, nr = parse_symbols(f.readlines())
+
+ if nr == 0:
+ sys.exit('No symbols available')
+ print(f'Have {nr} symbols')
+
+ if '__cert_list_start' not in symbols or \
+ 'system_certificate_list_size' not in symbols:
+ sys.exit("Can't find system certificate list")
+
+ start = symbols['__cert_list_start']
+ size_sym = symbols['system_certificate_list_size']
+
+ found = None
+ size = 0
+ buf = b''
+ with open(vmlinux, 'rb') as f:
+ for sec in sections:
+ s_vma = sec['vma']
+ s_len = sec['len']
+ s_vend = s_vma + s_len
+
+ if start < s_vma or start >= s_vend:
+ continue
+
+ if size_sym < s_vma or size_sym > s_vend:
+ sys.exit('Certificate list size was not found on the same section')
+
+ if found is not None:
+ sys.exit(f"Cert object in multiple sections: "
+ f"{sec['name']} and {found['name']}")
+
+ size_off = size_sym - s_vma + sec['foff']
+ f.seek(size_off)
+ packed = f.read(8)
+ if len(packed) != 8:
+ sys.exit(vmlinux)
+ size = int.from_bytes(packed, sys.byteorder)
+ end = start + size
+
+ print(f'Have {size} bytes of certs at VMA 0x{start:x}')
+ if end > s_vend:
+ sys.exit(f"Cert object partially overflows section {sec['name']}")
+ found = sec
+
+ if found is None:
+ sys.exit('Cert object not inside a section')
+
+ print(f"Certificate list in section {found['name']}")
+ foff = start - found['vma'] + found['foff']
+ print(f'Certificate list at file offset 0x{foff:x}')
+ f.seek(foff)
+ buf = f.read(size)
+ if len(buf) != size:
+ sys.exit(f'Short read on {vmlinux}')
+
+ with open(keyring, 'wb') as f:
+ f.write(buf)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
\ No newline at end of file
--
2.43.0
next prev parent reply other threads:[~2026-10-18 13:57 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-18 11:28 [RFC PATCH 0/7] scripts: convert remaining Perl utilities in scripts/ Breno Rodrigues Alves
2026-10-18 11:28 ` [RFC PATCH 1/7] scripts: convert checkstack.pl to Python Breno Rodrigues Alves
2026-10-18 11:28 ` [RFC PATCH 2/7] scripts: convert extract-module-sig.pl " Breno Rodrigues Alves
2026-10-18 11:28 ` [RFC PATCH 3/7] scripts: convert extract-sys-certs.pl " Breno Rodrigues Alves
2026-10-18 11:28 ` [RFC PATCH 4/7] scripts: convert headerdep.pl " Breno Rodrigues Alves
2026-10-18 11:28 ` [RFC PATCH 5/7] scripts: convert kconfig-sym-check.pl " Breno Rodrigues Alves
2026-10-18 11:28 ` [RFC PATCH 6/7] scripts: convert parse-maintainers.pl " Breno Rodrigues Alves
2026-10-18 11:28 ` [RFC PATCH 7/7] scripts: convert streamline_config.pl " Breno Rodrigues Alves
2026-10-18 13:57 ` [RFC PATCH v2 0/7] scripts: convert remaining Perl utilities in scripts/ Breno Rodrigues Alves
2026-10-18 13:57 ` [RFC PATCH v2 1/7] scripts: convert checkstack.pl to Python Breno Rodrigues Alves
2026-10-18 13:57 ` [RFC PATCH v2 2/7] scripts: convert extract-module-sig.pl " Breno Rodrigues Alves
2026-10-18 13:57 ` Breno Rodrigues Alves [this message]
2026-10-18 13:57 ` [RFC PATCH v2 4/7] scripts: convert headerdep.pl " Breno Rodrigues Alves
2026-10-18 13:57 ` [RFC PATCH v2 5/7] scripts: convert kconfig-sym-check.pl " Breno Rodrigues Alves
2026-10-18 13:57 ` [RFC PATCH v2 6/7] scripts: convert parse-maintainers.pl " Breno Rodrigues Alves
2026-10-18 13:57 ` [RFC PATCH v2 7/7] scripts: convert streamline_config.pl " Breno Rodrigues Alves
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=20261018135722.27410-4-breno3011alves@gmail.com \
--to=breno3011alves@gmail.com \
--cc=apw@canonical.com \
--cc=dwaipayanray1@gmail.com \
--cc=joe@perches.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lukas.bulwahn@gmail.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®