Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,105 @@ base, and can be enabled via the "--enable-code-coverage" configure flag and
the "check-code-coverage" make target. Additional details on generating code
coverage information can be found in the .travis.yml file.

## How to Update the syscalls.csv Table

*** NOTE - This currently can only be done on Ubuntu ***

1. Install dependencies

In addition to the normal libseccomp package dependencies, the following
packages must also be installed:
```
apt install libc6-dev-x32
```

1. Download source packages

Download the following source packages:
```
git clone https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
git clone https://github.com/hrw/syscalls-table.git
git clone git@github.com:<yourrepo>/libseccomp.git
```

1. Add new kernel version enumerations

The first line of [src/syscalls.csv](https://github.com/seccomp/libseccomp/blob/main/src/syscalls.csv)
contains the newest kernel version known by libseccomp. Add new kernel
version enumerations to the end of the `enum scmp_kver` enumeration in
[seccomp-kvers.h](https://github.com/seccomp/libseccomp/blob/main/include/seccomp-kvers.h).

Optional - Add new kernel versions to the `kernel_versions` list in
[arch-build-kver-tables.py](https://github.com/seccomp/libseccomp/blob/main/src/arch-build-kver-tables.py).

1. Build the table(s) of architectures, syscalls, and syscall numbers

Using the [syscalls-table](https://github.com/hrw/syscalls-table) tool,
build the tables of architectures, syscalls, and syscall numbers for the
new kernel versions.

```
cd libseccomp
./src/arch-build-kver-tables.py -d ../syscalls-table -k ../linux -V [Kernel Version(s)]

# example:
./src/arch-build-kver-tables.py -d ../syscalls-table -k ../linux -V 6.14,6.15,6.16,6.17,6.18,6.19,7.0-rc7
```

1. Add the tables to syscalls.csv

Parse the tables generated in the previous step and add the data to
syscalls.csv.

```
./src/arch-update-syscalls-csv.py -a -d ./ -k ../linux -c src/syscalls.csv -V [Kernel Version(s)]

# example
./src/arch-update-syscalls-csv.py -a -d ./ -k ../linux -c src/syscalls.csv -V 6.14,6.15,6.16,6.17,6.18,6.19,7.0-rc7
```

1. Update seccomp-syscalls.h with new syscalls

Run `cd src && ./arch-syscall-check` to determine if any new syscalls were
added and if they require __PNR and/or __SNR definitions. If this tool
identifies missing definitions, add them to
[include/seccomp-syscalls.h](https://github.com/seccomp/libseccomp/blob/main/include/seccomp-syscalls.h). [Here](https://github.com/seccomp/libseccomp/commit/f01e67509e45c672f4bdd643d94d90867cc19d90)
is an example of the syscalls that were added to kernel version v6.12.


1. Build the legacy syscalls.csv table (optional but recommended)

Prior to tracking the kernel version where syscalls were added, libseccomp
employed internal tools to build the syscalls.csv table. These tools can
be used to validate the syscall numbers and their architectures. Note that
they cannot be used to validate the kernel version number.

```
./autogen.sh && ./configure --enable-python && make check-build

cd src
make arch-syscall-dump
./arch-syscall-validate -c syscalls-prev.csv ../../linux/
```

1. Compare CSVs

Compare the checked-in (HEAD) CSV with the newly-generated syscalls.csv.
Verify the following:
* All new syscall names were properly added
* If a syscall number changed, it should only have transitioned from `PNR`
to a valid number. If a number changed for an architecture, verify that
its associated kernel version is correct
* No syscall rows were deleted

If you built `syscalls-prev.csv` in the previous step, do the same comparisons
as outlined above. Again, note that `syscalls-prev.csv` does not contain
kernel version information, so only the syscall names, syscall numbers, and
architectures can be verified.

There are many tools to compare CSVs. This [tool](https://www.textcompare.org/csv/)
has been especially useful.

## Explain Your Work

At the top of every patch you should include a description of the problem you
Expand Down
3 changes: 3 additions & 0 deletions include/seccomp-kvers.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,8 @@ enum scmp_kver {
SCMP_KV_6_15 = 78,
SCMP_KV_6_16 = 79,
SCMP_KV_6_17 = 80,
SCMP_KV_6_18 = 81,
SCMP_KV_6_19 = 82,
SCMP_KV_7_0 = 83,
__SCMP_KV_MAX,
};
18 changes: 18 additions & 0 deletions include/seccomp-syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,9 @@
#define __PNR_getpagesize -10249
#define __PNR_riscv_hwprobe -10250
#define __PNR_uretprobe -10251
#define __PNR_uprobe -10252
#define __PNR_rseq_slice_yield -10253
#define __PNR_listns -10254

/*
* libseccomp syscall definitions
Expand Down Expand Up @@ -648,6 +651,9 @@

#define __SNR_fgetxattr __NR_fgetxattr

#define __SNR_file_getattr __NR_file_getattr
#define __SNR_file_setattr __NR_file_setattr

#define __SNR_finit_module __NR_finit_module

#define __SNR_flistxattr __NR_flistxattr
Expand Down Expand Up @@ -1082,6 +1088,8 @@

#define __SNR_listmount __NR_listmount

#define __SNR_listns __NR_listns

#define __SNR_listxattr __NR_listxattr

#define __SNR_listxattrat __NR_listxattrat
Expand Down Expand Up @@ -1356,6 +1364,8 @@
#define __SNR_open_tree __PNR_open_tree
#endif

#define __SNR_open_tree_attr __NR_open_tree_attr

#define __SNR_openat __NR_openat

#define __SNR_openat2 __NR_openat2
Expand Down Expand Up @@ -1614,6 +1624,8 @@
#define __SNR_rseq __PNR_rseq
#endif

#define __SNR_rseq_slice_yield __NR_rseq_slice_yield

#define __SNR_rt_sigaction __NR_rt_sigaction

#define __SNR_rt_sigpending __NR_rt_sigpending
Expand Down Expand Up @@ -2304,6 +2316,12 @@

#define __SNR_unshare __NR_unshare

#ifdef __NR_uprobe
#define __SNR_uprobe __NR_uprobe
#else
#define __SNR_uprobe __PNR_uprobe
#endif

#ifdef __NR_uretprobe
#define __SNR_uretprobe __NR_uretprobe
#else
Expand Down
11 changes: 8 additions & 3 deletions src/arch-build-kver-tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#######################################################

from subprocess import TimeoutExpired
from pathlib import Path
import subprocess
import argparse
import os
Expand All @@ -43,7 +44,7 @@
'5.11', '5.12', '5.13', '5.14', '5.15', '5.16', '5.17',
'5.18', '5.19', '6.0', '6.1', '6.2', '6.3', '6.4', '6.5',
'6.6', '6.7', '6.8', '6.9', '6.10', '6.11', '6.12',
'6.13', '6.14', '6.15', '6.16', '6.17']
'6.13', '6.14', '6.15', '6.16', '6.17', '6.18', '6.19', '7.0']

def parse_args():
parser = argparse.ArgumentParser('Script to populate the syscalls.csv kernel versions',
Expand All @@ -66,6 +67,10 @@ def parse_args():
else:
args.versions = args.versions.split(',')

# Convert to absolute paths
args.datapath = Path(args.datapath).resolve()
args.kernelpath = Path(args.kernelpath).resolve()

return args

def run(command, verbose=False, shell=False, timeout=None):
Expand Down Expand Up @@ -135,10 +140,10 @@ def main(args):

src_path = os.path.join(args.datapath, 'data/tables')
dest_path = os.path.join(os.getcwd(), 'tables-{}'.format(kver))
cp_cmd = 'cp -r {} {}'.format(src_path, dest_path)
cp_cmd = 'cp -r {}/. {}'.format(src_path, dest_path)
ret, out, err = run(cp_cmd, shell=True)
if ret != 0:
raise RuntimeError('Table copy failed: {}'.format(ret))
raise RuntimeError('Table copy failed: {}'.format(err))

if __name__ == '__main__':
args = parse_args()
Expand Down
29 changes: 24 additions & 5 deletions src/arch-update-syscalls-csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
# along with this library; if not, see <http://www.gnu.org/licenses>.
#

from pathlib import Path
import subprocess
import datetime
import argparse
Expand All @@ -36,7 +37,7 @@
ignore_syscall_list = [
'arc_gettls', 'arc_settls', 'arc_usr_cmpxchg', 'bfin_spinlock',
'cache_sync', 'clone2', 'cmpxchg_badaddr', 'dipc', 'dma_memcpy',
'exec_with_loader', 'execv', 'file_getattr', 'file_setattr',
'exec_with_loader', 'execv',
'flush_cache', 'fp_udfiex_crtl', 'getdomainname', 'getdtablesize',
'gethostname', 'getunwind', 'getxgid', 'getxpid', 'getxuid',
'kern_features', 'llseek', 'madvise1', 'memory_ordering', 'metag_get_tls',
Expand Down Expand Up @@ -79,6 +80,10 @@ def parse_args():
args = parser.parse_args()
args.versions = args.versions.split(',')

# Convert to absolute paths
args.datapath = Path(args.datapath).resolve()
args.kernelpath = Path(args.kernelpath).resolve()

return args

def run(command, verbose=False, shell=False, timeout=None):
Expand Down Expand Up @@ -182,18 +187,25 @@ def parse_syscalls_csv(args):

def insert_new_syscall(syscalls, syscall_name, column_cnt):
inserted = False
new_row = list()

for i in range(0, column_cnt):
if (i % 2) == 0:
new_row.append('PNR')
else:
new_row.append('SCMP_KV_UNDEF')

for syscall in syscalls:
if syscall_name < syscall:
idx = list(syscalls.keys()).index(syscall)
syscalls_list = list(syscalls.items())
syscalls_list.insert(idx, (syscall_name, ['PNR'] * column_cnt))
syscalls_list.insert(idx, (syscall_name, new_row))
syscalls = dict(syscalls_list)
inserted = True
break

if not inserted:
syscalls[syscall_name] = ['PNR'] * column_cnt
syscalls[syscall_name] = new_row

return syscalls

Expand Down Expand Up @@ -290,8 +302,15 @@ def update_syscalls_dict(args, columns, syscalls, kver):
format(syscall_name, column, kver))

syscalls[syscall_name][col_idx] = str(syscall_num)
maj = kver.split('.')[0]
mnr = kver.split('.')[1]

if kver.find('-rc') > 0:
# Remove trailing release candidate tags
tmp_kver = kver.split('-')[0]
else:
tmp_kver = kver

maj = tmp_kver.split('.')[0]
mnr = tmp_kver.split('.')[1]
syscalls[syscall_name][col_idx + 1] = \
'SCMP_KV_{}_{}'.format(maj, mnr)

Expand Down
Loading
Loading