|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# |
| 3 | +# Seccomp Library program to build the kernel version tables |
| 4 | +# |
| 5 | +# Copyright (c) 2025 Oracle and/or its affiliates. All rights reserved. |
| 6 | +# Author: Tom Hromatka <[email protected]> |
| 7 | +# |
| 8 | + |
| 9 | +# |
| 10 | +# This library is free software; you can redistribute it and/or modify it |
| 11 | +# under the terms of version 2.1 of the GNU Lesser General Public License as |
| 12 | +# published by the Free Software Foundation. |
| 13 | +# |
| 14 | +# This library is distributed in the hope that it will be useful, but WITHOUT |
| 15 | +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 16 | +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License |
| 17 | +# for more details. |
| 18 | +# |
| 19 | +# You should have received a copy of the GNU Lesser General Public License |
| 20 | +# along with this library; if not, see <http://www.gnu.org/licenses>. |
| 21 | +# |
| 22 | + |
| 23 | +####################################################### |
| 24 | +#### WARNING - to generate proper headers for x32, you |
| 25 | +#### must install the glibc 32-bit headers |
| 26 | +#### |
| 27 | +#### apt install libc6-dev-x32 |
| 28 | +#### |
| 29 | +####################################################### |
| 30 | + |
| 31 | +from subprocess import TimeoutExpired |
| 32 | +import subprocess |
| 33 | +import argparse |
| 34 | +import os |
| 35 | + |
| 36 | +kernel_versions = ['3.0', '3.1', '3.2', '3.3', '3.4', '3.5', '3.6', '3.7', |
| 37 | + '3.8', '3.9', '3.10', '3.11', '3.12', '3.13', '3.14', |
| 38 | + '3.15', '3.16', '3.17', '3.18', '3.19', '4.0', '4.1', |
| 39 | + '4.2', '4.3', '4.4', '4.5', '4.6', '4.7', '4.8', '4.9', |
| 40 | + '4.10', '4.11', '4.12', '4.13', '4.14', '4.15', '4.16', |
| 41 | + '4.17', '4.18', '4.19', '4.20', '5.0', '5.1', '5.2', |
| 42 | + '5.3', '5.4', '5.5', '5.6', '5.7', '5.8', '5.9', '5.10', |
| 43 | + '5.11', '5.12', '5.13', '5.14', '5.15', '5.16', '5.17', |
| 44 | + '5.18', '5.19', '6.0', '6.1', '6.2', '6.3', '6.4', '6.5', |
| 45 | + '6.6', '6.7', '6.8', '6.9', '6.10', '6.11', '6.12', |
| 46 | + '6.13', '6.14', '6.15', '6.16', '6.17'] |
| 47 | + |
| 48 | +def parse_args(): |
| 49 | + parser = argparse.ArgumentParser('Script to populate the syscalls.csv kernel versions', |
| 50 | + formatter_class=argparse.RawTextHelpFormatter) |
| 51 | + parser.add_argument('-d', '--datapath', required=True, type=str, default=None, |
| 52 | + help="Path to the local copy of @hrw's syscalls-table tool") |
| 53 | + parser.add_argument('-k', '--kernelpath', required=True, type=str, default=None, |
| 54 | + help="Path to the kernel source directory") |
| 55 | + parser.add_argument('-V', '--versions', required=False, type=str, default=None, |
| 56 | + help="Comma-separated list of kernel versions to build, e.g " |
| 57 | + "3.0,6.1,6.10. If not specified all known kernel version " |
| 58 | + "tables are built") |
| 59 | + parser.add_argument('-v', '--verbose', action='store_true', |
| 60 | + help='Show verbose warnings') |
| 61 | + |
| 62 | + args = parser.parse_args() |
| 63 | + |
| 64 | + if not args.versions: |
| 65 | + args.versions = kernel_versions |
| 66 | + else: |
| 67 | + args.versions = args.versions.split(',') |
| 68 | + |
| 69 | + return args |
| 70 | + |
| 71 | +def run(command, verbose=False, shell=False, timeout=None): |
| 72 | + if shell: |
| 73 | + if isinstance(command, str): |
| 74 | + # nothing to do. command is already formatted as a string |
| 75 | + pass |
| 76 | + elif isinstance(command, list): |
| 77 | + command = ' '.join(command) |
| 78 | + else: |
| 79 | + raise ValueError('Unsupported command type') |
| 80 | + |
| 81 | + subproc = subprocess.Popen(command, shell=shell, |
| 82 | + stdout=subprocess.PIPE, |
| 83 | + stderr=subprocess.PIPE) |
| 84 | + |
| 85 | + if timeout: |
| 86 | + try: |
| 87 | + out, err = subproc.communicate(timeout=timeout) |
| 88 | + ret = subproc.returncode |
| 89 | + |
| 90 | + out = out.strip().decode('UTF-8') |
| 91 | + err = err.strip().decode('UTF-8') |
| 92 | + except TimeoutExpired as timeout: |
| 93 | + if timeout.stdout: |
| 94 | + out = timeout.stdout.strip().decode('UTF-8') |
| 95 | + else: |
| 96 | + out = '' |
| 97 | + if timeout.stderr: |
| 98 | + err = timeout.stderr.strip().decode('UTF-8') |
| 99 | + else: |
| 100 | + err = '' |
| 101 | + |
| 102 | + if len(err): |
| 103 | + ret = -1 |
| 104 | + else: |
| 105 | + ret = 0 |
| 106 | + else: |
| 107 | + out, err = subproc.communicate() |
| 108 | + ret = subproc.returncode |
| 109 | + |
| 110 | + out = out.strip().decode('UTF-8') |
| 111 | + err = err.strip().decode('UTF-8') |
| 112 | + |
| 113 | + if verbose: |
| 114 | + if not shell: |
| 115 | + command = ' '.join(command) |
| 116 | + print('run:\n\tcmd = {}\n\tret = {}\n\tstdout = {}\n\tstderr = {}\n'.format( |
| 117 | + command, ret, out, err)) |
| 118 | + |
| 119 | + return ret, out, err |
| 120 | + |
| 121 | +def main(args): |
| 122 | + for kver in args.versions: |
| 123 | + print('Building version table for kernel {}'.format(kver)) |
| 124 | + |
| 125 | + checkout_cmd = 'cd {};git checkout v{}'.format(args.kernelpath, kver) |
| 126 | + ret, out, err = run(checkout_cmd, shell=True) |
| 127 | + if ret != 0: |
| 128 | + raise KeyError('Failed to checkout v{}: {}'.format(kver, ret)) |
| 129 | + |
| 130 | + update_cmd = 'cd {};bash scripts/update-tables.sh {}'.format( |
| 131 | + args.datapath, args.kernelpath) |
| 132 | + ret, out, err = run(update_cmd, shell=True) |
| 133 | + if ret != 0: |
| 134 | + raise RuntimeError('Failed to update tables: {}'.format(ret)) |
| 135 | + |
| 136 | + src_path = os.path.join(args.datapath, 'data/tables') |
| 137 | + dest_path = os.path.join(os.getcwd(), 'tables-{}'.format(kver)) |
| 138 | + cp_cmd = 'cp -r {} {}'.format(src_path, dest_path) |
| 139 | + ret, out, err = run(cp_cmd, shell=True) |
| 140 | + if ret != 0: |
| 141 | + raise RuntimeError('Table copy failed: {}'.format(ret)) |
| 142 | + |
| 143 | +if __name__ == '__main__': |
| 144 | + args = parse_args() |
| 145 | + main(args) |
0 commit comments