mirror of
https://github.com/systemd/systemd
synced 2025-10-07 20:54:45 +02:00
Compare commits
59 Commits
7aefb194e7
...
869b44e0f7
Author | SHA1 | Date | |
---|---|---|---|
![]() |
869b44e0f7 | ||
![]() |
78738adf88 | ||
![]() |
4d7851380a | ||
![]() |
7b869ff949 | ||
![]() |
369f311686 | ||
![]() |
b1ce0a2b50 | ||
![]() |
531e6a2091 | ||
![]() |
0939d5c360 | ||
![]() |
1d81c3a74e | ||
![]() |
c35606b272 | ||
![]() |
3fc2a44043 | ||
![]() |
543a48b653 | ||
![]() |
da522c9921 | ||
![]() |
2b912d2066 | ||
![]() |
1a60b97524 | ||
![]() |
98751cf16e | ||
![]() |
090c3f924c | ||
![]() |
a1518f0a94 | ||
![]() |
1e29a967c7 | ||
![]() |
683efcf649 | ||
![]() |
4d000c4853 | ||
![]() |
ab1333b2b7 | ||
![]() |
bdfb884237 | ||
![]() |
a4a6e21673 | ||
![]() |
661b5bfd21 | ||
![]() |
86c4e42380 | ||
![]() |
0e0b482a71 | ||
![]() |
d38f87c56c | ||
![]() |
31b7616420 | ||
![]() |
628f45f4a3 | ||
![]() |
99ae2ae328 | ||
![]() |
878fa7d26e | ||
![]() |
0c0b4d544c | ||
![]() |
b3337feb55 | ||
![]() |
52fe0a490d | ||
![]() |
49bdc8b1e8 | ||
![]() |
d6b3793704 | ||
![]() |
054464ad52 | ||
![]() |
390097724b | ||
![]() |
470da65110 | ||
![]() |
d5f4bd3700 | ||
![]() |
e3fef210c8 | ||
![]() |
fe3f2ac073 | ||
![]() |
5dc3096efb | ||
![]() |
79eec46dfd | ||
![]() |
89701e02ac | ||
![]() |
303d1b6b57 | ||
![]() |
712f763036 | ||
![]() |
545fde151a | ||
![]() |
afa9992429 | ||
![]() |
a5d8520f86 | ||
![]() |
84c05ec632 | ||
![]() |
3484af2800 | ||
![]() |
5a1cb174f8 | ||
![]() |
204e3cb6c8 | ||
![]() |
7f76ff2821 | ||
![]() |
a4488ae6ae | ||
![]() |
3800adc9e5 | ||
![]() |
24a14e9050 |
16
.github/workflows/coverage.yml
vendored
16
.github/workflows/coverage.yml
vendored
@ -25,7 +25,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
- uses: systemd/mkosi@0d1143150835b21c1bfe64428df5f45b558280b1
|
||||
- uses: systemd/mkosi@184472f0f1f831ca29953546ec01fd941ff763a6
|
||||
|
||||
# Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space
|
||||
# immediately, we remove the files in the background. However, we first move them to a different location
|
||||
@ -83,22 +83,22 @@ jobs:
|
||||
run: mkosi summary
|
||||
|
||||
- name: Build tools tree
|
||||
run: sudo mkosi -f sandbox -- true
|
||||
run: sudo mkosi -f box -- true
|
||||
|
||||
- name: Configure meson
|
||||
run: |
|
||||
sudo mkosi sandbox -- \
|
||||
sudo mkosi box -- \
|
||||
meson setup \
|
||||
--buildtype=debugoptimized \
|
||||
build
|
||||
|
||||
- name: Build image
|
||||
run: sudo mkosi sandbox -- meson compile -C build mkosi
|
||||
run: sudo mkosi box -- meson compile -C build mkosi
|
||||
|
||||
- name: Initial coverage report
|
||||
run: |
|
||||
sudo mkdir -p build/test/coverage
|
||||
sudo mkosi sandbox -- \
|
||||
sudo mkosi box -- \
|
||||
lcov \
|
||||
--directory build/mkosi.builddir/arch~rolling~x86-64 \
|
||||
--capture \
|
||||
@ -115,7 +115,7 @@ jobs:
|
||||
# --preserve-env makes sure all the github actions environment variables are propagated which are
|
||||
# used in integration-test-wrapper.py to construct the `gh` command line to download the journals
|
||||
# of failed tests.
|
||||
sudo --preserve-env mkosi sandbox -- \
|
||||
sudo --preserve-env mkosi box -- \
|
||||
env \
|
||||
TEST_RUNNER=ubuntu-24.04 \
|
||||
meson test \
|
||||
@ -147,10 +147,10 @@ jobs:
|
||||
lcov_args+=(--add-tracefile "${file}")
|
||||
done < <(find build/test/coverage -name "TEST-*.coverage-info")
|
||||
|
||||
sudo mkosi sandbox -- lcov --ignore-errors inconsistent,inconsistent "${lcov_args[@]}" --output-file build/test/coverage/everything.coverage-info
|
||||
sudo mkosi box -- lcov --ignore-errors inconsistent,inconsistent "${lcov_args[@]}" --output-file build/test/coverage/everything.coverage-info
|
||||
|
||||
- name: List coverage report
|
||||
run: sudo mkosi sandbox -- lcov --ignore-errors inconsistent,inconsistent --list build/test/coverage/everything.coverage-info
|
||||
run: sudo mkosi box -- lcov --ignore-errors inconsistent,inconsistent --list build/test/coverage/everything.coverage-info
|
||||
|
||||
- name: Coveralls
|
||||
uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b
|
||||
|
24
.github/workflows/linter.yml
vendored
24
.github/workflows/linter.yml
vendored
@ -38,10 +38,10 @@ jobs:
|
||||
LINTER_RULES_PATH: .github/linters
|
||||
GITHUB_ACTIONS_CONFIG_FILE: actionlint.yml
|
||||
|
||||
- uses: systemd/mkosi@0d1143150835b21c1bfe64428df5f45b558280b1
|
||||
- uses: systemd/mkosi@184472f0f1f831ca29953546ec01fd941ff763a6
|
||||
|
||||
- name: Check that tabs are not used in Python code
|
||||
run: sh -c '! git grep -P "\\t" -- src/basic/generate-bpf-delegate-configs.py src/boot/generate-hwids-section.py src/ukify/ukify.py test/integration-tests/integration-test-wrapper.py'
|
||||
run: sh -c '! git grep -P "\\t" -- src/core/generate-bpf-delegate-configs.py src/boot/generate-hwids-section.py src/ukify/ukify.py test/integration-tests/integration-test-wrapper.py'
|
||||
|
||||
- name: Build tools tree
|
||||
run: |
|
||||
@ -51,29 +51,29 @@ jobs:
|
||||
ToolsTreeRelease=rawhide
|
||||
EOF
|
||||
|
||||
mkosi -f sandbox -- true
|
||||
mkosi -f box -- true
|
||||
|
||||
- name: Run mypy
|
||||
run: |
|
||||
mkosi sandbox -- mypy --version
|
||||
mkosi sandbox -- mypy src/basic/generate-bpf-delegate-configs.py src/boot/generate-hwids-section.py src/test/generate-sym-test.py src/ukify/ukify.py test/integration-tests/integration-test-wrapper.py
|
||||
mkosi box -- mypy --version
|
||||
mkosi box -- mypy src/core/generate-bpf-delegate-configs.py src/boot/generate-hwids-section.py src/test/generate-sym-test.py src/ukify/ukify.py test/integration-tests/integration-test-wrapper.py
|
||||
|
||||
- name: Run ruff check
|
||||
run: |
|
||||
mkosi sandbox -- ruff --version
|
||||
mkosi sandbox -- ruff check src/basic/generate-bpf-delegate-configs.py src/boot/generate-hwids-section.py src/test/generate-sym-test.py src/ukify/ukify.py test/integration-tests/integration-test-wrapper.py
|
||||
mkosi box -- ruff --version
|
||||
mkosi box -- ruff check src/core/generate-bpf-delegate-configs.py src/boot/generate-hwids-section.py src/test/generate-sym-test.py src/ukify/ukify.py test/integration-tests/integration-test-wrapper.py
|
||||
|
||||
- name: Run ruff format
|
||||
run: |
|
||||
mkosi sandbox -- ruff --version
|
||||
if ! mkosi sandbox -- ruff format --check src/basic/generate-bpf-delegate-configs.py src/boot/generate-hwids-section.py src/test/generate-sym-test.py src/ukify/ukify.py test/integration-tests/integration-test-wrapper.py
|
||||
mkosi box -- ruff --version
|
||||
if ! mkosi box -- ruff format --check src/core/generate-bpf-delegate-configs.py src/boot/generate-hwids-section.py src/test/generate-sym-test.py src/ukify/ukify.py test/integration-tests/integration-test-wrapper.py
|
||||
then
|
||||
echo "Please run 'ruff format' on the above files or apply the diffs below manually"
|
||||
mkosi sandbox -- ruff format --check --quiet --diff src/basic/generate-bpf-delegate-configs.py src/boot/generate-hwids-section.py src/test/generate-sym-test.py src/ukify/ukify.py test/integration-tests/integration-test-wrapper.py
|
||||
mkosi box -- ruff format --check --quiet --diff src/core/generate-bpf-delegate-configs.py src/boot/generate-hwids-section.py src/test/generate-sym-test.py src/ukify/ukify.py test/integration-tests/integration-test-wrapper.py
|
||||
fi
|
||||
|
||||
- name: Configure meson
|
||||
run: mkosi sandbox -- env CC=clang CXX=clang++ meson setup -Dlocalegen-path=/usr/bin/locale-gen -Dcompat-mutable-uid-boundaries=true build
|
||||
run: mkosi box -- env CC=clang CXX=clang++ meson setup -Dlocalegen-path=/usr/bin/locale-gen -Dcompat-mutable-uid-boundaries=true build
|
||||
|
||||
- name: Run clang-tidy
|
||||
run: mkosi sandbox -- meson test -C build --suite=clang-tidy --print-errorlogs --no-stdsplit
|
||||
run: mkosi box -- meson test -C build --suite=clang-tidy --print-errorlogs --no-stdsplit
|
||||
|
12
.github/workflows/mkosi.yml
vendored
12
.github/workflows/mkosi.yml
vendored
@ -147,7 +147,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
- uses: systemd/mkosi@0d1143150835b21c1bfe64428df5f45b558280b1
|
||||
- uses: systemd/mkosi@184472f0f1f831ca29953546ec01fd941ff763a6
|
||||
|
||||
# Freeing up disk space with rm -rf can take multiple minutes. Since we don't need the extra free space
|
||||
# immediately, we remove the files in the background. However, we first move them to a different location
|
||||
@ -214,21 +214,21 @@ jobs:
|
||||
run: mkosi summary
|
||||
|
||||
- name: Build tools tree
|
||||
run: sudo mkosi -f sandbox -- true
|
||||
run: sudo mkosi -f box -- true
|
||||
|
||||
- name: Configure meson
|
||||
run: |
|
||||
# /usr/sbin/bpftool is completely broken inside containers on Ubuntu which makes meson blow up so
|
||||
# disable the bpf-framework stuff to avoid the issue.
|
||||
# TODO: Drop when we move off Ubuntu Noble as this will be fixed in the next Ubuntu LTS release.
|
||||
sudo mkosi sandbox -- \
|
||||
sudo mkosi box -- \
|
||||
meson setup \
|
||||
--buildtype=debugoptimized \
|
||||
-Dbpf-framework=disabled \
|
||||
build
|
||||
|
||||
- name: Build image
|
||||
run: sudo mkosi sandbox -- meson compile -C build mkosi
|
||||
run: sudo mkosi box -- meson compile -C build mkosi
|
||||
|
||||
- name: Make sure sources weren't polluted by package build scripts
|
||||
run: |
|
||||
@ -243,7 +243,7 @@ jobs:
|
||||
|
||||
- name: Run integration tests
|
||||
run: |
|
||||
if [[ "$(sudo mkosi sandbox -- meson test --help)" == *"--max-lines"* ]]; then
|
||||
if [[ "$(sudo mkosi box -- meson test --help)" == *"--max-lines"* ]]; then
|
||||
MAX_LINES=(--max-lines 300)
|
||||
else
|
||||
MAX_LINES=()
|
||||
@ -256,7 +256,7 @@ jobs:
|
||||
# --preserve-env makes sure all the github actions environment variables are propagated which are
|
||||
# used in integration-test-wrapper.py to construct the `gh` command line to download the journals
|
||||
# of failed tests.
|
||||
sudo --preserve-env mkosi sandbox -- \
|
||||
sudo --preserve-env mkosi box -- \
|
||||
env \
|
||||
TEST_PREFER_QEMU=${{ matrix.vm }} \
|
||||
TEST_NO_QEMU=${{ matrix.no_qemu }} \
|
||||
|
3
NEWS
3
NEWS
@ -135,6 +135,9 @@ CHANGES WITH 258 in spe:
|
||||
incompatible with PrivateDevices= and resulted in automatic extension
|
||||
of the DeviceAllow= list. The latter behaviour has been removed.
|
||||
|
||||
* The command 'journalctl --follow' now exits with success on
|
||||
SIGTERM/SIGINT, or its pipe STDOUT is disconnected.
|
||||
|
||||
Announcements of Future Feature Removals:
|
||||
|
||||
* Support for System V service scripts is deprecated and will be
|
||||
|
@ -20,6 +20,9 @@ There are many, and more are constantly added, so we will not enumerate them all
|
||||
|
||||
The code that is shared between components is split into a few directories, each with a different purpose:
|
||||
|
||||
- 'src/include/uapi/' contains copy of kernel headers we use.
|
||||
'src/include/override/' contains wrappers for libc and kernel headers, to provide several missing symbols.
|
||||
|
||||
- `src/basic/` and `src/fundamental/` — those directories contain code primitives that are used by all other code.
|
||||
`src/fundamental/` is stricter, because it used for EFI and user-space code, while `src/basic/` is only used for user-space code.
|
||||
The code in `src/fundamental/` cannot depend on any other code in the tree, and `src/basic/` can depend only on itself and `src/fundamental/`.
|
||||
@ -43,6 +46,12 @@ Any code that is used only for EFI goes under `src/boot/efi/`, and `src/fundamen
|
||||
|
||||
To summarize:
|
||||
|
||||
`src/include/uapi/`
|
||||
- copy of kernel headers
|
||||
|
||||
`src/include/override/`
|
||||
- wrappers for libc and kernel headers
|
||||
|
||||
`src/fundamental/`
|
||||
- may be used by all code in the tree
|
||||
- may not use any code outside of `src/fundamental/`
|
||||
|
@ -40,16 +40,16 @@ Then, you can build, run and test systemd executables as follows:
|
||||
|
||||
```sh
|
||||
$ mkosi -f genkey # Generate signing keys once.
|
||||
$ mkosi -f sandbox -- meson setup -Dbpf-framework=disabled build # bpftool detection inside mkosi sandbox is broken on Ubuntu Noble and older
|
||||
$ mkosi -f sandbox -- meson compile -C build
|
||||
$ mkosi -f sandbox -- build/systemctl --version
|
||||
$ mkosi -f sandbox -- meson test -C build # Run the unit tests
|
||||
$ mkosi -f box -- meson setup -Dbpf-framework=disabled build # bpftool detection inside mkosi box is broken on Ubuntu Noble and older
|
||||
$ mkosi -f box -- meson compile -C build
|
||||
$ mkosi -f box -- build/systemctl --version
|
||||
$ mkosi -f box -- meson test -C build # Run the unit tests
|
||||
```
|
||||
|
||||
To build and boot an OS image with the latest systemd installed:
|
||||
|
||||
```sh
|
||||
$ mkosi -f sandbox -- meson compile -C build mkosi # (re-)build the OS image
|
||||
$ mkosi -f box -- meson compile -C build mkosi # (re-)build the OS image
|
||||
$ mkosi boot # Boot the image with systemd-nspawn.
|
||||
$ mkosi vm # Boot the image with qemu.
|
||||
```
|
||||
@ -65,8 +65,8 @@ $ cd systemd
|
||||
$ git checkout -b <BRANCH> # where BRANCH is the name of the branch
|
||||
$ $EDITOR src/core/main.c # or wherever you'd like to make your changes
|
||||
$ mkosi -f genkey # Generate signing keys once.
|
||||
$ mkosi -f sandbox -- meson setup build # Set up meson
|
||||
$ mkosi -f sandbox -- meson compile -C build mkosi # (re-)build the test image
|
||||
$ mkosi -f box -- meson setup build # Set up meson
|
||||
$ mkosi -f box -- meson compile -C build mkosi # (re-)build the test image
|
||||
$ mkosi vm # Boot the image in qemu
|
||||
$ git add -p # interactively put together your patch
|
||||
$ git commit # commit it
|
||||
@ -85,7 +85,7 @@ not required to write basic patches.
|
||||
## Building the OS image without a tools tree
|
||||
|
||||
By default, `mkosi` will first build a tools tree and use it build the image and
|
||||
provide the environment for `mkosi sandbox`. To disable the tools tree and use
|
||||
provide the environment for `mkosi box`. To disable the tools tree and use
|
||||
binaries from your host instead, write the following to `mkosi/mkosi.local.conf`:
|
||||
|
||||
```conf
|
||||
@ -311,7 +311,7 @@ To debug systemd-boot in an IDE such as VSCode we can use a launch configuration
|
||||
right in your editor of choice (with the right plugin installed). When using mkosi, we can run clangd in the
|
||||
mkosi tools tree to avoid needing to install clangd on the host machine.
|
||||
|
||||
All that is required is to run `mkosi -f sandbox true` once to make sure the tools tree is available and to modify
|
||||
All that is required is to run `mkosi -f box true` once to make sure the tools tree is available and to modify
|
||||
the path of the clangd binary used by your editor to the `mkosi.clangd` script included in the systemd repository.
|
||||
For example, for VScode, you'd have to add the following to the VSCode workspace settings of the systemd repository:
|
||||
|
||||
@ -329,7 +329,7 @@ When using clangd, it's recommended to setup the build directory containing the
|
||||
compilation database used by clangd to use clang as the compiler as well:
|
||||
|
||||
```sh
|
||||
$ mkosi sandbox -- env CC=clang CXX=clang++ meson setup build
|
||||
$ mkosi box -- env CC=clang CXX=clang++ meson setup build
|
||||
```
|
||||
|
||||
Additionally, the `gensources` target can be used to make sure all generated
|
||||
@ -337,5 +337,5 @@ sources are generated to avoid clangd complaining that these source files don't
|
||||
exist.
|
||||
|
||||
```sh
|
||||
$ mkosi sandbox -- ninja -C build gensources
|
||||
$ mkosi box -- ninja -C build gensources
|
||||
```
|
||||
|
@ -20,9 +20,10 @@ xsltproc_flags = [
|
||||
'--stringparam', 'man.copyright.section.enabled', '0',
|
||||
'--stringparam', 'systemd.version', '@0@'.format(meson.project_version()),
|
||||
'--path',
|
||||
'@0@:@1@:@2@'.format(meson.current_build_dir(),
|
||||
'@0@:@1@:@2@:@3@'.format(meson.current_build_dir(),
|
||||
meson.current_source_dir(),
|
||||
libshared_build_dir)]
|
||||
libshared_build_dir,
|
||||
libcore_build_dir)]
|
||||
|
||||
custom_man_xsl = files('custom-man.xsl')
|
||||
custom_html_xsl = files('custom-html.xsl')
|
||||
@ -35,17 +36,6 @@ custom_entities_ent = custom_target(
|
||||
|
||||
man_page_depends += custom_entities_ent
|
||||
|
||||
generate_bpf_delegate_configs = find_program('../src/basic/generate-bpf-delegate-configs.py')
|
||||
|
||||
bpf_delegate_xml = custom_target(
|
||||
input : files('../src/basic/include/linux/bpf.h'),
|
||||
output : 'bpf-delegate.xml',
|
||||
command : [generate_bpf_delegate_configs,
|
||||
'doc',
|
||||
'@INPUT@'],
|
||||
capture : true)
|
||||
man_page_depends += bpf_delegate_xml
|
||||
|
||||
man_pages = []
|
||||
html_pages = []
|
||||
source_xml_files = []
|
||||
|
@ -2567,7 +2567,7 @@ RestrictNamespaces=~cgroup net</programlisting>
|
||||
available to the unit's processes. When mounting the BPF filesystem with the fsopen() API, four mount
|
||||
options can be specified to set a list of BPF commands, maps, programs and attachment types that are
|
||||
allowed to be used. Processes needs to get a file descriptor for the bpffs mountpoint and use that to
|
||||
get a token which will enable for that user namespace the BPF functionalities choosen upon bpffs mount.
|
||||
get a token which will enable for that user namespace the BPF functionalities chosen upon bpffs mount.
|
||||
A more detailed explanation of the feature can be found in this
|
||||
<ulink url="https://lwn.net/Articles/947173/">LWN post</ulink>.</para>
|
||||
|
||||
|
40
meson.build
40
meson.build
@ -580,7 +580,6 @@ foreach ident : [
|
||||
['fsconfig', '''#include <sys/mount.h>'''], # since glibc-2.36
|
||||
['fsmount', '''#include <sys/mount.h>'''], # since glibc-2.36
|
||||
['fsopen', '''#include <sys/mount.h>'''], # since glibc-2.36
|
||||
['fspick', '''#include <sys/mount.h>'''], # since glibc-2.36
|
||||
['mount_setattr', '''#include <sys/mount.h>'''], # since glibc-2.36
|
||||
['move_mount', '''#include <sys/mount.h>'''], # since glibc-2.36
|
||||
['open_tree', '''#include <sys/mount.h>'''], # since glibc-2.36
|
||||
@ -591,15 +590,17 @@ foreach ident : [
|
||||
['ioprio_get', '''#include <sched.h>'''], # no known header declares ioprio_get
|
||||
['ioprio_set', '''#include <sched.h>'''], # no known header declares ioprio_set
|
||||
['rt_tgsigqueueinfo', '''#include <signal.h>'''], # no known header declares rt_tgsigqueueinfo
|
||||
['open_tree_attr', '''#include <sys/mount.h>'''], # no known header declares open_tree_attr
|
||||
['quotactl_fd', '''#include <sys/quota.h>'''], # no known header declares quotactl_fd
|
||||
['fchmodat2', '''#include <sys/stat.h>'''], # no known header declares fchmodat2
|
||||
['bpf', '''#include <sys/syscall.h>'''], # no known header declares bpf
|
||||
['kcmp', '''#include <sys/syscall.h>'''], # no known header declares kcmp
|
||||
['keyctl', '''#include <sys/syscall.h>'''], # no known header declares keyctl
|
||||
['pivot_root', '''#include <sys/syscall.h>'''], # no known header declares pivot_root
|
||||
['add_key', '''#include <sys/syscall.h>'''], # no known header declares add_key
|
||||
['request_key', '''#include <sys/syscall.h>'''], # no known header declares request_key
|
||||
['setxattrat', '''#include <sys/xattr.h>'''], # no known header declares setxattrat
|
||||
['removexattrat', '''#include <sys/xattr.h>'''], # no known header declares removexattrat
|
||||
['open_tree_attr', '''#include <sys/mount.h>'''], # no known header declares open_tree_attr
|
||||
['pivot_root', '''#include <unistd.h>'''], # no known header declares pivot_root
|
||||
]
|
||||
|
||||
have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE')
|
||||
@ -2008,16 +2009,33 @@ dbus_programs = []
|
||||
# A list of boot stubs. Required for testing of ukify.
|
||||
boot_stubs = []
|
||||
|
||||
# This is similar to system_includes below, but for passing custom_target().
|
||||
system_include_args = [
|
||||
'-isystem', meson.project_build_root() / 'src/include/override',
|
||||
'-isystem', meson.project_source_root() / 'src/include/override',
|
||||
'-isystem', meson.project_build_root() / 'src/include/uapi',
|
||||
'-isystem', meson.project_source_root() / 'src/include/uapi',
|
||||
]
|
||||
|
||||
system_includes = [
|
||||
include_directories(
|
||||
# gcc(1) says
|
||||
# "Directories specified with -isystem options are scanned in left-to-right order",
|
||||
# and meson puts the directories in the reversed order. Hence, a directory with a lower
|
||||
# priority must be listed earlier.
|
||||
'src/include/uapi',
|
||||
'src/include/override',
|
||||
is_system : true,
|
||||
),
|
||||
]
|
||||
|
||||
basic_includes = [
|
||||
include_directories(
|
||||
'src/basic',
|
||||
'src/fundamental',
|
||||
'src/systemd',
|
||||
),
|
||||
include_directories(
|
||||
'src/basic/include',
|
||||
is_system : true,
|
||||
),
|
||||
system_includes,
|
||||
version_include,
|
||||
]
|
||||
|
||||
@ -2039,6 +2057,8 @@ includes = [libsystemd_includes, include_directories('src/shared')]
|
||||
|
||||
subdir('po')
|
||||
subdir('catalog')
|
||||
subdir('src/include')
|
||||
subdir('src/libc')
|
||||
subdir('src/fundamental')
|
||||
subdir('src/basic')
|
||||
subdir('src/libsystemd')
|
||||
@ -2054,7 +2074,8 @@ libsystemd = shared_library(
|
||||
# Make sure our library is never deleted from memory, so that our open logging fds don't leak on dlopen/dlclose cycles.
|
||||
'-z', 'nodelete',
|
||||
'-Wl,--version-script=' + libsystemd_sym_path],
|
||||
link_with : [libbasic_static],
|
||||
link_with : [libc_wrapper_static,
|
||||
libbasic_static],
|
||||
link_whole : [libsystemd_static],
|
||||
dependencies : [librt,
|
||||
threads,
|
||||
@ -2067,6 +2088,7 @@ libsystemd = shared_library(
|
||||
if static_libsystemd != 'false'
|
||||
install_libsystemd_static = static_library(
|
||||
'systemd',
|
||||
libc_wrapper_sources,
|
||||
libsystemd_sources,
|
||||
basic_sources,
|
||||
fundamental_sources,
|
||||
@ -2112,6 +2134,7 @@ libudev = shared_library(
|
||||
if static_libudev != 'false'
|
||||
install_libudev_static = static_library(
|
||||
'udev',
|
||||
libc_wrapper_sources,
|
||||
basic_sources,
|
||||
fundamental_sources,
|
||||
shared_sources,
|
||||
@ -2216,6 +2239,7 @@ nss_template = {
|
||||
# Note that we link NSS modules with '-z nodelete' so that mempools never get orphaned
|
||||
'link_args' : ['-z', 'nodelete'],
|
||||
'link_with' : [
|
||||
libc_wrapper_static,
|
||||
libsystemd_static,
|
||||
libshared_static,
|
||||
libbasic_static,
|
||||
|
@ -9,7 +9,7 @@ else
|
||||
fi
|
||||
|
||||
exec "${SPAWN[@]}" \
|
||||
mkosi sandbox -- \
|
||||
mkosi box -- \
|
||||
clangd \
|
||||
--compile-commands-dir=build \
|
||||
--path-mappings="\
|
||||
|
@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
[Config]
|
||||
MinimumVersion=commit:0d1143150835b21c1bfe64428df5f45b558280b1
|
||||
MinimumVersion=commit:184472f0f1f831ca29953546ec01fd941ff763a6
|
||||
Dependencies=
|
||||
exitrd
|
||||
initrd
|
||||
|
@ -1,8 +1,5 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
[Match]
|
||||
Distribution=arch
|
||||
|
||||
[Build]
|
||||
Environment=
|
||||
GIT_URL=https://gitlab.archlinux.org/archlinux/packaging/packages/systemd.git
|
||||
|
@ -27,6 +27,8 @@ Packages=
|
||||
cryptsetup
|
||||
device-mapper-event
|
||||
device-mapper-multipath
|
||||
dfuzzer
|
||||
erofs-utils
|
||||
git-core
|
||||
glibc-langpack-de
|
||||
glibc-langpack-en
|
||||
@ -38,6 +40,7 @@ Packages=
|
||||
iputils
|
||||
iscsi-initiator-utils
|
||||
kernel-core
|
||||
knot
|
||||
libcap-ng-utils
|
||||
man-db
|
||||
nmap-ncat
|
||||
@ -52,6 +55,7 @@ Packages=
|
||||
python3-pexpect
|
||||
# needed to upgrade and downgrade systemd-ukify in tests
|
||||
python3-zstd
|
||||
qrencode
|
||||
quota
|
||||
rpm
|
||||
softhsm
|
||||
|
11
mkosi/mkosi.conf.d/centos-fedora/mkosi.conf.d/efi.conf
Normal file
11
mkosi/mkosi.conf.d/centos-fedora/mkosi.conf.d/efi.conf
Normal file
@ -0,0 +1,11 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
[Match]
|
||||
Architecture=uefi
|
||||
|
||||
[Content]
|
||||
Packages=
|
||||
sbsigntools
|
||||
|
||||
VolatilePackages=
|
||||
systemd-boot
|
@ -1,9 +1,5 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
[Match]
|
||||
Distribution=|centos
|
||||
Distribution=|fedora
|
||||
|
||||
[Build]
|
||||
Environment=
|
||||
GIT_URL=https://src.fedoraproject.org/rpms/systemd.git
|
||||
|
@ -5,6 +5,7 @@ Distribution=centos
|
||||
|
||||
[Distribution]
|
||||
Release=10
|
||||
Repositories=epel,epel-next
|
||||
|
||||
[Build]
|
||||
Environment=
|
||||
|
@ -1,9 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
[Match]
|
||||
Release=9
|
||||
|
||||
[Distribution]
|
||||
Repositories=
|
||||
epel
|
||||
epel-next
|
@ -1,18 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
[Match]
|
||||
Repositories=epel
|
||||
Architecture=|x86
|
||||
Architecture=|x86-64
|
||||
Architecture=|arm
|
||||
Architecture=|arm64
|
||||
Architecture=|riscv32
|
||||
Architecture=|riscv64
|
||||
Architecture=|loongarch64
|
||||
|
||||
[Content]
|
||||
Packages=
|
||||
sbsigntools
|
||||
|
||||
VolatilePackages=
|
||||
systemd-boot
|
@ -1,12 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
[Match]
|
||||
Repositories=epel
|
||||
|
||||
[Content]
|
||||
Packages=
|
||||
dfuzzer
|
||||
dhcp-server
|
||||
erofs-utils
|
||||
knot
|
||||
qrencode
|
@ -4,13 +4,7 @@
|
||||
Environment=WITH_DEBUG=1
|
||||
|
||||
[Match]
|
||||
Architecture=|x86
|
||||
Architecture=|x86-64
|
||||
Architecture=|arm
|
||||
Architecture=|arm64
|
||||
Architecture=|riscv32
|
||||
Architecture=|riscv64
|
||||
Architecture=|loongarch64
|
||||
Architecture=uefi
|
||||
|
||||
[Content]
|
||||
VolatilePackages=
|
||||
|
@ -2,13 +2,7 @@
|
||||
# sbsigntool exists only on UEFI architectures
|
||||
|
||||
[Match]
|
||||
Architecture=|x86
|
||||
Architecture=|x86-64
|
||||
Architecture=|arm
|
||||
Architecture=|arm64
|
||||
Architecture=|riscv32
|
||||
Architecture=|riscv64
|
||||
Architecture=|loongarch64
|
||||
Architecture=uefi
|
||||
|
||||
[Content]
|
||||
Packages=
|
||||
|
@ -1,9 +1,5 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
[Match]
|
||||
Distribution=|debian
|
||||
Distribution=|ubuntu
|
||||
|
||||
[Build]
|
||||
Environment=
|
||||
GIT_URL=https://salsa.debian.org/systemd-team/systemd.git
|
||||
|
@ -10,15 +10,11 @@ Release=rawhide
|
||||
Packages=
|
||||
btrfs-progs
|
||||
compsize
|
||||
dfuzzer
|
||||
dhcp-server
|
||||
dnf5
|
||||
erofs-utils
|
||||
f2fs-tools
|
||||
# Required for systemd-networkd-tests.py (netdevsim and sch_xxx modules)
|
||||
kernel-modules-extra
|
||||
kernel-modules-internal
|
||||
knot
|
||||
qrencode
|
||||
rpmautospec
|
||||
scsi-target-utils
|
||||
|
@ -1,18 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
[Match]
|
||||
Distribution=fedora
|
||||
Architecture=|x86
|
||||
Architecture=|x86-64
|
||||
Architecture=|arm
|
||||
Architecture=|arm64
|
||||
Architecture=|riscv32
|
||||
Architecture=|riscv64
|
||||
Architecture=|loongarch64
|
||||
|
||||
[Content]
|
||||
Packages=
|
||||
sbsigntools
|
||||
|
||||
VolatilePackages=
|
||||
systemd-boot
|
@ -4,13 +4,7 @@
|
||||
Environment=WITH_DEBUG=1
|
||||
|
||||
[Match]
|
||||
Architecture=|x86
|
||||
Architecture=|x86-64
|
||||
Architecture=|arm
|
||||
Architecture=|arm64
|
||||
Architecture=|riscv32
|
||||
Architecture=|riscv64
|
||||
Architecture=|loongarch64
|
||||
Architecture=uefi
|
||||
|
||||
[Content]
|
||||
VolatilePackages=
|
||||
|
@ -1,14 +1,7 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
[Match]
|
||||
Distribution=opensuse
|
||||
Architecture=|x86
|
||||
Architecture=|x86-64
|
||||
Architecture=|arm
|
||||
Architecture=|arm64
|
||||
Architecture=|riscv32
|
||||
Architecture=|riscv64
|
||||
Architecture=|loongarch64
|
||||
Architecture=uefi
|
||||
|
||||
[Content]
|
||||
VolatilePackages=
|
||||
|
@ -1,8 +1,5 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
[Match]
|
||||
Distribution=opensuse
|
||||
|
||||
[Build]
|
||||
Environment=
|
||||
GIT_URL=https://github.com/bmwiedemann/openSUSE
|
||||
|
@ -1,5 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/magic.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/xattr.h>
|
||||
@ -18,8 +20,6 @@
|
||||
#include "fs-util.h"
|
||||
#include "log.h"
|
||||
#include "login-util.h"
|
||||
#include "missing_fs.h"
|
||||
#include "missing_magic.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "pidref.h"
|
||||
|
@ -126,10 +126,6 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
|
||||
assert(!FLAGS_SET(flags, CHASE_STEP|CHASE_EXTRACT_FILENAME));
|
||||
assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
|
||||
|
||||
/* Either the file may be missing, or we return an fd to the final object, but both make no sense */
|
||||
if (FLAGS_SET(flags, CHASE_NONEXISTENT))
|
||||
assert(!ret_fd);
|
||||
|
||||
if (FLAGS_SET(flags, CHASE_STEP))
|
||||
assert(!ret_fd);
|
||||
|
||||
@ -552,11 +548,13 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
|
||||
}
|
||||
|
||||
if (ret_fd) {
|
||||
/* Return the O_PATH fd we currently are looking to the caller. It can translate it to a
|
||||
* proper fd by opening /proc/self/fd/xyz. */
|
||||
|
||||
assert(fd >= 0);
|
||||
*ret_fd = TAKE_FD(fd);
|
||||
if (exists) {
|
||||
/* Return the O_PATH fd we currently are looking to the caller. It can translate it
|
||||
* to a proper fd by opening /proc/self/fd/xyz. */
|
||||
assert(fd >= 0);
|
||||
*ret_fd = TAKE_FD(fd);
|
||||
} else
|
||||
*ret_fd = -EBADF;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(flags, CHASE_STEP))
|
||||
|
@ -3,19 +3,14 @@
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
cpp="$1"
|
||||
filesystems_gperf="$2"
|
||||
cpp="${1:?}"
|
||||
filesystems_gperf="${2:?}"
|
||||
shift 2
|
||||
|
||||
includes=""
|
||||
for i in "$@"; do
|
||||
includes="$includes -include $i"
|
||||
done
|
||||
|
||||
error=false
|
||||
|
||||
# shellcheck disable=SC2086
|
||||
for fs in $($cpp -dM $includes - </dev/null | \
|
||||
for fs in $($cpp -dM -include linux/magic.h "$@" - </dev/null | \
|
||||
grep -E '_MAGIC' | \
|
||||
grep -vE 'LINUX_MAGIC' | \
|
||||
awk '/^#define[ \t]+[A-Z0-9_]+MAGIC[ \t]+/ { print $2; }'); do
|
||||
|
@ -20,316 +20,24 @@
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
static int files_add(
|
||||
DIR *dir,
|
||||
const char *dirpath,
|
||||
int rfd,
|
||||
const char *root, /* for logging, can be NULL */
|
||||
Hashmap **files,
|
||||
Set **masked,
|
||||
const char *suffix,
|
||||
ConfFilesFlags flags) {
|
||||
ConfFile* conf_file_free(ConfFile *c) {
|
||||
if (!c)
|
||||
return NULL;
|
||||
|
||||
int r;
|
||||
free(c->name);
|
||||
free(c->result);
|
||||
free(c->original_path);
|
||||
free(c->resolved_path);
|
||||
safe_close(c->fd);
|
||||
|
||||
assert(dir);
|
||||
assert(dirpath);
|
||||
assert(rfd >= 0 || rfd == AT_FDCWD);
|
||||
assert(files);
|
||||
assert(masked);
|
||||
|
||||
root = strempty(root);
|
||||
|
||||
FOREACH_DIRENT(de, dir, return log_debug_errno(errno, "Failed to read directory '%s/%s': %m",
|
||||
root, skip_leading_slash(dirpath))) {
|
||||
|
||||
/* Does this match the suffix? */
|
||||
if (suffix && !endswith(de->d_name, suffix))
|
||||
continue;
|
||||
|
||||
/* Has this file already been found in an earlier directory? */
|
||||
if (hashmap_contains(*files, de->d_name)) {
|
||||
log_debug("Skipping overridden file '%s/%s/%s'.",
|
||||
root, skip_leading_slash(dirpath), de->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Has this been masked in an earlier directory? */
|
||||
if ((flags & CONF_FILES_FILTER_MASKED) != 0 && set_contains(*masked, de->d_name)) {
|
||||
log_debug("File '%s/%s/%s' is masked by previous entry.",
|
||||
root, skip_leading_slash(dirpath), de->d_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
_cleanup_free_ char *p = path_join(dirpath, de->d_name);
|
||||
if (!p)
|
||||
return log_oom_debug();
|
||||
|
||||
_cleanup_free_ char *resolved_path = NULL;
|
||||
bool need_stat = (flags & (CONF_FILES_FILTER_MASKED | CONF_FILES_REGULAR | CONF_FILES_DIRECTORY | CONF_FILES_EXECUTABLE)) != 0;
|
||||
struct stat st;
|
||||
|
||||
if (!need_stat || FLAGS_SET(flags, CONF_FILES_FILTER_MASKED_BY_SYMLINK)) {
|
||||
|
||||
/* Even if no verification is requested, let's unconditionally call chaseat(),
|
||||
* to drop unsafe symlinks. */
|
||||
|
||||
r = chaseat(rfd, p, CHASE_AT_RESOLVE_IN_ROOT | CHASE_NONEXISTENT, &resolved_path, /* ret_fd = */ NULL);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to chase '%s/%s', ignoring: %m",
|
||||
root, skip_leading_slash(p));
|
||||
continue;
|
||||
}
|
||||
if (r == 0 && FLAGS_SET(flags, CONF_FILES_FILTER_MASKED_BY_SYMLINK)) {
|
||||
|
||||
/* If the path points to /dev/null in a image or so, then the device node may not exist. */
|
||||
if (path_equal(skip_leading_slash(resolved_path), "dev/null")) {
|
||||
/* Mark this one as masked */
|
||||
r = set_put_strdup(masked, de->d_name);
|
||||
if (r < 0)
|
||||
return log_oom_debug();
|
||||
|
||||
log_debug("File '%s/%s' is a mask (symlink to /dev/null).",
|
||||
root, skip_leading_slash(p));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the flag is set, we need to have stat, hence, skip the entry. */
|
||||
log_debug_errno(SYNTHETIC_ERRNO(ENOENT), "Failed to chase '%s/%s', ignoring: %m",
|
||||
root, skip_leading_slash(p));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (need_stat && fstatat(rfd, resolved_path, &st, AT_SYMLINK_NOFOLLOW) < 0) {
|
||||
log_debug_errno(errno, "Failed to stat '%s/%s', ignoring: %m",
|
||||
root, skip_leading_slash(p));
|
||||
continue;
|
||||
}
|
||||
|
||||
} else {
|
||||
r = chase_and_statat(rfd, p, CHASE_AT_RESOLVE_IN_ROOT, &resolved_path, &st);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to chase and stat '%s/%s', ignoring: %m",
|
||||
root, skip_leading_slash(p));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Is this a masking entry? */
|
||||
if (FLAGS_SET(flags, CONF_FILES_FILTER_MASKED_BY_SYMLINK) && stat_may_be_dev_null(&st)) {
|
||||
/* Mark this one as masked */
|
||||
r = set_put_strdup(masked, de->d_name);
|
||||
if (r < 0)
|
||||
return log_oom_debug();
|
||||
|
||||
log_debug("File '%s/%s' is a mask (symlink to /dev/null).", root, skip_leading_slash(p));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(flags, CONF_FILES_FILTER_MASKED_BY_EMPTY) && stat_is_empty(&st)) {
|
||||
/* Mark this one as masked */
|
||||
r = set_put_strdup(masked, de->d_name);
|
||||
if (r < 0)
|
||||
return log_oom_debug();
|
||||
|
||||
log_debug("File '%s/%s' is a mask (an empty file).", root, skip_leading_slash(p));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(flags, CONF_FILES_REGULAR|CONF_FILES_DIRECTORY)) {
|
||||
if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
|
||||
log_debug("Ignoring '%s/%s', as it is neither a regular file or directory.", root, skip_leading_slash(p));
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
/* Is this node a regular file? */
|
||||
if (FLAGS_SET(flags, CONF_FILES_REGULAR) && !S_ISREG(st.st_mode)) {
|
||||
log_debug("Ignoring '%s/%s', as it is not a regular file.", root, skip_leading_slash(p));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Is this node a directory? */
|
||||
if (FLAGS_SET(flags, CONF_FILES_DIRECTORY) && !S_ISDIR(st.st_mode)) {
|
||||
log_debug("Ignoring '%s/%s', as it is not a directory.", root, skip_leading_slash(p));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Does this node have the executable bit set?
|
||||
* As requested: check if the file is marked executable. Note that we don't check access(X_OK)
|
||||
* here, as we care about whether the file is marked executable at all, and not whether it is
|
||||
* executable for us, because if so, such errors are stuff we should log about. */
|
||||
if (FLAGS_SET(flags, CONF_FILES_EXECUTABLE) && (st.st_mode & 0111) == 0) {
|
||||
log_debug("Ignoring '%s/%s', as it is not marked executable.", root, skip_leading_slash(p));
|
||||
continue;
|
||||
}
|
||||
|
||||
_cleanup_free_ char *n = strdup(de->d_name);
|
||||
if (!n)
|
||||
return log_oom_debug();
|
||||
|
||||
r = hashmap_ensure_put(files, &string_hash_ops_free_free, n, p);
|
||||
if (r < 0) {
|
||||
assert(r == -ENOMEM);
|
||||
return log_oom_debug();
|
||||
}
|
||||
assert(r > 0);
|
||||
|
||||
TAKE_PTR(n);
|
||||
TAKE_PTR(p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return mfree(c);
|
||||
}
|
||||
|
||||
static int copy_and_sort_files_from_hashmap(Hashmap *fh, const char *root, ConfFilesFlags flags, char ***ret) {
|
||||
_cleanup_free_ char **sv = NULL;
|
||||
_cleanup_strv_free_ char **files = NULL;
|
||||
size_t n = 0;
|
||||
int r;
|
||||
void conf_file_free_many(ConfFile **array, size_t n) {
|
||||
FOREACH_ARRAY(i, array, n)
|
||||
conf_file_free(*i);
|
||||
|
||||
assert(ret);
|
||||
|
||||
r = hashmap_dump_sorted(fh, (void***) &sv, /* ret_n = */ NULL);
|
||||
if (r < 0)
|
||||
return log_oom_debug();
|
||||
|
||||
/* The entries in the array given by hashmap_dump_sorted() are still owned by the hashmap. */
|
||||
STRV_FOREACH(s, sv) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
|
||||
if (FLAGS_SET(flags, CONF_FILES_BASENAME)) {
|
||||
r = path_extract_filename(*s, &p);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to extract filename from '%s': %m", *s);
|
||||
} else if (root) {
|
||||
r = chaseat_prefix_root(*s, root, &p);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to prefix '%s' with root '%s': %m", *s, root);
|
||||
}
|
||||
|
||||
if (p)
|
||||
r = strv_consume_with_size(&files, &n, TAKE_PTR(p));
|
||||
else
|
||||
r = strv_extend_with_size(&files, &n, *s);
|
||||
if (r < 0)
|
||||
return log_oom_debug();
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(files);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int insert_replacement(Hashmap **fh, char *filename_replacement, char *resolved_replacement, char **ret) {
|
||||
_cleanup_free_ char *fname = ASSERT_PTR(filename_replacement), *path = ASSERT_PTR(resolved_replacement);
|
||||
int r;
|
||||
|
||||
assert(fh);
|
||||
|
||||
/* This consumes the input filename and path. */
|
||||
|
||||
const char *existing = hashmap_get(*fh, fname);
|
||||
if (existing) {
|
||||
log_debug("An entry with higher priority already exists ('%s' -> '%s'), ignoring the replacement: %s",
|
||||
fname, existing, path);
|
||||
if (ret)
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_cleanup_free_ char *copy = NULL;
|
||||
if (ret) {
|
||||
copy = strdup(path);
|
||||
if (!copy)
|
||||
return log_oom_debug();
|
||||
}
|
||||
|
||||
r = hashmap_ensure_put(fh, &string_hash_ops_free_free, fname, path);
|
||||
if (r < 0) {
|
||||
assert(r == -ENOMEM);
|
||||
return log_oom_debug();
|
||||
}
|
||||
assert(r > 0);
|
||||
|
||||
log_debug("Inserted replacement: '%s' -> '%s'", fname, path);
|
||||
|
||||
TAKE_PTR(fname);
|
||||
TAKE_PTR(path);
|
||||
|
||||
if (ret)
|
||||
*ret = TAKE_PTR(copy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int conf_files_list_impl(
|
||||
const char *suffix,
|
||||
int rfd,
|
||||
const char *root, /* for logging, can be NULL */
|
||||
ConfFilesFlags flags,
|
||||
const char * const *dirs,
|
||||
const char *replacement,
|
||||
Hashmap **ret,
|
||||
char **ret_inserted) {
|
||||
|
||||
_cleanup_hashmap_free_ Hashmap *fh = NULL;
|
||||
_cleanup_set_free_ Set *masked = NULL;
|
||||
int r;
|
||||
|
||||
assert(rfd >= 0 || rfd == AT_FDCWD);
|
||||
assert(ret);
|
||||
|
||||
_cleanup_free_ char *filename_replacement = NULL, *resolved_dirpath_replacement = NULL, *resolved_replacement = NULL, *inserted = NULL;
|
||||
if (replacement) {
|
||||
r = path_extract_filename(replacement, &filename_replacement);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_free_ char *d = NULL;
|
||||
r = path_extract_directory(replacement, &d);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = chaseat(rfd, d, CHASE_AT_RESOLVE_IN_ROOT | CHASE_NONEXISTENT, &resolved_dirpath_replacement, /* ret_fd = */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
resolved_replacement = path_join(resolved_dirpath_replacement, filename_replacement);
|
||||
if (!resolved_replacement)
|
||||
return log_oom_debug();
|
||||
}
|
||||
|
||||
STRV_FOREACH(p, dirs) {
|
||||
_cleanup_closedir_ DIR *dir = NULL;
|
||||
_cleanup_free_ char *path = NULL;
|
||||
|
||||
r = chase_and_opendirat(rfd, *p, CHASE_AT_RESOLVE_IN_ROOT, &path, &dir);
|
||||
if (r < 0) {
|
||||
if (r != -ENOENT)
|
||||
log_debug_errno(r, "Failed to chase and open directory '%s%s', ignoring: %m", strempty(root), *p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (resolved_replacement && path_equal(resolved_dirpath_replacement, path)) {
|
||||
r = insert_replacement(&fh, TAKE_PTR(filename_replacement), TAKE_PTR(resolved_replacement), ret_inserted ? &inserted : NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = files_add(dir, path, rfd, root, &fh, &masked, suffix, flags);
|
||||
if (r == -ENOMEM)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (resolved_replacement) {
|
||||
r = insert_replacement(&fh, TAKE_PTR(filename_replacement), TAKE_PTR(resolved_replacement), ret_inserted ? &inserted : NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(fh);
|
||||
if (ret_inserted)
|
||||
*ret_inserted = TAKE_PTR(inserted);
|
||||
return 0;
|
||||
free(array);
|
||||
}
|
||||
|
||||
static int prepare_dirs(const char *root, char * const *dirs, int *ret_rfd, char **ret_root, char ***ret_dirs) {
|
||||
@ -339,25 +47,27 @@ static int prepare_dirs(const char *root, char * const *dirs, int *ret_rfd, char
|
||||
|
||||
assert(ret_rfd);
|
||||
assert(ret_root);
|
||||
assert(ret_dirs);
|
||||
assert(ret_dirs || strv_isempty(dirs));
|
||||
|
||||
r = empty_or_root_harder_to_null(&root);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to determine if '%s' points to the root directory: %m", strempty(root));
|
||||
|
||||
dirs_abs = strv_copy(dirs);
|
||||
if (!dirs_abs)
|
||||
return log_oom();
|
||||
if (ret_dirs) {
|
||||
dirs_abs = strv_copy(dirs);
|
||||
if (!dirs_abs)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (root) {
|
||||
/* WHen a non-trivial root is specified, we will prefix the result later. Hence, it is not
|
||||
/* When a non-trivial root is specified, we will prefix the result later. Hence, it is not
|
||||
* necessary to modify each config directories here. but needs to normalize the root directory. */
|
||||
r = path_make_absolute_cwd(root, &root_abs);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to make '%s' absolute: %m", root);
|
||||
|
||||
path_simplify(root_abs);
|
||||
} else {
|
||||
} else if (ret_dirs) {
|
||||
/* When an empty root or "/" is specified, we will open "/" below, hence we need to make
|
||||
* each config directory absolute if relative. */
|
||||
r = path_strv_make_absolute_cwd(dirs_abs);
|
||||
@ -371,7 +81,462 @@ static int prepare_dirs(const char *root, char * const *dirs, int *ret_rfd, char
|
||||
|
||||
*ret_rfd = TAKE_FD(rfd);
|
||||
*ret_root = TAKE_PTR(root_abs);
|
||||
*ret_dirs = TAKE_PTR(dirs_abs);
|
||||
if (ret_dirs)
|
||||
*ret_dirs = TAKE_PTR(dirs_abs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int conf_file_prefix_root(ConfFile *c, const char *root) {
|
||||
char *p;
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
|
||||
r = chaseat_prefix_root(c->result, root, &p);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to prefix '%s' with root '%s': %m", c->result, root);
|
||||
free_and_replace(c->result, p);
|
||||
|
||||
r = chaseat_prefix_root(c->resolved_path, root, &p);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to prefix '%s' with root '%s': %m", c->resolved_path, root);
|
||||
free_and_replace(c->resolved_path, p);
|
||||
|
||||
/* Do not use chaseat_prefix_root(), as it is for the result of chaseat(), but the path is not chased. */
|
||||
p = path_join(empty_to_root(root), skip_leading_slash(c->original_path));
|
||||
if (!p)
|
||||
return log_oom_debug();
|
||||
path_simplify(p);
|
||||
free_and_replace(c->original_path, p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int conf_file_new_at(const char *path, int rfd, ChaseFlags chase_flags, ConfFile **ret) {
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(rfd >= 0 || rfd == AT_FDCWD);
|
||||
assert(ret);
|
||||
|
||||
_cleanup_free_ char *root = NULL;
|
||||
if (rfd >= 0 && DEBUG_LOGGING)
|
||||
(void) fd_get_path(rfd, &root);
|
||||
|
||||
_cleanup_(conf_file_freep) ConfFile *c = new(ConfFile, 1);
|
||||
if (!c)
|
||||
return log_oom_debug();
|
||||
|
||||
*c = (ConfFile) {
|
||||
.original_path = strdup(path),
|
||||
.fd = -EBADF,
|
||||
};
|
||||
|
||||
if (!c->original_path)
|
||||
return log_oom_debug();
|
||||
|
||||
r = path_extract_filename(path, &c->name);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to extract filename from '%s': %m", path);
|
||||
|
||||
_cleanup_free_ char *dirpath = NULL, *resolved_dirpath = NULL;
|
||||
r = path_extract_directory(path, &dirpath);
|
||||
if (r < 0 && r != -EDESTADDRREQ)
|
||||
return log_debug_errno(r, "Failed to extract directory from '%s': %m", path);
|
||||
if (r >= 0) {
|
||||
r = chaseat(rfd, dirpath,
|
||||
CHASE_AT_RESOLVE_IN_ROOT | (FLAGS_SET(chase_flags, CHASE_NONEXISTENT) ? CHASE_NONEXISTENT : CHASE_MUST_BE_DIRECTORY),
|
||||
&resolved_dirpath, /* ret_fd = */ NULL);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to chase '%s%s': %m", empty_to_root(root), skip_leading_slash(dirpath));
|
||||
}
|
||||
|
||||
c->result = path_join(resolved_dirpath, c->name);
|
||||
if (!c->result)
|
||||
return log_oom_debug();
|
||||
|
||||
r = chaseat(rfd, c->result, CHASE_AT_RESOLVE_IN_ROOT | chase_flags, &c->resolved_path, &c->fd);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to chase '%s%s': %m", empty_to_root(root), skip_leading_slash(c->original_path));
|
||||
|
||||
if (c->fd >= 0 && fstat(c->fd, &c->st) < 0)
|
||||
return log_debug_errno(r, "Failed to stat '%s%s': %m", empty_to_root(root), skip_leading_slash(c->resolved_path));
|
||||
|
||||
*ret = TAKE_PTR(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int conf_file_new(const char *path, const char *root, ChaseFlags chase_flags, ConfFile **ret) {
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert((chase_flags & (CHASE_PREFIX_ROOT | CHASE_STEP)) == 0);
|
||||
assert(ret);
|
||||
|
||||
_cleanup_free_ char *root_abs = NULL;
|
||||
_cleanup_close_ int rfd = -EBADF;
|
||||
r = prepare_dirs(root, /* dirs = */ NULL, &rfd, &root_abs, /* ret_dirs = */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_free_ char *path_abs = NULL;
|
||||
if (!root_abs) {
|
||||
r = path_make_absolute_cwd(path, &path_abs);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to make '%s' absolute: %m", path);
|
||||
|
||||
path = path_abs;
|
||||
}
|
||||
|
||||
_cleanup_(conf_file_freep) ConfFile *c = NULL;
|
||||
r = conf_file_new_at(path, rfd, chase_flags, &c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = conf_file_prefix_root(c, root_abs);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
conf_file_hash_ops,
|
||||
char, string_hash_func, string_compare_func,
|
||||
ConfFile, conf_file_free);
|
||||
|
||||
static int files_add(
|
||||
DIR *dir,
|
||||
const char *original_dirpath,
|
||||
const char *resolved_dirpath,
|
||||
int rfd,
|
||||
const char *root, /* for logging, can be NULL */
|
||||
Hashmap **files,
|
||||
Set **masked,
|
||||
const char *suffix,
|
||||
ConfFilesFlags flags) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(dir);
|
||||
assert(original_dirpath);
|
||||
assert(resolved_dirpath);
|
||||
assert(rfd >= 0 || rfd == AT_FDCWD);
|
||||
assert(files);
|
||||
assert(masked);
|
||||
|
||||
root = strempty(root);
|
||||
|
||||
FOREACH_DIRENT(de, dir, return log_debug_errno(errno, "Failed to read directory '%s/%s': %m",
|
||||
root, skip_leading_slash(original_dirpath))) {
|
||||
|
||||
_cleanup_free_ char *original_path = path_join(original_dirpath, de->d_name);
|
||||
if (!original_path)
|
||||
return log_oom_debug();
|
||||
|
||||
/* Does this match the suffix? */
|
||||
if (suffix && !endswith(de->d_name, suffix)) {
|
||||
log_debug("Skipping file '%s/%s' with unexpected suffix.", root, skip_leading_slash(original_path));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Has this file already been found in an earlier directory? */
|
||||
if (hashmap_contains(*files, de->d_name)) {
|
||||
log_debug("Skipping overridden file '%s/%s'.", root, skip_leading_slash(original_path));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Has this been masked in an earlier directory? */
|
||||
if ((flags & CONF_FILES_FILTER_MASKED) != 0 && set_contains(*masked, de->d_name)) {
|
||||
log_debug("File '%s/%s' is masked by previous entry.", root, skip_leading_slash(original_path));
|
||||
continue;
|
||||
}
|
||||
|
||||
_cleanup_free_ char *p = path_join(resolved_dirpath, de->d_name);
|
||||
if (!p)
|
||||
return log_oom_debug();
|
||||
|
||||
_cleanup_free_ char *resolved_path = NULL;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
bool need_stat = (flags & (CONF_FILES_FILTER_MASKED | CONF_FILES_REGULAR | CONF_FILES_DIRECTORY | CONF_FILES_EXECUTABLE)) != 0;
|
||||
ChaseFlags chase_flags = CHASE_AT_RESOLVE_IN_ROOT;
|
||||
|
||||
if (!need_stat || FLAGS_SET(flags, CONF_FILES_FILTER_MASKED_BY_SYMLINK))
|
||||
/* Even if no verification is requested, let's unconditionally call chaseat(),
|
||||
* to drop unsafe symlinks. */
|
||||
chase_flags |= CHASE_NONEXISTENT;
|
||||
|
||||
r = chaseat(rfd, p, chase_flags, &resolved_path, &fd);
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to chase '%s/%s', ignoring: %m",
|
||||
root, skip_leading_slash(original_path));
|
||||
continue;
|
||||
}
|
||||
if (r == 0) {
|
||||
if (FLAGS_SET(flags, CONF_FILES_FILTER_MASKED_BY_SYMLINK)) {
|
||||
|
||||
/* If the path points to /dev/null in a image or so, then the device node may not exist. */
|
||||
if (path_equal(skip_leading_slash(resolved_path), "dev/null")) {
|
||||
/* Mark this one as masked */
|
||||
r = set_put_strdup(masked, de->d_name);
|
||||
if (r < 0)
|
||||
return log_oom_debug();
|
||||
|
||||
log_debug("File '%s/%s' is a mask (symlink to /dev/null).",
|
||||
root, skip_leading_slash(original_path));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (need_stat) {
|
||||
/* If we need to have stat, skip the entry. */
|
||||
log_debug_errno(SYNTHETIC_ERRNO(ENOENT), "Failed to chase '%s/%s', ignoring: %m",
|
||||
root, skip_leading_slash(original_path));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Even if we do not need stat, let's take stat now. The caller may use the info later. */
|
||||
struct stat st = {};
|
||||
if (fd >= 0 && fstat(fd, &st) < 0) {
|
||||
log_debug_errno(errno, "Failed to stat '%s/%s', ignoring: %m",
|
||||
root, skip_leading_slash(original_path));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Is this a masking entry? */
|
||||
if (FLAGS_SET(flags, CONF_FILES_FILTER_MASKED_BY_SYMLINK) && stat_may_be_dev_null(&st)) {
|
||||
/* Mark this one as masked */
|
||||
r = set_put_strdup(masked, de->d_name);
|
||||
if (r < 0)
|
||||
return log_oom_debug();
|
||||
|
||||
log_debug("File '%s/%s' is a mask (symlink to /dev/null).", root, skip_leading_slash(original_path));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(flags, CONF_FILES_FILTER_MASKED_BY_EMPTY) && stat_is_empty(&st)) {
|
||||
/* Mark this one as masked */
|
||||
r = set_put_strdup(masked, de->d_name);
|
||||
if (r < 0)
|
||||
return log_oom_debug();
|
||||
|
||||
log_debug("File '%s/%s' is a mask (an empty file).", root, skip_leading_slash(original_path));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FLAGS_SET(flags, CONF_FILES_REGULAR|CONF_FILES_DIRECTORY)) {
|
||||
if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
|
||||
log_debug("Ignoring '%s/%s', as it is neither a regular file or directory.", root, skip_leading_slash(original_path));
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
/* Is this node a regular file? */
|
||||
if (FLAGS_SET(flags, CONF_FILES_REGULAR) && !S_ISREG(st.st_mode)) {
|
||||
log_debug("Ignoring '%s/%s', as it is not a regular file.", root, skip_leading_slash(original_path));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Is this node a directory? */
|
||||
if (FLAGS_SET(flags, CONF_FILES_DIRECTORY) && !S_ISDIR(st.st_mode)) {
|
||||
log_debug("Ignoring '%s/%s', as it is not a directory.", root, skip_leading_slash(original_path));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Does this node have the executable bit set?
|
||||
* As requested: check if the file is marked executable. Note that we don't check access(X_OK)
|
||||
* here, as we care about whether the file is marked executable at all, and not whether it is
|
||||
* executable for us, because if so, such errors are stuff we should log about. */
|
||||
if (FLAGS_SET(flags, CONF_FILES_EXECUTABLE) && (st.st_mode & 0111) == 0) {
|
||||
log_debug("Ignoring '%s/%s', as it is not marked executable.", root, skip_leading_slash(original_path));
|
||||
continue;
|
||||
}
|
||||
|
||||
_cleanup_(conf_file_freep) ConfFile *c = new(ConfFile, 1);
|
||||
if (!c)
|
||||
return log_oom_debug();
|
||||
|
||||
*c = (ConfFile) {
|
||||
.name = strdup(de->d_name),
|
||||
.result = TAKE_PTR(p),
|
||||
.original_path = TAKE_PTR(original_path),
|
||||
.resolved_path = TAKE_PTR(resolved_path),
|
||||
.fd = TAKE_FD(fd),
|
||||
.st = st,
|
||||
};
|
||||
|
||||
if (!c->name)
|
||||
return log_oom_debug();
|
||||
|
||||
r = hashmap_ensure_put(files, &conf_file_hash_ops, c->name, c);
|
||||
if (r < 0) {
|
||||
assert(r == -ENOMEM);
|
||||
return log_oom_debug();
|
||||
}
|
||||
assert(r > 0);
|
||||
|
||||
TAKE_PTR(c);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dump_files(Hashmap *fh, const char *root, ConfFile ***ret_files, size_t *ret_n_files) {
|
||||
ConfFile **files = NULL;
|
||||
size_t n_files = 0;
|
||||
int r;
|
||||
|
||||
CLEANUP_ARRAY(files, n_files, conf_file_free_many);
|
||||
|
||||
assert(ret_files);
|
||||
assert(ret_n_files);
|
||||
|
||||
/* The entries in the array given by hashmap_dump_sorted() are still owned by the hashmap. */
|
||||
r = hashmap_dump_sorted(fh, (void***) &files, &n_files);
|
||||
if (r < 0)
|
||||
return log_oom_debug();
|
||||
|
||||
/* Hence, we need to remove them from the hashmap. */
|
||||
FOREACH_ARRAY(i, files, n_files)
|
||||
assert_se(hashmap_remove(fh, (*i)->name) == *i);
|
||||
|
||||
if (root)
|
||||
FOREACH_ARRAY(i, files, n_files) {
|
||||
r = conf_file_prefix_root(*i, root);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*ret_files = TAKE_PTR(files);
|
||||
*ret_n_files = n_files;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int copy_and_sort_files_from_hashmap(Hashmap *fh, const char *root, ConfFilesFlags flags, char ***ret) {
|
||||
_cleanup_strv_free_ char **results = NULL;
|
||||
_cleanup_free_ ConfFile **files = NULL;
|
||||
size_t n_files = 0, n_results = 0;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* The entries in the array given by hashmap_dump_sorted() are still owned by the hashmap.
|
||||
* Hence, do not use conf_file_free_many() for 'entries' */
|
||||
r = hashmap_dump_sorted(fh, (void***) &files, &n_files);
|
||||
if (r < 0)
|
||||
return log_oom_debug();
|
||||
|
||||
FOREACH_ARRAY(i, files, n_files) {
|
||||
ConfFile *c = *i;
|
||||
|
||||
if (FLAGS_SET(flags, CONF_FILES_BASENAME))
|
||||
r = strv_extend_with_size(&results, &n_results, c->name);
|
||||
else if (root) {
|
||||
char *p;
|
||||
|
||||
r = chaseat_prefix_root(c->result, root, &p);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to prefix '%s' with root '%s': %m", c->result, root);
|
||||
|
||||
r = strv_consume_with_size(&results, &n_results, TAKE_PTR(p));
|
||||
} else
|
||||
r = strv_extend_with_size(&results, &n_results, c->result);
|
||||
if (r < 0)
|
||||
return log_oom_debug();
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(results);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int insert_replacement(Hashmap **fh, ConfFile *replacement, const ConfFile **ret) {
|
||||
_cleanup_(conf_file_freep) ConfFile *c = ASSERT_PTR(replacement);
|
||||
int r;
|
||||
|
||||
assert(fh);
|
||||
assert(ret);
|
||||
|
||||
/* This consumes the input ConfFile. */
|
||||
|
||||
ConfFile *existing = hashmap_get(*fh, c->name);
|
||||
if (existing) {
|
||||
log_debug("An entry with higher priority '%s' -> '%s' already exists, ignoring the replacement: %s",
|
||||
existing->name, existing->result, c->original_path);
|
||||
*ret = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = hashmap_ensure_put(fh, &conf_file_hash_ops, c->name, c);
|
||||
if (r < 0) {
|
||||
assert(r == -ENOMEM);
|
||||
return log_oom_debug();
|
||||
}
|
||||
assert(r > 0);
|
||||
|
||||
log_debug("Inserted replacement: '%s' -> '%s'", c->name, c->result);
|
||||
|
||||
*ret = TAKE_PTR(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int conf_files_list_impl(
|
||||
const char *suffix,
|
||||
int rfd,
|
||||
const char *root, /* for logging, can be NULL */
|
||||
ConfFilesFlags flags,
|
||||
const char * const *dirs,
|
||||
const char *replacement,
|
||||
Hashmap **ret,
|
||||
const ConfFile **ret_inserted) {
|
||||
|
||||
_cleanup_hashmap_free_ Hashmap *fh = NULL;
|
||||
_cleanup_set_free_ Set *masked = NULL;
|
||||
_cleanup_(conf_file_freep) ConfFile *c = NULL;
|
||||
const ConfFile *inserted = NULL;
|
||||
int r;
|
||||
|
||||
assert(rfd >= 0 || rfd == AT_FDCWD);
|
||||
assert(ret);
|
||||
|
||||
if (replacement) {
|
||||
r = conf_file_new_at(replacement, rfd, CHASE_NONEXISTENT, &c);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
STRV_FOREACH(p, dirs) {
|
||||
_cleanup_closedir_ DIR *dir = NULL;
|
||||
_cleanup_free_ char *path = NULL;
|
||||
|
||||
r = chase_and_opendirat(rfd, *p, CHASE_AT_RESOLVE_IN_ROOT, &path, &dir);
|
||||
if (r < 0) {
|
||||
if (r != -ENOENT)
|
||||
log_debug_errno(r, "Failed to chase and open directory '%s/%s', ignoring: %m", strempty(root), skip_leading_slash(*p));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c && streq_ptr(path_startswith(c->result, path), c->name)) {
|
||||
r = insert_replacement(&fh, TAKE_PTR(c), &inserted);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = files_add(dir, *p, path, rfd, root, &fh, &masked, suffix, flags);
|
||||
if (r == -ENOMEM)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (c) {
|
||||
r = insert_replacement(&fh, TAKE_PTR(c), &inserted);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
*ret = TAKE_PTR(fh);
|
||||
if (ret_inserted)
|
||||
*ret_inserted = inserted;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -402,6 +567,35 @@ int conf_files_list_strv(
|
||||
return copy_and_sort_files_from_hashmap(fh, empty_to_root(root_abs), flags, ret);
|
||||
}
|
||||
|
||||
int conf_files_list_strv_full(
|
||||
const char *suffix,
|
||||
const char *root,
|
||||
ConfFilesFlags flags,
|
||||
const char * const *dirs,
|
||||
ConfFile ***ret_files,
|
||||
size_t *ret_n_files) {
|
||||
|
||||
_cleanup_hashmap_free_ Hashmap *fh = NULL;
|
||||
_cleanup_close_ int rfd = -EBADF;
|
||||
_cleanup_free_ char *root_abs = NULL;
|
||||
_cleanup_strv_free_ char **dirs_abs = NULL;
|
||||
int r;
|
||||
|
||||
assert(ret_files);
|
||||
assert(ret_n_files);
|
||||
|
||||
r = prepare_dirs(root, (char**) dirs, &rfd, &root_abs, &dirs_abs);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = conf_files_list_impl(suffix, rfd, root_abs, flags, (const char * const *) dirs_abs,
|
||||
/* replacement = */ NULL, &fh, /* ret_inserted = */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return dump_files(fh, empty_to_root(root_abs), ret_files, ret_n_files);
|
||||
}
|
||||
|
||||
int conf_files_list_strv_at(
|
||||
char ***ret,
|
||||
const char *suffix,
|
||||
@ -426,14 +620,48 @@ int conf_files_list_strv_at(
|
||||
return copy_and_sort_files_from_hashmap(fh, /* root = */ NULL, flags, ret);
|
||||
}
|
||||
|
||||
int conf_files_list_strv_at_full(
|
||||
const char *suffix,
|
||||
int rfd,
|
||||
ConfFilesFlags flags,
|
||||
const char * const *dirs,
|
||||
ConfFile ***ret_files,
|
||||
size_t *ret_n_files) {
|
||||
|
||||
_cleanup_hashmap_free_ Hashmap *fh = NULL;
|
||||
_cleanup_free_ char *root = NULL;
|
||||
int r;
|
||||
|
||||
assert(rfd >= 0 || rfd == AT_FDCWD);
|
||||
assert(ret_files);
|
||||
assert(ret_n_files);
|
||||
|
||||
if (rfd >= 0 && DEBUG_LOGGING)
|
||||
(void) fd_get_path(rfd, &root); /* for logging */
|
||||
|
||||
r = conf_files_list_impl(suffix, rfd, root, flags, dirs, /* replacement = */ NULL, &fh, /* ret_inserted = */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return dump_files(fh, /* root = */ NULL, ret_files, ret_n_files);
|
||||
}
|
||||
|
||||
int conf_files_list(char ***ret, const char *suffix, const char *root, ConfFilesFlags flags, const char *dir) {
|
||||
return conf_files_list_strv(ret, suffix, root, flags, STRV_MAKE_CONST(dir));
|
||||
}
|
||||
|
||||
int conf_files_list_full(const char *suffix, const char *root, ConfFilesFlags flags, const char *dir, ConfFile ***ret_files, size_t *ret_n_files) {
|
||||
return conf_files_list_strv_full(suffix, root, flags, STRV_MAKE_CONST(dir), ret_files, ret_n_files);
|
||||
}
|
||||
|
||||
int conf_files_list_at(char ***ret, const char *suffix, int rfd, ConfFilesFlags flags, const char *dir) {
|
||||
return conf_files_list_strv_at(ret, suffix, rfd, flags, STRV_MAKE_CONST(dir));
|
||||
}
|
||||
|
||||
int conf_files_list_at_full(const char *suffix, int rfd, ConfFilesFlags flags, const char *dir, ConfFile ***ret_files, size_t *ret_n_files) {
|
||||
return conf_files_list_strv_at_full(suffix, rfd, flags, STRV_MAKE_CONST(dir), ret_files, ret_n_files);
|
||||
}
|
||||
|
||||
int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, ConfFilesFlags flags, const char *dirs) {
|
||||
_cleanup_strv_free_ char **d = NULL;
|
||||
|
||||
@ -446,6 +674,19 @@ int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, Co
|
||||
return conf_files_list_strv(ret, suffix, root, flags, (const char**) d);
|
||||
}
|
||||
|
||||
int conf_files_list_nulstr_full(const char *suffix, const char *root, ConfFilesFlags flags, const char *dirs, ConfFile ***ret_files, size_t *ret_n_files) {
|
||||
_cleanup_strv_free_ char **d = NULL;
|
||||
|
||||
assert(ret_files);
|
||||
assert(ret_n_files);
|
||||
|
||||
d = strv_split_nulstr(dirs);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
return conf_files_list_strv_full(suffix, root, flags, (const char**) d, ret_files, ret_n_files);
|
||||
}
|
||||
|
||||
int conf_files_list_nulstr_at(char ***ret, const char *suffix, int rfd, ConfFilesFlags flags, const char *dirs) {
|
||||
_cleanup_strv_free_ char **d = NULL;
|
||||
|
||||
@ -458,6 +699,19 @@ int conf_files_list_nulstr_at(char ***ret, const char *suffix, int rfd, ConfFile
|
||||
return conf_files_list_strv_at(ret, suffix, rfd, flags, (const char**) d);
|
||||
}
|
||||
|
||||
int conf_files_list_nulstr_at_full(const char *suffix, int rfd, ConfFilesFlags flags, const char *dirs, ConfFile ***ret_files, size_t *ret_n_files) {
|
||||
_cleanup_strv_free_ char **d = NULL;
|
||||
|
||||
assert(ret_files);
|
||||
assert(ret_n_files);
|
||||
|
||||
d = strv_split_nulstr(dirs);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
return conf_files_list_strv_at_full(suffix, rfd, flags, (const char**) d, ret_files, ret_n_files);
|
||||
}
|
||||
|
||||
int conf_files_list_with_replacement(
|
||||
const char *root,
|
||||
char **config_dirs,
|
||||
@ -471,6 +725,7 @@ int conf_files_list_with_replacement(
|
||||
_cleanup_close_ int rfd = -EBADF;
|
||||
_cleanup_free_ char *root_abs = NULL;
|
||||
_cleanup_strv_free_ char **dirs_abs = NULL;
|
||||
const ConfFile *c = NULL;
|
||||
int r;
|
||||
|
||||
assert(ret_files);
|
||||
@ -480,18 +735,14 @@ int conf_files_list_with_replacement(
|
||||
return r;
|
||||
|
||||
r = conf_files_list_impl(".conf", rfd, root_abs, flags, (const char * const *) dirs_abs,
|
||||
replacement, &fh, ret_inserted ? &inserted : NULL);
|
||||
replacement, &fh, ret_inserted ? &c : NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (inserted) {
|
||||
char *p;
|
||||
|
||||
r = chaseat_prefix_root(inserted, root_abs, &p);
|
||||
if (c) {
|
||||
r = chaseat_prefix_root(c->result, root_abs, &inserted);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to prefix '%s' with root '%s': %m", inserted, empty_to_root(root_abs));
|
||||
|
||||
free_and_replace(inserted, p);
|
||||
return log_debug_errno(r, "Failed to prefix '%s' with root '%s': %m", c->result, empty_to_root(root_abs));
|
||||
}
|
||||
|
||||
r = copy_and_sort_files_from_hashmap(fh, empty_to_root(root_abs), flags, ret_files);
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "forward.h"
|
||||
|
||||
typedef enum ConfFilesFlags {
|
||||
@ -13,12 +15,36 @@ typedef enum ConfFilesFlags {
|
||||
CONF_FILES_FILTER_MASKED = CONF_FILES_FILTER_MASKED_BY_SYMLINK | CONF_FILES_FILTER_MASKED_BY_EMPTY,
|
||||
} ConfFilesFlags;
|
||||
|
||||
typedef struct ConfFile {
|
||||
char *name; /* name of a file found in config directories */
|
||||
char *result; /* resolved config directory with the original file name found in the directory */
|
||||
char *original_path; /* original config directory with the original file name found in the directory */
|
||||
char *resolved_path; /* fully resolved path, where the filename part of the path may be different from the original name */
|
||||
int fd; /* O_PATH fd to resolved_path, -EBADF if the resolved_path does not exist */
|
||||
struct stat st; /* stat of the file. */
|
||||
} ConfFile;
|
||||
|
||||
ConfFile* conf_file_free(ConfFile *c);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(ConfFile*, conf_file_free);
|
||||
void conf_file_free_many(ConfFile **array, size_t n);
|
||||
|
||||
int conf_file_new_at(const char *path, int rfd, ChaseFlags chase_flags, ConfFile **ret);
|
||||
int conf_file_new(const char *path, const char *root, ChaseFlags chase_flags, ConfFile **ret);
|
||||
|
||||
int conf_files_list(char ***ret, const char *suffix, const char *root, ConfFilesFlags flags, const char *dir);
|
||||
int conf_files_list_at(char ***ret, const char *suffix, int rfd, ConfFilesFlags flags, const char *dir);
|
||||
int conf_files_list_strv(char ***ret, const char *suffix, const char *root, ConfFilesFlags flags, const char* const* dirs);
|
||||
int conf_files_list_strv_at(char ***ret, const char *suffix, int rfd, ConfFilesFlags flags, const char * const *dirs);
|
||||
int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, ConfFilesFlags flags, const char *dirs);
|
||||
int conf_files_list_nulstr_at(char ***ret, const char *suffix, int rfd, ConfFilesFlags flags, const char *dirs);
|
||||
|
||||
int conf_files_list_full(const char *suffix, const char *root, ConfFilesFlags flags, const char *dir, ConfFile ***ret_files, size_t *ret_n_files);
|
||||
int conf_files_list_at_full(const char *suffix, int rfd, ConfFilesFlags flags, const char *dir, ConfFile ***ret_files, size_t *ret_n_files);
|
||||
int conf_files_list_strv_full(const char *suffix, const char *root, ConfFilesFlags flags, const char * const *dirs, ConfFile ***ret_files, size_t *ret_n_files);
|
||||
int conf_files_list_strv_at_full(const char *suffix, int rfd, ConfFilesFlags flags, const char * const *dirs, ConfFile ***ret_files, size_t *ret_n_files);
|
||||
int conf_files_list_nulstr_full(const char *suffix, const char *root, ConfFilesFlags flags, const char *dirs, ConfFile ***ret_files, size_t *ret_n_files);
|
||||
int conf_files_list_nulstr_at_full(const char *suffix, int rfd, ConfFilesFlags flags, const char *dirs, ConfFile ***ret_files, size_t *ret_n_files);
|
||||
|
||||
int conf_files_list_with_replacement(
|
||||
const char *root,
|
||||
char **config_dirs,
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/kcmp.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/kcmp.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
@ -16,7 +16,6 @@
|
||||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "log.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
|
@ -6,7 +6,6 @@ _Pragma("GCC diagnostic ignored \"-Wzero-as-null-pointer-constant\"")
|
||||
#include <linux/magic.h>
|
||||
|
||||
#include "filesystems.h"
|
||||
#include "missing_magic.h"
|
||||
#include "stat-util.h"
|
||||
|
||||
struct FilesystemMagic {
|
||||
|
@ -104,6 +104,7 @@ typedef struct Set Set;
|
||||
|
||||
typedef struct dual_timestamp dual_timestamp;
|
||||
typedef struct triple_timestamp triple_timestamp;
|
||||
typedef struct ConfFile ConfFile;
|
||||
typedef struct LockFile LockFile;
|
||||
typedef struct PidRef PidRef;
|
||||
typedef struct Prioq Prioq;
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "label.h"
|
||||
#include "lock-util.h"
|
||||
#include "log.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "mkdir.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
|
@ -3,6 +3,9 @@
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
${1:?} -E -dM -include sys/socket.h -include "${2:?}" - </dev/null | \
|
||||
CC=${1:?}
|
||||
shift
|
||||
|
||||
$CC -E -dM -include sys/socket.h "$@" - </dev/null | \
|
||||
grep -Ev 'AF_UNSPEC|AF_MAX' | \
|
||||
awk '/^#define[ \t]+AF_[^ \t]+[ \t]+[AP]F_[^ \t]/ { print $2; }'
|
||||
|
@ -3,6 +3,9 @@
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
${1:?} -dM -include "${2:?}" - </dev/null | \
|
||||
CC=${1:?}
|
||||
shift
|
||||
|
||||
$CC -dM -include linux/if_arp.h "$@" - </dev/null | \
|
||||
awk '/^#define[ \t]+ARPHRD_[^ \t]+[ \t]+[^ \t]/ { print $2; }' | \
|
||||
sed -e 's/ARPHRD_//'
|
||||
|
@ -3,6 +3,9 @@
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
${1:?} -dM -include "${2:?}" - </dev/null | \
|
||||
CC=${1:?}
|
||||
shift
|
||||
|
||||
$CC -dM -include linux/capability.h "$@" - </dev/null | \
|
||||
awk '/^#define[ \t]+CAP_[A-Z_]+[ \t]+/ { print $2; }' | \
|
||||
grep -v CAP_LAST_CAP
|
||||
|
@ -6,6 +6,9 @@ set -o pipefail
|
||||
# In kernel's arch/parisc/include/uapi/asm/errno.h, ECANCELLED and EREFUSED are defined as aliases of
|
||||
# ECANCELED and ECONNREFUSED, respectively. Let's drop them.
|
||||
|
||||
${1:?} -dM -include errno.h - </dev/null | \
|
||||
CC=${1:?}
|
||||
shift
|
||||
|
||||
$CC -dM -include errno.h "$@" - </dev/null | \
|
||||
grep -Ev '^#define[[:space:]]+(ECANCELLED|EREFUSED)' | \
|
||||
awk '/^#define[ \t]+E[^ _]+[ \t]+/ { print $2; }'
|
||||
|
@ -1,8 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
/* To make struct xattr_args defined, which is used by setxattrat(). Note, the kernel header must be
|
||||
* included before the glibc header, otherwise the struct will not be defined. */
|
||||
#include <linux/xattr.h>
|
||||
|
||||
#include_next <sys/xattr.h>
|
@ -3,7 +3,6 @@
|
||||
#include "alloc-util.h"
|
||||
#include "keyring-util.h"
|
||||
#include "log.h"
|
||||
#include "missing_syscall.h"
|
||||
|
||||
int keyring_read(key_serial_t serial, void **ret, size_t *ret_size) {
|
||||
size_t bufsize = 100;
|
||||
|
@ -1,8 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <sys/keyctl.h> /* IWYU pragma: export */
|
||||
|
||||
#include "forward.h"
|
||||
#include "missing_keyctl.h"
|
||||
|
||||
/* Like TAKE_PTR() but for key_serial_t, resetting them to -1 */
|
||||
#define TAKE_KEY_SERIAL(key_serial) TAKE_GENERIC(key_serial, key_serial_t, -1)
|
||||
|
@ -84,6 +84,7 @@ basic_sources = files(
|
||||
'psi-util.c',
|
||||
'random-util.c',
|
||||
'ratelimit.c',
|
||||
'raw-clone.c',
|
||||
'recurse-dir.c',
|
||||
'replace-var.c',
|
||||
'rlimit-util.c',
|
||||
@ -119,44 +120,26 @@ basic_sources = files(
|
||||
|
||||
sources += basic_sources
|
||||
|
||||
missing_audit_h = files('missing_audit.h')
|
||||
|
||||
missing_syscall_def_h = files('missing_syscall_def.h')
|
||||
basic_sources += missing_syscall_def_h
|
||||
|
||||
generate_af_list = find_program('generate-af-list.sh')
|
||||
af_list_txt = custom_target(
|
||||
output : 'af-list.txt',
|
||||
command : [generate_af_list, cpp, files('include/sys/socket.h')],
|
||||
capture : true)
|
||||
|
||||
generate_arphrd_list = find_program('generate-arphrd-list.sh')
|
||||
arphrd_list_txt = custom_target(
|
||||
output : 'arphrd-list.txt',
|
||||
command : [generate_arphrd_list, cpp, files('include/linux/if_arp.h')],
|
||||
capture : true)
|
||||
|
||||
generate_cap_list = find_program('generate-cap-list.sh')
|
||||
cap_list_txt = custom_target(
|
||||
output : 'cap-list.txt',
|
||||
command : [generate_cap_list, cpp, files('include/linux/capability.h')],
|
||||
capture : true)
|
||||
|
||||
generate_errno_list = find_program('generate-errno-list.sh')
|
||||
errno_list_txt = custom_target(
|
||||
output : 'errno-list.txt',
|
||||
command : [generate_errno_list, cpp],
|
||||
capture : true)
|
||||
|
||||
generated_gperf_headers = []
|
||||
foreach item : [['af', af_list_txt, 'af', '', ['<sys/socket.h>']],
|
||||
['arphrd', arphrd_list_txt, 'arphrd', 'ARPHRD_', []],
|
||||
['cap', cap_list_txt, 'capability', '', []],
|
||||
['errno', errno_list_txt, 'errno', '', []]]
|
||||
foreach item : [
|
||||
# name, source, struct name, prefix, headers
|
||||
['af', af_sources, 'af', '', ['<sys/socket.h>'], ],
|
||||
['arphrd', arphrd_sources, 'arphrd', 'ARPHRD_', ['<linux/if_arp.h>'], ],
|
||||
['cap', cap_sources, 'capability', '', ['<linux/capability.h>'], ],
|
||||
['errno', [], 'errno', '', ['<errno.h>'], ],
|
||||
]
|
||||
|
||||
fname = '@0@-list.txt'.format(item[0])
|
||||
generate_list = files('generate-@0@-list.sh'.format(item[0]))
|
||||
list_txt = custom_target(
|
||||
input : [generate_list, item[1]],
|
||||
output : fname,
|
||||
command : [env, 'bash', generate_list, cpp, system_include_args],
|
||||
capture : true)
|
||||
|
||||
fname = '@0@-from-name.gperf'.format(item[0])
|
||||
gperf_file = custom_target(
|
||||
input : item[1],
|
||||
input : list_txt,
|
||||
output : fname,
|
||||
command : [generate_gperfs, item[2], item[3], '@INPUT@'] + item[4],
|
||||
capture : true)
|
||||
@ -176,7 +159,7 @@ foreach item : [['af', af_list_txt, 'af', '', ['<sys/sock
|
||||
fname = '@0@-to-name.inc'.format(item[0])
|
||||
awkscript = '@0@-to-name.awk'.format(item[0])
|
||||
target2 = custom_target(
|
||||
input : [awkscript, item[1]],
|
||||
input : [awkscript, list_txt],
|
||||
output : fname,
|
||||
command : [awk, '-f', '@INPUT0@', '@INPUT1@'],
|
||||
capture : true)
|
||||
@ -189,61 +172,13 @@ basic_sources += generated_gperf_headers
|
||||
|
||||
############################################################
|
||||
|
||||
arch_list = [
|
||||
'alpha',
|
||||
'arc',
|
||||
'arm',
|
||||
'arm64',
|
||||
'i386',
|
||||
'ia64',
|
||||
'loongarch64',
|
||||
'm68k',
|
||||
'mips64',
|
||||
'mips64n32',
|
||||
'mipso32',
|
||||
'parisc',
|
||||
'powerpc',
|
||||
'powerpc64',
|
||||
'riscv32',
|
||||
'riscv64',
|
||||
's390',
|
||||
's390x',
|
||||
'sparc',
|
||||
'x86_64'
|
||||
]
|
||||
|
||||
run_target(
|
||||
'update-syscall-tables',
|
||||
command : [update_syscall_tables_sh, meson.current_source_dir()] + arch_list)
|
||||
|
||||
syscall_list_txt = files('syscall-list.txt')
|
||||
|
||||
syscall_lists = []
|
||||
foreach arch: arch_list
|
||||
syscall_lists += files('syscalls-@0@.txt'.format(arch))
|
||||
endforeach
|
||||
|
||||
missing_syscalls_py = find_program('missing_syscalls.py')
|
||||
|
||||
run_target(
|
||||
'update-syscall-header',
|
||||
command : [missing_syscalls_py,
|
||||
missing_syscall_def_h,
|
||||
syscall_lists])
|
||||
|
||||
############################################################
|
||||
|
||||
filesystem_includes = files(
|
||||
'include/linux/magic.h',
|
||||
'missing_magic.h',
|
||||
)
|
||||
|
||||
check_filesystems = find_program('check-filesystems.sh')
|
||||
r = run_command(
|
||||
[
|
||||
'env', '--chdir', meson.project_build_root(),
|
||||
check_filesystems, cpp, files('filesystems-gperf.gperf')
|
||||
] + filesystem_includes,
|
||||
check_filesystems, cpp, files('filesystems-gperf.gperf'),
|
||||
system_include_args,
|
||||
],
|
||||
check: false,
|
||||
)
|
||||
if r.returncode() != 0
|
||||
@ -273,17 +208,8 @@ filesystem_switch_case_inc = custom_target(
|
||||
'@INPUT@'],
|
||||
capture : true)
|
||||
|
||||
generate_bpf_delegate_configs = find_program('generate-bpf-delegate-configs.py')
|
||||
bpf_delegate_configs_inc = custom_target(
|
||||
input : files('include/linux/bpf.h'),
|
||||
output : 'bpf-delegate-configs.inc',
|
||||
command : [generate_bpf_delegate_configs,
|
||||
'code',
|
||||
'@INPUT@'],
|
||||
capture : true)
|
||||
|
||||
generated_sources += [filesystem_list_inc, filesystem_switch_case_inc, filesystems_gperf_h, bpf_delegate_configs_inc]
|
||||
basic_sources += [filesystem_list_inc, filesystem_switch_case_inc, filesystems_gperf_h, bpf_delegate_configs_inc]
|
||||
generated_sources += [filesystem_list_inc, filesystem_switch_case_inc, filesystems_gperf_h]
|
||||
basic_sources += [filesystem_list_inc, filesystem_switch_case_inc, filesystems_gperf_h]
|
||||
|
||||
libbasic_static = static_library(
|
||||
'basic',
|
||||
|
@ -1,249 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
/* Missing glibc definitions to access certain kernel APIs */
|
||||
|
||||
#include <linux/mempolicy.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/xattr.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef ARCH_MIPS
|
||||
#include <asm/sgidefs.h>
|
||||
#endif
|
||||
|
||||
#include "forward.h"
|
||||
#include "missing_keyctl.h"
|
||||
#include "missing_syscall_def.h"
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_FCHMODAT2
|
||||
/* since kernel v6.6 (78252deb023cf0879256fcfbafe37022c390762b) */
|
||||
static inline int missing_fchmodat2(int dirfd, const char *path, mode_t mode, int flags) {
|
||||
return syscall(__NR_fchmodat2, dirfd, path, mode, flags);
|
||||
}
|
||||
|
||||
# define fchmodat2 missing_fchmodat2
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_PIVOT_ROOT
|
||||
static inline int missing_pivot_root(const char *new_root, const char *put_old) {
|
||||
return syscall(__NR_pivot_root, new_root, put_old);
|
||||
}
|
||||
|
||||
# define pivot_root missing_pivot_root
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_IOPRIO_GET
|
||||
static inline int missing_ioprio_get(int which, int who) {
|
||||
return syscall(__NR_ioprio_get, which, who);
|
||||
}
|
||||
|
||||
# define ioprio_get missing_ioprio_get
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_IOPRIO_SET
|
||||
static inline int missing_ioprio_set(int which, int who, int ioprio) {
|
||||
return syscall(__NR_ioprio_set, which, who, ioprio);
|
||||
}
|
||||
|
||||
# define ioprio_set missing_ioprio_set
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_KCMP
|
||||
static inline int missing_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) {
|
||||
return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2);
|
||||
}
|
||||
|
||||
# define kcmp missing_kcmp
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_KEYCTL
|
||||
static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) {
|
||||
return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5);
|
||||
|
||||
# define keyctl missing_keyctl
|
||||
}
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
static inline key_serial_t missing_add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) {
|
||||
return syscall(__NR_add_key, type, description, payload, plen, ringid);
|
||||
|
||||
# define add_key missing_add_key
|
||||
}
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
static inline key_serial_t missing_request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) {
|
||||
return syscall(__NR_request_key, type, description, callout_info, destringid);
|
||||
|
||||
# define request_key missing_request_key
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_BPF
|
||||
union bpf_attr;
|
||||
|
||||
static inline int missing_bpf(int cmd, union bpf_attr *attr, size_t size) {
|
||||
return (int) syscall(__NR_bpf, cmd, attr, size);
|
||||
}
|
||||
|
||||
# define bpf missing_bpf
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_SET_MEMPOLICY
|
||||
static inline long missing_set_mempolicy(int mode, const unsigned long *nodemask,
|
||||
unsigned long maxnode) {
|
||||
return syscall(__NR_set_mempolicy, mode, nodemask, maxnode);
|
||||
}
|
||||
|
||||
# define set_mempolicy missing_set_mempolicy
|
||||
#endif
|
||||
|
||||
#if !HAVE_GET_MEMPOLICY
|
||||
static inline long missing_get_mempolicy(int *mode, unsigned long *nodemask,
|
||||
unsigned long maxnode, void *addr,
|
||||
unsigned long flags) {
|
||||
return syscall(__NR_get_mempolicy, mode, nodemask, maxnode, addr, flags);
|
||||
}
|
||||
|
||||
# define get_mempolicy missing_get_mempolicy
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_PIDFD_SEND_SIGNAL
|
||||
/* since kernel v5.1 (3eb39f47934f9d5a3027fe00d906a45fe3a15fad) */
|
||||
static inline int missing_pidfd_send_signal(int fd, int sig, siginfo_t *info, unsigned flags) {
|
||||
return syscall(__NR_pidfd_send_signal, fd, sig, info, flags);
|
||||
}
|
||||
|
||||
# define pidfd_send_signal missing_pidfd_send_signal
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_PIDFD_OPEN
|
||||
/* since kernel v5.3 (7615d9e1780e26e0178c93c55b73309a5dc093d7) */
|
||||
static inline int missing_pidfd_open(pid_t pid, unsigned flags) {
|
||||
return syscall(__NR_pidfd_open, pid, flags);
|
||||
}
|
||||
|
||||
# define pidfd_open missing_pidfd_open
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_RT_TGSIGQUEUEINFO
|
||||
static inline int missing_rt_tgsigqueueinfo(pid_t tgid, pid_t tid, int sig, siginfo_t *info) {
|
||||
return syscall(__NR_rt_tgsigqueueinfo, tgid, tid, sig, info);
|
||||
}
|
||||
|
||||
# define rt_tgsigqueueinfo missing_rt_tgsigqueueinfo
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_EXECVEAT
|
||||
/* since kernel v3.19 (51f39a1f0cea1cacf8c787f652f26dfee9611874) */
|
||||
static inline int missing_execveat(int dirfd, const char *pathname,
|
||||
char *const argv[], char *const envp[],
|
||||
int flags) {
|
||||
return syscall(__NR_execveat, dirfd, pathname, argv, envp, flags);
|
||||
}
|
||||
|
||||
# define execveat missing_execveat
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_CLOSE_RANGE
|
||||
/* since kernel v5.9 (9b4feb630e8e9801603f3cab3a36369e3c1cf88d) */
|
||||
static inline int missing_close_range(unsigned first_fd, unsigned end_fd, unsigned flags) {
|
||||
/* Kernel-side the syscall expects fds as unsigned integers (just like close() actually), while
|
||||
* userspace exclusively uses signed integers for fds. glibc chose to expose it 1:1 however, hence we
|
||||
* do so here too, even if we end up passing signed fds to it most of the time. */
|
||||
return syscall(__NR_close_range,
|
||||
first_fd,
|
||||
end_fd,
|
||||
flags);
|
||||
}
|
||||
|
||||
# define close_range missing_close_range
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_SCHED_SETATTR
|
||||
/* since kernel 3.14 (e6cfc0295c7d51b008999a8b13a44fb43f8685ea) */
|
||||
static inline ssize_t missing_sched_setattr(pid_t pid, struct sched_attr *attr, unsigned int flags) {
|
||||
return syscall(__NR_sched_setattr, pid, attr, flags);
|
||||
}
|
||||
|
||||
# define sched_setattr missing_sched_setattr
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
/* glibc does not provide clone() on ia64, only clone2(). Not only that, but it also doesn't provide a
|
||||
* prototype, only the symbol in the shared library (it provides a prototype for clone(), but not the
|
||||
* symbol in the shared library). */
|
||||
#if defined(__ia64__)
|
||||
int __clone2(int (*fn)(void *), void *stack_base, size_t stack_size, int flags, void *arg);
|
||||
#define HAVE_CLONE 0
|
||||
#else
|
||||
/* We know that everywhere else clone() is available, so we don't bother with a meson check (that takes time
|
||||
* at build time) and just define it. Once the kernel drops ia64 support, we can drop this too. */
|
||||
#define HAVE_CLONE 1
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_QUOTACTL_FD
|
||||
/* since kernel v5.14 (64c2c2c62f92339b176ea24403d8db16db36f9e6) */
|
||||
static inline int missing_quotactl_fd(int fd, int cmd, int id, void *addr) {
|
||||
return syscall(__NR_quotactl_fd, fd, cmd, id, addr);
|
||||
}
|
||||
|
||||
# define quotactl_fd missing_quotactl_fd
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_SETXATTRAT
|
||||
/* since kernel v6.13 (6140be90ec70c39fa844741ca3cc807dd0866394) */
|
||||
static inline int missing_setxattrat(int fd, const char *path, int at_flags, const char *name, const struct xattr_args *args, size_t size) {
|
||||
return syscall(__NR_setxattrat, fd, path, at_flags, name, args, size);
|
||||
}
|
||||
|
||||
# define setxattrat missing_setxattrat
|
||||
#endif
|
||||
|
||||
/* ======================================================================= */
|
||||
|
||||
#if !HAVE_REMOVEXATTRAT
|
||||
/* since kernel v6.13 (6140be90ec70c39fa844741ca3cc807dd0866394) */
|
||||
static inline int missing_removexattrat(int fd, const char *path, int at_flags, const char *name) {
|
||||
return syscall(__NR_removexattrat, fd, path, at_flags, name);
|
||||
}
|
||||
|
||||
# define removexattrat missing_removexattrat
|
||||
#endif
|
@ -1,6 +1,8 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <linux/magic.h>
|
||||
#include <linux/nsfs.h>
|
||||
#include <sched.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mount.h>
|
||||
@ -10,8 +12,6 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "log.h"
|
||||
#include "missing_magic.h"
|
||||
#include "missing_namespace.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "namespace-util.h"
|
||||
#include "parse-util.h"
|
||||
|
@ -1,5 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/magic.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <threads.h>
|
||||
#include <unistd.h>
|
||||
@ -7,8 +9,6 @@
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "missing_fs.h"
|
||||
#include "missing_magic.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "pidfd-util.h"
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <sys/pidfd.h> /* IWYU pragma: export */
|
||||
|
||||
#include "forward.h"
|
||||
#include "missing_syscall.h" /* IWYU pragma: export */
|
||||
|
||||
int pidfd_get_namespace(int fd, unsigned long ns_type_cmd);
|
||||
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include "locale-util.h"
|
||||
#include "log.h"
|
||||
#include "memory-util.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "namespace-util.h"
|
||||
#include "nulstr-util.h"
|
||||
|
84
src/basic/raw-clone.c
Normal file
84
src/basic/raw-clone.c
Normal file
@ -0,0 +1,84 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
/***
|
||||
Copyright © 2016 Michael Karcher
|
||||
***/
|
||||
|
||||
#include <errno.h>
|
||||
#include <sched.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "process-util.h"
|
||||
#include "raw-clone.h"
|
||||
|
||||
/**
|
||||
* raw_clone() - uses clone to create a new process with clone flags
|
||||
* @flags: Flags to pass to the clone system call
|
||||
*
|
||||
* Uses the clone system call to create a new process with the cloning flags and termination signal passed in the flags
|
||||
* parameter. Opposed to glibc's clone function, using this function does not set up a separate stack for the child, but
|
||||
* relies on copy-on-write semantics on the one stack at a common virtual address, just as fork does.
|
||||
*
|
||||
* To obtain copy-on-write semantics, flags must not contain CLONE_VM, and thus CLONE_THREAD and CLONE_SIGHAND
|
||||
* (which require CLONE_VM) are not usable.
|
||||
*
|
||||
* Additionally, as this function does not pass the ptid (pidfd in the case of CLONE_PIDFD), newtls and ctid
|
||||
* parameters to the kernel, flags must not contain CLONE_PARENT_SETTID, CLONE_CHILD_SETTID, CLONE_CHILD_CLEARTID,
|
||||
* CLONE_SETTLS, or CLONE_PIDFD.
|
||||
*
|
||||
* WARNING: 💣 this call (just like glibc's own clone() wrapper) will not synchronize on glibc's malloc
|
||||
* locks, which means they will be in an undefined state in the child if the parent is
|
||||
* threaded. This means: the parent must either never use threads, or the child cannot use memory
|
||||
* allocation itself. This is a major pitfall, hence be careful! 💣
|
||||
*
|
||||
* Returns: 0 in the child process and the child process id in the parent.
|
||||
*/
|
||||
pid_t raw_clone(unsigned long flags) {
|
||||
pid_t ret;
|
||||
|
||||
assert((flags & (CLONE_VM|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID|CLONE_CHILD_CLEARTID|CLONE_SETTLS|CLONE_PIDFD)) == 0);
|
||||
#if defined(__s390x__) || defined(__s390__) || defined(__CRIS__)
|
||||
/* On s390/s390x and cris the order of the first and second arguments
|
||||
* of the raw clone() system call is reversed. */
|
||||
ret = (pid_t) syscall(__NR_clone, NULL, flags);
|
||||
#elif defined(__sparc__)
|
||||
{
|
||||
/**
|
||||
* sparc always returns the other process id in %o0, and
|
||||
* a boolean flag whether this is the child or the parent in
|
||||
* %o1. Inline assembly is needed to get the flag returned
|
||||
* in %o1.
|
||||
*/
|
||||
int in_child, child_pid, error;
|
||||
|
||||
asm volatile("mov %3, %%g1\n\t"
|
||||
"mov %4, %%o0\n\t"
|
||||
"mov 0 , %%o1\n\t"
|
||||
#if defined(__arch64__)
|
||||
"t 0x6d\n\t"
|
||||
#else
|
||||
"t 0x10\n\t"
|
||||
#endif
|
||||
"addx %%g0, 0, %2\n\t"
|
||||
"mov %%o1, %0\n\t"
|
||||
"mov %%o0, %1" :
|
||||
"=r"(in_child), "=r"(child_pid), "=r"(error) :
|
||||
"i"(__NR_clone), "r"(flags) :
|
||||
"%o1", "%o0", "%g1", "cc" );
|
||||
|
||||
if (error) {
|
||||
errno = child_pid;
|
||||
ret = -1;
|
||||
} else
|
||||
ret = in_child ? 0 : child_pid;
|
||||
}
|
||||
#else
|
||||
ret = (pid_t) syscall(__NR_clone, flags, NULL);
|
||||
#endif
|
||||
|
||||
if (ret == 0)
|
||||
reset_cached_pid();
|
||||
|
||||
return ret;
|
||||
}
|
@ -1,85 +1,8 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
Copyright © 2016 Michael Karcher
|
||||
***/
|
||||
#include <sched.h> /* IWYU pragma: export */
|
||||
|
||||
#include <errno.h>
|
||||
#include <sched.h>
|
||||
#include <sys/syscall.h>
|
||||
#include "forward.h"
|
||||
|
||||
#include "log.h"
|
||||
#include "macro.h"
|
||||
#include "process-util.h"
|
||||
|
||||
/**
|
||||
* raw_clone() - uses clone to create a new process with clone flags
|
||||
* @flags: Flags to pass to the clone system call
|
||||
*
|
||||
* Uses the clone system call to create a new process with the cloning flags and termination signal passed in the flags
|
||||
* parameter. Opposed to glibc's clone function, using this function does not set up a separate stack for the child, but
|
||||
* relies on copy-on-write semantics on the one stack at a common virtual address, just as fork does.
|
||||
*
|
||||
* To obtain copy-on-write semantics, flags must not contain CLONE_VM, and thus CLONE_THREAD and CLONE_SIGHAND
|
||||
* (which require CLONE_VM) are not usable.
|
||||
*
|
||||
* Additionally, as this function does not pass the ptid (pidfd in the case of CLONE_PIDFD), newtls and ctid
|
||||
* parameters to the kernel, flags must not contain CLONE_PARENT_SETTID, CLONE_CHILD_SETTID, CLONE_CHILD_CLEARTID,
|
||||
* CLONE_SETTLS, or CLONE_PIDFD.
|
||||
*
|
||||
* WARNING: 💣 this call (just like glibc's own clone() wrapper) will not synchronize on glibc's malloc
|
||||
* locks, which means they will be in an undefined state in the child if the parent is
|
||||
* threaded. This means: the parent must either never use threads, or the child cannot use memory
|
||||
* allocation itself. This is a major pitfall, hence be careful! 💣
|
||||
*
|
||||
* Returns: 0 in the child process and the child process id in the parent.
|
||||
*/
|
||||
static inline pid_t raw_clone(unsigned long flags) {
|
||||
pid_t ret;
|
||||
|
||||
assert((flags & (CLONE_VM|CLONE_PARENT_SETTID|CLONE_CHILD_SETTID|CLONE_CHILD_CLEARTID|CLONE_SETTLS|CLONE_PIDFD)) == 0);
|
||||
#if defined(__s390x__) || defined(__s390__) || defined(__CRIS__)
|
||||
/* On s390/s390x and cris the order of the first and second arguments
|
||||
* of the raw clone() system call is reversed. */
|
||||
ret = (pid_t) syscall(__NR_clone, NULL, flags);
|
||||
#elif defined(__sparc__)
|
||||
{
|
||||
/**
|
||||
* sparc always returns the other process id in %o0, and
|
||||
* a boolean flag whether this is the child or the parent in
|
||||
* %o1. Inline assembly is needed to get the flag returned
|
||||
* in %o1.
|
||||
*/
|
||||
int in_child, child_pid, error;
|
||||
|
||||
asm volatile("mov %3, %%g1\n\t"
|
||||
"mov %4, %%o0\n\t"
|
||||
"mov 0 , %%o1\n\t"
|
||||
#if defined(__arch64__)
|
||||
"t 0x6d\n\t"
|
||||
#else
|
||||
"t 0x10\n\t"
|
||||
#endif
|
||||
"addx %%g0, 0, %2\n\t"
|
||||
"mov %%o1, %0\n\t"
|
||||
"mov %%o0, %1" :
|
||||
"=r"(in_child), "=r"(child_pid), "=r"(error) :
|
||||
"i"(__NR_clone), "r"(flags) :
|
||||
"%o1", "%o0", "%g1", "cc" );
|
||||
|
||||
if (error) {
|
||||
errno = child_pid;
|
||||
ret = -1;
|
||||
} else
|
||||
ret = in_child ? 0 : child_pid;
|
||||
}
|
||||
#else
|
||||
ret = (pid_t) syscall(__NR_clone, flags, NULL);
|
||||
#endif
|
||||
|
||||
if (ret == 0)
|
||||
reset_cached_pid();
|
||||
|
||||
return ret;
|
||||
}
|
||||
pid_t raw_clone(unsigned long flags);
|
||||
|
@ -1,15 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <linux/reboot.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* glibc defines the reboot() API call, which is a wrapper around the system call of the same name, but without the
|
||||
* extra "arg" parameter. Since we need that parameter for some calls, let's add a "raw" wrapper that is defined the
|
||||
* same way, except it takes the additional argument. */
|
||||
|
||||
static inline int raw_reboot(int cmd, const void *arg) {
|
||||
return (int) syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, cmd, arg);
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "errno-util.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "parse-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "stdio-util.h"
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <linux/magic.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@ -13,7 +14,6 @@
|
||||
#include "fs-util.h"
|
||||
#include "hash-funcs.h"
|
||||
#include "log.h"
|
||||
#include "missing_magic.h"
|
||||
#include "mountpoint-util.h"
|
||||
#include "path-util.h"
|
||||
#include "siphash24.h"
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <linux/kd.h>
|
||||
#include <linux/magic.h>
|
||||
#include <linux/tiocl.h>
|
||||
#include <linux/vt.h>
|
||||
#include <poll.h>
|
||||
@ -27,7 +28,6 @@
|
||||
#include "inotify-util.h"
|
||||
#include "io-util.h"
|
||||
#include "log.h"
|
||||
#include "missing_magic.h"
|
||||
#include "namespace-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "nulstr-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "sparse-endian.h"
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <fnmatch.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/bpf_insn.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@ -12,7 +13,6 @@
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "log.h"
|
||||
#include "missing_bpf.h"
|
||||
#include "nulstr-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/magic.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bpf-foreign.h"
|
||||
@ -8,7 +9,6 @@
|
||||
#include "cgroup.h"
|
||||
#include "hash-funcs.h"
|
||||
#include "hashmap.h"
|
||||
#include "missing_magic.h"
|
||||
#include "siphash24.h"
|
||||
#include "stat-util.h"
|
||||
#include "unit.h"
|
||||
|
@ -1,12 +1,10 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <sys/reboot.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ansi-color.h"
|
||||
#include "emergency-action.h"
|
||||
#include "manager.h"
|
||||
#include "raw-reboot.h"
|
||||
#include "reboot-util.h"
|
||||
#include "special.h"
|
||||
#include "string-table.h"
|
||||
|
@ -1,13 +1,14 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <grp.h>
|
||||
#include <linux/ioprio.h>
|
||||
#include <linux/prctl.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/securebits.h>
|
||||
#include <poll.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/ioprio.h>
|
||||
#include <sys/keyctl.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/statvfs.h>
|
||||
@ -54,7 +55,6 @@
|
||||
#include "journal-send.h"
|
||||
#include "manager.h"
|
||||
#include "memfd-util.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "mkdir-label.h"
|
||||
#include "mount-util.h"
|
||||
#include "namespace-util.h"
|
||||
|
@ -100,15 +100,34 @@ load_fragment_gperf_nulstr_c = custom_target(
|
||||
command : [awk, '-f', '@INPUT0@', '@INPUT1@'],
|
||||
capture : true)
|
||||
|
||||
generated_sources += [load_fragment_gperf_c, load_fragment_gperf_nulstr_c]
|
||||
generate_bpf_delegate_configs = files('generate-bpf-delegate-configs.py')
|
||||
bpf_delegate_configs_inc = custom_target(
|
||||
input : [generate_bpf_delegate_configs, bpf_delegate_sources],
|
||||
output : 'bpf-delegate-configs.inc',
|
||||
command : [python,
|
||||
generate_bpf_delegate_configs,
|
||||
'code',
|
||||
bpf_delegate_sources],
|
||||
capture : true)
|
||||
|
||||
bpf_delegate_xml = custom_target(
|
||||
input : [generate_bpf_delegate_configs, bpf_delegate_sources],
|
||||
output : 'bpf-delegate.xml',
|
||||
command : [python,
|
||||
generate_bpf_delegate_configs,
|
||||
'doc',
|
||||
bpf_delegate_sources],
|
||||
capture : true)
|
||||
man_page_depends += bpf_delegate_xml
|
||||
|
||||
generated_sources += [load_fragment_gperf_c, load_fragment_gperf_nulstr_c, bpf_delegate_configs_inc]
|
||||
libcore_sources += [load_fragment_gperf_c, load_fragment_gperf_nulstr_c, bpf_delegate_configs_inc]
|
||||
libcore_build_dir = meson.current_build_dir()
|
||||
libcore_name = 'systemd-core-@0@'.format(shared_lib_tag)
|
||||
|
||||
libcore_static = static_library(
|
||||
libcore_name,
|
||||
libcore_sources,
|
||||
load_fragment_gperf_c,
|
||||
load_fragment_gperf_nulstr_c,
|
||||
include_directories : [includes, include_directories('.')],
|
||||
implicit_include_directories : false,
|
||||
c_args : ['-fvisibility=default'],
|
||||
@ -162,6 +181,7 @@ executor_libs = get_option('link-executor-shared') ? \
|
||||
libcore,
|
||||
libshared,
|
||||
] : [
|
||||
libc_wrapper_static,
|
||||
libcore_static,
|
||||
libshared_static,
|
||||
libbasic_static,
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/loop.h>
|
||||
#include <linux/magic.h>
|
||||
#include <sched.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -29,7 +30,6 @@
|
||||
#include "log.h"
|
||||
#include "loop-util.h"
|
||||
#include "loopback-setup.h"
|
||||
#include "missing_magic.h"
|
||||
#include "mkdir-label.h"
|
||||
#include "mount-util.h"
|
||||
#include "mountpoint-util.h"
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sd-bus.h"
|
||||
#include "sd-varlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "audit-fd.h"
|
||||
@ -26,6 +27,7 @@ static bool initialized = false;
|
||||
|
||||
struct audit_info {
|
||||
sd_bus_creds *creds;
|
||||
sd_varlink *link;
|
||||
const char *path;
|
||||
const char *cmdline;
|
||||
const char *function;
|
||||
@ -48,12 +50,23 @@ static int audit_callback(
|
||||
char uid_buf[DECIMAL_STR_MAX(uid_t) + 1] = "n/a";
|
||||
char gid_buf[DECIMAL_STR_MAX(gid_t) + 1] = "n/a";
|
||||
|
||||
if (sd_bus_creds_get_audit_login_uid(audit->creds, &login_uid) >= 0)
|
||||
xsprintf(login_uid_buf, UID_FMT, login_uid);
|
||||
if (sd_bus_creds_get_euid(audit->creds, &uid) >= 0)
|
||||
xsprintf(uid_buf, UID_FMT, uid);
|
||||
if (sd_bus_creds_get_egid(audit->creds, &gid) >= 0)
|
||||
xsprintf(gid_buf, GID_FMT, gid);
|
||||
if (audit->creds) {
|
||||
/* DBus case */
|
||||
if (sd_bus_creds_get_audit_login_uid(audit->creds, &login_uid) >= 0)
|
||||
xsprintf(login_uid_buf, UID_FMT, login_uid);
|
||||
if (sd_bus_creds_get_euid(audit->creds, &uid) >= 0)
|
||||
xsprintf(uid_buf, UID_FMT, uid);
|
||||
if (sd_bus_creds_get_egid(audit->creds, &gid) >= 0)
|
||||
xsprintf(gid_buf, GID_FMT, gid);
|
||||
}
|
||||
|
||||
if (audit->link) {
|
||||
/* varlink */
|
||||
if (sd_varlink_get_peer_uid(audit->link, &uid) >= 0)
|
||||
xsprintf(uid_buf, UID_FMT, uid);
|
||||
if (sd_varlink_get_peer_gid(audit->link, &gid) >= 0)
|
||||
xsprintf(gid_buf, GID_FMT, gid);
|
||||
}
|
||||
|
||||
(void) snprintf(msgbuf, msgbufsize,
|
||||
"auid=%s uid=%s gid=%s%s%s%s%s%s%s%s%s%s",
|
||||
@ -164,13 +177,85 @@ static int access_init(sd_bus_error *error) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_our_contexts(const Unit *unit, const char **ret_acon, const char **ret_tclass, char **ret_fcon) {
|
||||
_cleanup_freecon_ char *fcon = NULL;
|
||||
|
||||
assert(ret_acon);
|
||||
assert(ret_tclass);
|
||||
assert(ret_fcon);
|
||||
|
||||
if (unit && unit->access_selinux_context) {
|
||||
/* Nice! The unit comes with a SELinux context read from the unit file */
|
||||
*ret_acon = unit->access_selinux_context;
|
||||
*ret_tclass = "service";
|
||||
*ret_fcon = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If no unit context is known, use our own */
|
||||
|
||||
/* Ideally, we should call mac_selinux_get_our_label() here because it
|
||||
* does exactly the same - call getcon_raw(). However, it involves
|
||||
* selinux_init() which opens label DB. It was not part of the
|
||||
* original code. I don't want to change it for now. */
|
||||
if (getcon_raw(&fcon) < 0)
|
||||
return log_debug_errno(errno, "SELinux getcon_raw() failed: %m");
|
||||
|
||||
if (!fcon)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "SELinux returned no context of the current process");
|
||||
|
||||
*ret_acon = fcon;
|
||||
*ret_tclass = "system";
|
||||
*ret_fcon = TAKE_PTR(fcon);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_access(
|
||||
const char *scon,
|
||||
const char *tcon,
|
||||
const char *tclass,
|
||||
const char *permission,
|
||||
struct audit_info *audit_info,
|
||||
sd_bus_error *error) {
|
||||
|
||||
bool enforce = mac_selinux_enforcing();
|
||||
int r;
|
||||
|
||||
assert(scon);
|
||||
assert(tcon);
|
||||
assert(tclass);
|
||||
assert(permission);
|
||||
assert(audit_info);
|
||||
assert(audit_info->function);
|
||||
|
||||
r = selinux_check_access(scon, tcon, tclass, permission, &audit_info);
|
||||
if (r < 0) {
|
||||
errno = -(r = errno_or_else(EPERM));
|
||||
|
||||
if (enforce)
|
||||
sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access: %m");
|
||||
}
|
||||
|
||||
return log_selinux_enforcing_errno(
|
||||
r,
|
||||
"SELinux access check scon=%s tcon=%s tclass=%s perm=%s state=%s function=%s path=%s cmdline=%s: %m",
|
||||
scon,
|
||||
tcon,
|
||||
tclass,
|
||||
permission,
|
||||
enforce ? "enforcing" : "permissive",
|
||||
audit_info->function,
|
||||
empty_to_na(audit_info->path),
|
||||
empty_to_na(audit_info->cmdline));
|
||||
}
|
||||
|
||||
/*
|
||||
This function communicates with the kernel to check whether or not it should
|
||||
allow the access.
|
||||
If the machine is in permissive mode it will return ok. Audit messages will
|
||||
still be generated if the access would be denied in enforcing mode.
|
||||
*/
|
||||
int mac_selinux_access_check_internal(
|
||||
int mac_selinux_access_check_bus_internal(
|
||||
sd_bus_message *message,
|
||||
const Unit *unit,
|
||||
const char *permission,
|
||||
@ -216,30 +301,21 @@ int mac_selinux_access_check_internal(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (unit && unit->access_selinux_context) {
|
||||
/* Nice! The unit comes with a SELinux context read from the unit file */
|
||||
acon = unit->access_selinux_context;
|
||||
tclass = "service";
|
||||
} else {
|
||||
/* If no unit context is known, use our own */
|
||||
if (getcon_raw(&fcon) < 0) {
|
||||
log_warning_errno(errno, "SELinux getcon_raw() failed%s (perm=%s): %m",
|
||||
enforce ? "" : ", ignoring",
|
||||
permission);
|
||||
if (!enforce)
|
||||
return 0;
|
||||
r = get_our_contexts(unit, &acon, &tclass, &fcon);
|
||||
if (r < 0) {
|
||||
log_selinux_enforcing_errno(
|
||||
r,
|
||||
"Failed to retrieves SELinux context of current process (perm=%s)%s: %m",
|
||||
permission,
|
||||
enforce ? "" : ", ignoring");
|
||||
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context: %m");
|
||||
}
|
||||
if (!fcon) {
|
||||
if (!enforce)
|
||||
return 0;
|
||||
if (!enforce)
|
||||
return 0;
|
||||
|
||||
if (r == -EOPNOTSUPP)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "We appear not to have any SELinux context: %m");
|
||||
}
|
||||
|
||||
acon = fcon;
|
||||
tclass = "system";
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Failed to get current context: %m");
|
||||
}
|
||||
|
||||
(void) sd_bus_creds_get_cmdline(creds, &cmdline);
|
||||
@ -252,23 +328,67 @@ int mac_selinux_access_check_internal(
|
||||
.function = function,
|
||||
};
|
||||
|
||||
r = selinux_check_access(scon, acon, tclass, permission, &audit_info);
|
||||
if (r < 0) {
|
||||
errno = -(r = errno_or_else(EPERM));
|
||||
return check_access(scon, acon, tclass, permission, &audit_info, error);
|
||||
}
|
||||
|
||||
if (enforce)
|
||||
sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "SELinux policy denies access: %m");
|
||||
}
|
||||
int mac_selinux_access_check_varlink_internal(
|
||||
sd_varlink *link,
|
||||
const Unit *unit,
|
||||
const char *permission,
|
||||
const char *function) {
|
||||
|
||||
log_full_errno_zerook(LOG_DEBUG, r,
|
||||
"SELinux access check scon=%s tcon=%s tclass=%s perm=%s state=%s function=%s path=%s cmdline=%s: %m",
|
||||
scon, acon, tclass, permission, enforce ? "enforcing" : "permissive", function, strna(unit ? unit->fragment_path : NULL), empty_to_na(cl));
|
||||
return enforce ? r : 0;
|
||||
_cleanup_freecon_ char *fcon = NULL, *scon = NULL;
|
||||
const char *tclass, *acon;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(permission);
|
||||
assert(function);
|
||||
|
||||
r = access_init(/* error= */ NULL);
|
||||
if (r <= 0)
|
||||
return log_debug_errno(r, "Failed to init SELinux: %m");
|
||||
|
||||
/* delay call until we checked in `access_init()` if SELinux is actually enabled */
|
||||
bool enforce = mac_selinux_enforcing();
|
||||
|
||||
int fd = sd_varlink_get_fd(link);
|
||||
if (fd < 0)
|
||||
return log_debug_errno(fd, "Failed to get varlink peer fd: %m");
|
||||
|
||||
/* We should call mac_selinux_get_peer_label() here similarly to get_our_contexts().
|
||||
* See the explanation there why not. */
|
||||
if (getpeercon_raw(fd, &scon) < 0)
|
||||
return log_selinux_enforcing_errno(
|
||||
errno,
|
||||
"Failed to get peer SELinux context%s: %m",
|
||||
enforce ? "" : ", ignoring");
|
||||
|
||||
if (!scon)
|
||||
return log_selinux_enforcing_errno(
|
||||
SYNTHETIC_ERRNO(EOPNOTSUPP),
|
||||
"Peer does not have SELinux context");
|
||||
|
||||
r = get_our_contexts(unit, &acon, &tclass, &fcon);
|
||||
if (r < 0)
|
||||
return log_selinux_enforcing_errno(
|
||||
r,
|
||||
"Failed to retrieves SELinux context of current process (perm=%s)%s: %m",
|
||||
permission,
|
||||
enforce ? "" : ", ignoring");
|
||||
|
||||
struct audit_info audit_info = {
|
||||
.link = link,
|
||||
.path = unit ? unit->fragment_path : NULL,
|
||||
.function = function,
|
||||
};
|
||||
|
||||
return check_access(scon, acon, tclass, permission, &audit_info, /* error= */ NULL);
|
||||
}
|
||||
|
||||
#else /* HAVE_SELINUX */
|
||||
|
||||
int mac_selinux_access_check_internal(
|
||||
int mac_selinux_access_check_bus_internal(
|
||||
sd_bus_message *message,
|
||||
const Unit *unit,
|
||||
const char *permission,
|
||||
@ -278,4 +398,12 @@ int mac_selinux_access_check_internal(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mac_selinux_access_check_varlink_internal(
|
||||
sd_varlink *link,
|
||||
const Unit *unit,
|
||||
const char *permission,
|
||||
const char *function) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* HAVE_SELINUX */
|
||||
|
@ -3,10 +3,17 @@
|
||||
|
||||
#include "core-forward.h"
|
||||
|
||||
int mac_selinux_access_check_internal(sd_bus_message *message, const Unit *unit, const char *permission, const char *function, sd_bus_error *error);
|
||||
int mac_selinux_access_check_bus_internal(sd_bus_message *message, const Unit *unit, const char *permission, const char *function, sd_bus_error *error);
|
||||
int mac_selinux_access_check_varlink_internal(sd_varlink *link, const Unit *unit, const char *permission, const char *function);
|
||||
|
||||
#define mac_selinux_access_check(message, permission, error) \
|
||||
mac_selinux_access_check_internal((message), NULL, (permission), __func__, (error))
|
||||
mac_selinux_access_check_bus_internal((message), NULL, (permission), __func__, (error))
|
||||
|
||||
#define mac_selinux_unit_access_check(unit, message, permission, error) \
|
||||
mac_selinux_access_check_internal((message), (unit), (permission), __func__, (error))
|
||||
mac_selinux_access_check_bus_internal((message), (unit), (permission), __func__, (error))
|
||||
|
||||
#define mac_selinux_access_check_varlink(link, permission) \
|
||||
mac_selinux_access_check_varlink_internal((link), NULL, (permission), __func__)
|
||||
|
||||
#define mac_selinux_unit_access_check_varlink(unit, link, permission) \
|
||||
mac_selinux_access_check_bus_internal((link), (unit), (permission), __func__)
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/audit.h>
|
||||
#include <math.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
@ -31,7 +32,6 @@
|
||||
#include "image-policy.h"
|
||||
#include "log.h"
|
||||
#include "manager.h"
|
||||
#include "missing_audit.h"
|
||||
#include "mount-util.h"
|
||||
#include "namespace.h"
|
||||
#include "open-file.h"
|
||||
|
@ -39,48 +39,7 @@ static int manager_environment_build_json(sd_json_variant **ret, const char *nam
|
||||
return sd_json_variant_new_array_strv(ret, l);
|
||||
}
|
||||
|
||||
static int manager_context_build_json(sd_json_variant **ret, const char *name, void *userdata) {
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
_cleanup_strv_free_ char **taints = NULL;
|
||||
|
||||
taints = taint_strv();
|
||||
if (!taints)
|
||||
return -ENOMEM;
|
||||
|
||||
return sd_json_buildo(
|
||||
ASSERT_PTR(ret),
|
||||
SD_JSON_BUILD_PAIR_STRING("Version", GIT_VERSION),
|
||||
SD_JSON_BUILD_PAIR_STRING("Architecture", architecture_to_string(uname_architecture())),
|
||||
SD_JSON_BUILD_PAIR_STRING("Features", systemd_features),
|
||||
JSON_BUILD_PAIR_STRV_NON_EMPTY("Taints", taints),
|
||||
SD_JSON_BUILD_PAIR_STRV("UnitPath", m->lookup_paths.search_path),
|
||||
JSON_BUILD_PAIR_STRV_NON_EMPTY("Environment", m->transient_environment),
|
||||
SD_JSON_BUILD_PAIR_STRING("DefaultStandardOutput", exec_output_to_string(m->defaults.std_output)),
|
||||
SD_JSON_BUILD_PAIR_STRING("DefaultStandardError", exec_output_to_string(m->defaults.std_error)),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("ServiceWatchdogs", m->service_watchdogs),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("DefaultTimerAccuracyUSec", m->defaults.timer_accuracy_usec),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("DefaultTimeoutStartUSec", m->defaults.timeout_start_usec),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("DefaultTimeoutStopUSec", m->defaults.timeout_stop_usec),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("DefaultTimeoutAbortUSec", manager_default_timeout_abort_usec(m)),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("DefaultDeviceTimeoutUSec", m->defaults.device_timeout_usec),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("DefaultRestartUSec", m->defaults.restart_usec),
|
||||
JSON_BUILD_PAIR_RATELIMIT("DefaultStartLimit", &m->defaults.start_limit),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultIOAccounting", m->defaults.io_accounting),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultIPAccounting", m->defaults.ip_accounting),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultMemoryAccounting", m->defaults.memory_accounting),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultTasksAccounting", m->defaults.tasks_accounting),
|
||||
SD_JSON_BUILD_PAIR_CALLBACK("DefaultLimits", rlimit_table_build_json, m->defaults.rlimit),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("DefaultTasksMax", cgroup_tasks_max_resolve(&m->defaults.tasks_max)),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("DefaultMemoryPressureThresholdUSec", m->defaults.memory_pressure_threshold_usec),
|
||||
SD_JSON_BUILD_PAIR_STRING("DefaultMemoryPressureWatch", cgroup_pressure_watch_to_string(m->defaults.memory_pressure_watch)),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("TimerSlackNSec", (uint64_t) prctl(PR_GET_TIMERSLACK)),
|
||||
SD_JSON_BUILD_PAIR_STRING("DefaultOOMPolicy", oom_policy_to_string(m->defaults.oom_policy)),
|
||||
SD_JSON_BUILD_PAIR_INTEGER("DefaultOOMScoreAdjust", m->defaults.oom_score_adjust),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultRestrictSUIDSGID", m->defaults.restrict_suid_sgid),
|
||||
SD_JSON_BUILD_PAIR_STRING("CtrlAltDelBurstAction", emergency_action_to_string(m->cad_burst_action)));
|
||||
}
|
||||
|
||||
static int log_level_build_runtime_json(sd_json_variant **ret, const char *name, void *userdata) {
|
||||
static int log_level_build_json(sd_json_variant **ret, const char *name, void *userdata) {
|
||||
_cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
|
||||
int log_max_level = log_get_max_level();
|
||||
int r;
|
||||
@ -107,15 +66,70 @@ static int log_level_build_runtime_json(sd_json_variant **ret, const char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manager_context_build_json(sd_json_variant **ret, const char *name, void *userdata) {
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
|
||||
/* The main principle behind context/runtime split is the following:
|
||||
* If it make sense to place a property into a config/unit file it belongs to Context.
|
||||
* Otherwise it's a 'Runtime'. */
|
||||
|
||||
return sd_json_buildo(
|
||||
ASSERT_PTR(ret),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("ShowStatus", manager_get_show_status_on(m)),
|
||||
JSON_BUILD_PAIR_CALLBACK_NON_NULL("LogLevel", log_level_build_json, m),
|
||||
SD_JSON_BUILD_PAIR_STRING("LogTarget", log_target_to_string(log_get_target())),
|
||||
JSON_BUILD_PAIR_CALLBACK_NON_NULL("Environment", manager_environment_build_json, m),
|
||||
SD_JSON_BUILD_PAIR_STRING("DefaultStandardOutput", exec_output_to_string(m->defaults.std_output)),
|
||||
SD_JSON_BUILD_PAIR_STRING("DefaultStandardError", exec_output_to_string(m->defaults.std_error)),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("ServiceWatchdogs", m->service_watchdogs),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("DefaultTimerAccuracyUSec", m->defaults.timer_accuracy_usec),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("DefaultTimeoutStartUSec", m->defaults.timeout_start_usec),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("DefaultTimeoutStopUSec", m->defaults.timeout_stop_usec),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("DefaultTimeoutAbortUSec", manager_default_timeout_abort_usec(m)),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("DefaultDeviceTimeoutUSec", m->defaults.device_timeout_usec),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("DefaultRestartUSec", m->defaults.restart_usec),
|
||||
JSON_BUILD_PAIR_RATELIMIT("DefaultStartLimit", &m->defaults.start_limit),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultIOAccounting", m->defaults.io_accounting),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultIPAccounting", m->defaults.ip_accounting),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultMemoryAccounting", m->defaults.memory_accounting),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultTasksAccounting", m->defaults.tasks_accounting),
|
||||
SD_JSON_BUILD_PAIR_CALLBACK("DefaultLimits", rlimit_table_build_json, m->defaults.rlimit),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("DefaultTasksMax", cgroup_tasks_max_resolve(&m->defaults.tasks_max)),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("DefaultMemoryPressureThresholdUSec", m->defaults.memory_pressure_threshold_usec),
|
||||
SD_JSON_BUILD_PAIR_STRING("DefaultMemoryPressureWatch", cgroup_pressure_watch_to_string(m->defaults.memory_pressure_watch)),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("RuntimeWatchdogUSec", manager_get_watchdog(m, WATCHDOG_RUNTIME)),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("RebootWatchdogUSec", manager_get_watchdog(m, WATCHDOG_REBOOT)),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("KExecWatchdogUSec", manager_get_watchdog(m, WATCHDOG_KEXEC)),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("RuntimeWatchdogPreUSec", manager_get_watchdog(m, WATCHDOG_PRETIMEOUT)),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("RuntimeWatchdogPreGovernor", m->watchdog_pretimeout_governor),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("WatchdogDevice", watchdog_get_device()),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("TimerSlackNSec", (uint64_t) prctl(PR_GET_TIMERSLACK)),
|
||||
SD_JSON_BUILD_PAIR_STRING("DefaultOOMPolicy", oom_policy_to_string(m->defaults.oom_policy)),
|
||||
SD_JSON_BUILD_PAIR_INTEGER("DefaultOOMScoreAdjust", m->defaults.oom_score_adjust),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("DefaultRestrictSUIDSGID", m->defaults.restrict_suid_sgid),
|
||||
SD_JSON_BUILD_PAIR_STRING("CtrlAltDelBurstAction", emergency_action_to_string(m->cad_burst_action)),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("ConfirmSpawn", manager_get_confirm_spawn(m)),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("ControlGroup", m->cgroup_root));
|
||||
}
|
||||
|
||||
static int manager_runtime_build_json(sd_json_variant **ret, const char *name, void *userdata) {
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
dual_timestamp watchdog_last_ping;
|
||||
_cleanup_strv_free_ char **taints = NULL;
|
||||
|
||||
taints = taint_strv();
|
||||
if (!taints)
|
||||
return -ENOMEM;
|
||||
|
||||
return sd_json_buildo(
|
||||
ASSERT_PTR(ret),
|
||||
SD_JSON_BUILD_PAIR_STRING("Version", GIT_VERSION),
|
||||
SD_JSON_BUILD_PAIR_STRING("Architecture", architecture_to_string(uname_architecture())),
|
||||
SD_JSON_BUILD_PAIR_STRING("Features", systemd_features),
|
||||
JSON_BUILD_PAIR_STRV_NON_EMPTY("Taints", taints),
|
||||
SD_JSON_BUILD_PAIR_STRV("UnitPath", m->lookup_paths.search_path),
|
||||
SD_JSON_BUILD_PAIR_STRING("Virtualization", virtualization_to_string(detect_virtualization())),
|
||||
SD_JSON_BUILD_PAIR_STRING("ConfidentialVirtualization", confidential_virtualization_to_string(detect_confidential_virtualization())),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("ConfirmSpawn", manager_get_confirm_spawn(m)),
|
||||
JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("FirmwareTimestamp", &m->timestamps[MANAGER_TIMESTAMP_FIRMWARE]),
|
||||
JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("LoaderTimestamp", &m->timestamps[MANAGER_TIMESTAMP_LOADER]),
|
||||
JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("KernelTimestamp", &m->timestamps[MANAGER_TIMESTAMP_KERNEL]),
|
||||
@ -135,26 +149,15 @@ static int manager_runtime_build_json(sd_json_variant **ret, const char *name, v
|
||||
JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("InitRDGeneratorsFinishTimestamp", &m->timestamps[MANAGER_TIMESTAMP_INITRD_GENERATORS_FINISH]),
|
||||
JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("InitRDUnitsLoadStartTimestamp", &m->timestamps[MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_START]),
|
||||
JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("InitRDUnitsLoadFinishTimestamp", &m->timestamps[MANAGER_TIMESTAMP_INITRD_UNITS_LOAD_FINISH]),
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("ShowStatus", manager_get_show_status_on(m)),
|
||||
JSON_BUILD_PAIR_CALLBACK_NON_NULL("LogLevel", log_level_build_runtime_json, m),
|
||||
SD_JSON_BUILD_PAIR_STRING("LogTarget", log_target_to_string(log_get_target())),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("NNames", hashmap_size(m->units)),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("NFailedUnits", set_size(m->failed_units)),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("NJobs", hashmap_size(m->jobs)),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("NInstalledJobs", m->n_installed_jobs),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("NFailedJobs", m->n_failed_jobs),
|
||||
SD_JSON_BUILD_PAIR_REAL("Progress", manager_get_progress(m)),
|
||||
JSON_BUILD_PAIR_CALLBACK_NON_NULL("Environment", manager_environment_build_json, m),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("WatchdogDevice", watchdog_get_device()),
|
||||
JSON_BUILD_PAIR_DUAL_TIMESTAMP_NON_NULL("WatchdogLastPingTimestamp", watchdog_get_last_ping_as_dual_timestamp(&watchdog_last_ping)),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("ControlGroup", m->cgroup_root),
|
||||
SD_JSON_BUILD_PAIR_STRING("SystemState", manager_state_to_string(manager_state(m))),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("ExitCode", m->return_value),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("RuntimeWatchdogUSec", manager_get_watchdog(m, WATCHDOG_RUNTIME)),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("RuntimeWatchdogPreUSec", manager_get_watchdog(m, WATCHDOG_PRETIMEOUT)),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("RuntimeWatchdogPreGovernor", m->watchdog_pretimeout_governor),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("RebootWatchdogUSec", manager_get_watchdog(m, WATCHDOG_REBOOT)),
|
||||
JSON_BUILD_PAIR_FINITE_USEC("KExecWatchdogUSec", manager_get_watchdog(m, WATCHDOG_KEXEC)),
|
||||
SD_JSON_BUILD_PAIR_UNSIGNED("SoftRebootsCount", m->soft_reboots_count));
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <getopt.h>
|
||||
#include <linux/magic.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "sd-json.h"
|
||||
@ -23,7 +24,6 @@
|
||||
#include "log.h"
|
||||
#include "main-func.h"
|
||||
#include "memory-util.h"
|
||||
#include "missing_magic.h"
|
||||
#include "pager.h"
|
||||
#include "parse-argument.h"
|
||||
#include "parse-util.h"
|
||||
|
@ -19,7 +19,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
assert_se(fd >= 0);
|
||||
assert_se(write(fd, data, size) == (ssize_t) size);
|
||||
|
||||
(void) catalog_import_file(&h, name);
|
||||
(void) catalog_import_file(&h, fd, name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -22,8 +22,6 @@
|
||||
#include "keyring-util.h"
|
||||
#include "log.h"
|
||||
#include "memory-util.h"
|
||||
#include "missing_keyctl.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "mkdir.h"
|
||||
#include "mount-util.h"
|
||||
#include "nulstr-util.h"
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/loop.h>
|
||||
#include <linux/magic.h>
|
||||
#include <poll.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/ioctl.h>
|
||||
@ -45,8 +46,6 @@
|
||||
#include "keyring-util.h"
|
||||
#include "loop-util.h"
|
||||
#include "memory-util.h"
|
||||
#include "missing_magic.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "mkdir.h"
|
||||
#include "mkfs-util.h"
|
||||
#include "openssl-util.h"
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "homework-password-cache.h"
|
||||
#include "keyring-util.h"
|
||||
#include "log.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "string-util.h"
|
||||
#include "user-record.h"
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/magic.h>
|
||||
|
||||
#include "btrfs-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
@ -7,7 +9,6 @@
|
||||
#include "homework-quota.h"
|
||||
#include "log.h"
|
||||
#include "memory-util.h"
|
||||
#include "missing_magic.h"
|
||||
#include "quota-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "user-record.h"
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <linux/magic.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mount.h>
|
||||
#include <unistd.h>
|
||||
@ -35,8 +36,6 @@
|
||||
#include "loop-util.h"
|
||||
#include "main-func.h"
|
||||
#include "memory-util.h"
|
||||
#include "missing_magic.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "mount-util.h"
|
||||
#include "path-util.h"
|
||||
#include "recovery-key.h"
|
||||
|
@ -2,11 +2,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <linux/fscrypt.h>
|
||||
#include <sys/keyctl.h>
|
||||
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "homework-forward.h"
|
||||
#include "missing_keyctl.h"
|
||||
#include "user-record-util.h"
|
||||
|
||||
typedef struct HomeSetup {
|
||||
|
45
src/include/meson.build
Normal file
45
src/include/meson.build
Normal file
@ -0,0 +1,45 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
subdir('override/sys')
|
||||
|
||||
# Source files that provides AF_XYZ
|
||||
af_sources = files(
|
||||
'override/sys/socket.h',
|
||||
)
|
||||
|
||||
# Source files that provides ARPHRD_XYZ
|
||||
arphrd_sources = files(
|
||||
'uapi/linux/if_arp.h',
|
||||
)
|
||||
|
||||
# Source files that provides CAP_XYZ
|
||||
cap_sources = files(
|
||||
'uapi/linux/capability.h',
|
||||
)
|
||||
|
||||
# Source files that provides BPF delegate options
|
||||
bpf_delegate_sources = files(
|
||||
'uapi/linux/bpf.h',
|
||||
)
|
||||
|
||||
# Source files that provides ETHTOOL_LINK_MODE_XYZ
|
||||
ethtool_link_mode_sources = files(
|
||||
'uapi/linux/ethtool.h',
|
||||
)
|
||||
|
||||
# Source files that provides IPPROTO_XYZ
|
||||
ipproto_sources = files(
|
||||
'override/netinet/in.h',
|
||||
'uapi/linux/in.h',
|
||||
)
|
||||
|
||||
# Source files that provides AUDIT_XYZ
|
||||
audit_sources = files(
|
||||
'override/linux/audit.h',
|
||||
)
|
||||
|
||||
# Source files that provides KEY_XYZ
|
||||
keyboard_sources = files(
|
||||
'uapi/linux/input.h',
|
||||
'uapi/linux/input-event-codes.h',
|
||||
)
|
@ -1,13 +1,15 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <linux/audit.h> /* IWYU pragma: export */
|
||||
#include_next <linux/audit.h> /* IWYU pragma: export */
|
||||
|
||||
#if HAVE_AUDIT
|
||||
# include <libaudit.h> /* IWYU pragma: export */
|
||||
#endif
|
||||
|
||||
/* We use _Static_assert() directly here instead of assert_cc()
|
||||
#include <assert.h>
|
||||
|
||||
/* We use static_assert() directly here instead of assert_cc()
|
||||
* because if we include macro.h in this header, the invocation
|
||||
* of generate-audit_type-list.sh becomes more complex.
|
||||
*/
|
||||
@ -15,17 +17,17 @@
|
||||
#ifndef AUDIT_SERVICE_START
|
||||
# define AUDIT_SERVICE_START 1130 /* Service (daemon) start */
|
||||
#else
|
||||
_Static_assert(AUDIT_SERVICE_START == 1130, "");
|
||||
static_assert(AUDIT_SERVICE_START == 1130, "");
|
||||
#endif
|
||||
|
||||
#ifndef AUDIT_SERVICE_STOP
|
||||
# define AUDIT_SERVICE_STOP 1131 /* Service (daemon) stop */
|
||||
#else
|
||||
_Static_assert(AUDIT_SERVICE_STOP == 1131, "");
|
||||
static_assert(AUDIT_SERVICE_STOP == 1131, "");
|
||||
#endif
|
||||
|
||||
#ifndef MAX_AUDIT_MESSAGE_LENGTH
|
||||
# define MAX_AUDIT_MESSAGE_LENGTH 8970
|
||||
#else
|
||||
_Static_assert(MAX_AUDIT_MESSAGE_LENGTH == 8970, "");
|
||||
static_assert(MAX_AUDIT_MESSAGE_LENGTH == 8970, "");
|
||||
#endif
|
@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <linux/bpf.h> /* IWYU pragma: export */
|
||||
#include_next <linux/bpf.h> /* IWYU pragma: export */
|
||||
|
||||
/* defined in linux/filter.h */
|
||||
/* Unconditional jumps, goto pc + off16 */
|
@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <linux/fs.h> /* IWYU pragma: export */
|
||||
#include_next <linux/fs.h> /* IWYU pragma: export */
|
||||
|
||||
/* Not exposed yet. Defined at fs/ext4/ext4.h */
|
||||
#ifndef EXT4_IOC_RESIZE_FS
|
@ -1,9 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <linux/keyctl.h> /* IWYU pragma: export */
|
||||
#include_next <linux/keyctl.h> /* IWYU pragma: export */
|
||||
|
||||
#include "forward.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/* From linux/key.h */
|
||||
#ifndef KEY_POS_VIEW
|
||||
@ -42,5 +42,5 @@ typedef int32_t key_serial_t;
|
||||
# define KEY_OTH_SETATTR 0x00000020
|
||||
# define KEY_OTH_ALL 0x0000003f
|
||||
#else
|
||||
assert_cc(KEY_OTH_ALL == 0x0000003f);
|
||||
static_assert(KEY_OTH_ALL == 0x0000003f, "");
|
||||
#endif
|
@ -1,102 +1,104 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <linux/magic.h> /* IWYU pragma: export */
|
||||
#include_next <linux/magic.h> /* IWYU pragma: export */
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/* Not exposed yet (4.20). Defined at ipc/mqueue.c */
|
||||
#ifndef MQUEUE_MAGIC
|
||||
# define MQUEUE_MAGIC 0x19800202
|
||||
#else
|
||||
assert_cc(MQUEUE_MAGIC == 0x19800202);
|
||||
static_assert(MQUEUE_MAGIC == 0x19800202, "");
|
||||
#endif
|
||||
|
||||
/* b1123ea6d3b3da25af5c8a9d843bd07ab63213f4 (4.8), dropped by 68f2736a858324c3ec852f6c2cddd9d1c777357d (v6.0) */
|
||||
#ifndef BALLOON_KVM_MAGIC
|
||||
# define BALLOON_KVM_MAGIC 0x13661366
|
||||
#else
|
||||
assert_cc(BALLOON_KVM_MAGIC == 0x13661366);
|
||||
static_assert(BALLOON_KVM_MAGIC == 0x13661366, "");
|
||||
#endif
|
||||
|
||||
/* 48b4800a1c6af2cdda344ea4e2c843dcc1f6afc9 (4.8), dropped by 68f2736a858324c3ec852f6c2cddd9d1c777357d (v6.0) */
|
||||
#ifndef ZSMALLOC_MAGIC
|
||||
# define ZSMALLOC_MAGIC 0x58295829
|
||||
#else
|
||||
assert_cc(ZSMALLOC_MAGIC == 0x58295829);
|
||||
static_assert(ZSMALLOC_MAGIC == 0x58295829, "");
|
||||
#endif
|
||||
|
||||
/* ea8157ab2ae5e914dd427e5cfab533b6da3819cd (5.3), dropped by 68f2736a858324c3ec852f6c2cddd9d1c777357d (v6.0) */
|
||||
#ifndef Z3FOLD_MAGIC
|
||||
# define Z3FOLD_MAGIC 0x33
|
||||
#else
|
||||
assert_cc(Z3FOLD_MAGIC == 0x33);
|
||||
static_assert(Z3FOLD_MAGIC == 0x33, "");
|
||||
#endif
|
||||
|
||||
/* fe030c9b85e6783bc52fe86449c0a4b8aa16c753 (5.5), dropped by 68f2736a858324c3ec852f6c2cddd9d1c777357d (v6.0) */
|
||||
#ifndef PPC_CMM_MAGIC
|
||||
# define PPC_CMM_MAGIC 0xc7571590
|
||||
#else
|
||||
assert_cc(PPC_CMM_MAGIC == 0xc7571590);
|
||||
static_assert(PPC_CMM_MAGIC == 0xc7571590, "");
|
||||
#endif
|
||||
|
||||
/* Not in mainline but included in Ubuntu */
|
||||
#ifndef SHIFTFS_MAGIC
|
||||
# define SHIFTFS_MAGIC 0x6a656a62
|
||||
#else
|
||||
assert_cc(SHIFTFS_MAGIC == 0x6a656a62);
|
||||
static_assert(SHIFTFS_MAGIC == 0x6a656a62, "");
|
||||
#endif
|
||||
|
||||
/* Not exposed yet. Defined at fs/fuse/control.c */
|
||||
#ifndef FUSE_CTL_SUPER_MAGIC
|
||||
# define FUSE_CTL_SUPER_MAGIC 0x65735543
|
||||
#else
|
||||
assert_cc(FUSE_CTL_SUPER_MAGIC == 0x65735543);
|
||||
static_assert(FUSE_CTL_SUPER_MAGIC == 0x65735543, "");
|
||||
#endif
|
||||
|
||||
/* Not exposed yet. Defined at fs/orangefs/orangefs-kernel.h */
|
||||
#ifndef ORANGEFS_DEVREQ_MAGIC
|
||||
# define ORANGEFS_DEVREQ_MAGIC 0x20030529
|
||||
#else
|
||||
assert_cc(ORANGEFS_DEVREQ_MAGIC == 0x20030529);
|
||||
static_assert(ORANGEFS_DEVREQ_MAGIC == 0x20030529, "");
|
||||
#endif
|
||||
|
||||
/* linux/gfs2_ondisk.h */
|
||||
#ifndef GFS2_MAGIC
|
||||
# define GFS2_MAGIC 0x01161970
|
||||
#else
|
||||
assert_cc(GFS2_MAGIC == 0x01161970);
|
||||
static_assert(GFS2_MAGIC == 0x01161970, "");
|
||||
#endif
|
||||
|
||||
/* Not exposed yet. Defined at fs/configfs/mount.c */
|
||||
#ifndef CONFIGFS_MAGIC
|
||||
# define CONFIGFS_MAGIC 0x62656570
|
||||
#else
|
||||
assert_cc(CONFIGFS_MAGIC == 0x62656570);
|
||||
static_assert(CONFIGFS_MAGIC == 0x62656570, "");
|
||||
#endif
|
||||
|
||||
/* Not exposed yet. Defined at fs/vboxsf/super.c */
|
||||
#ifndef VBOXSF_SUPER_MAGIC
|
||||
# define VBOXSF_SUPER_MAGIC 0x786f4256
|
||||
#else
|
||||
assert_cc(VBOXSF_SUPER_MAGIC == 0x786f4256);
|
||||
static_assert(VBOXSF_SUPER_MAGIC == 0x786f4256, "");
|
||||
#endif
|
||||
|
||||
/* Not exposed yet, internally actually called RPCAUTH_GSSMAGIC. Defined in net/sunrpc/rpc_pipe.c */
|
||||
#ifndef RPC_PIPEFS_SUPER_MAGIC
|
||||
# define RPC_PIPEFS_SUPER_MAGIC 0x67596969
|
||||
#else
|
||||
assert_cc(RPC_PIPEFS_SUPER_MAGIC == 0x67596969);
|
||||
static_assert(RPC_PIPEFS_SUPER_MAGIC == 0x67596969, "");
|
||||
#endif
|
||||
|
||||
/* Not exposed yet, defined at fs/ntfs/ntfs.h */
|
||||
#ifndef NTFS_SB_MAGIC
|
||||
# define NTFS_SB_MAGIC 0x5346544e
|
||||
#else
|
||||
assert_cc(NTFS_SB_MAGIC == 0x5346544e);
|
||||
static_assert(NTFS_SB_MAGIC == 0x5346544e, "");
|
||||
#endif
|
||||
|
||||
/* Not exposed yet, encoded literally in fs/ntfs3/super.c. */
|
||||
#ifndef NTFS3_SUPER_MAGIC
|
||||
# define NTFS3_SUPER_MAGIC 0x7366746e
|
||||
#else
|
||||
assert_cc(NTFS3_SUPER_MAGIC == 0x7366746e);
|
||||
static_assert(NTFS3_SUPER_MAGIC == 0x7366746e, "");
|
||||
#endif
|
@ -1,8 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <linux/nsfs.h> /* IWYU pragma: export */
|
||||
#include <linux/types.h>
|
||||
#include_next <linux/nsfs.h> /* IWYU pragma: export */
|
||||
|
||||
/* Root namespace inode numbers, as per include/linux/proc_ns.h in the kernel source tree, since v3.8:
|
||||
* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=98f842e675f96ffac96e6c50315790912b2812be */
|
@ -1,7 +1,8 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "forward.h"
|
||||
#include <linux/ioctl.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* This is currently not exported in the public kernel headers, but the libxfs library code part of xfsprogs
|
||||
* defines it as public header */
|
||||
@ -22,10 +23,10 @@ typedef struct xfs_fsop_geom {
|
||||
uint64_t rtblocks;
|
||||
uint64_t rtextents;
|
||||
uint64_t logstart;
|
||||
unsigned char uuid[16];
|
||||
uint8_t uuid[16];
|
||||
uint32_t sunit;
|
||||
uint32_t swidth;
|
||||
int32_t version;
|
||||
int32_t version;
|
||||
uint32_t flags;
|
||||
uint32_t logsectsize;
|
||||
uint32_t rtsectsize;
|
@ -35,3 +35,22 @@ static_assert(PF_KTHREAD == 0x00200000, "");
|
||||
#else
|
||||
static_assert(TASK_COMM_LEN == 16, "");
|
||||
#endif
|
||||
|
||||
/* glibc does not provide clone() on ia64, only clone2(). Not only that, but it also doesn't provide a
|
||||
* prototype, only the symbol in the shared library (it provides a prototype for clone(), but not the
|
||||
* symbol in the shared library). */
|
||||
#if defined(__ia64__)
|
||||
int __clone2(int (*fn)(void *), void *stack_base, size_t stack_size, int flags, void *arg);
|
||||
#define HAVE_CLONE 0
|
||||
#else
|
||||
/* We know that everywhere else clone() is available, so we don't bother with a meson check (that takes time
|
||||
* at build time) and just define it. Once the kernel drops ia64 support, we can drop this too. */
|
||||
#define HAVE_CLONE 1
|
||||
#endif
|
||||
|
||||
/* Defined since glibc-2.41.
|
||||
* Supported since kernel 3.14 (e6cfc0295c7d51b008999a8b13a44fb43f8685ea). */
|
||||
#if !HAVE_SCHED_SETATTR
|
||||
int missing_sched_setattr(pid_t pid, struct sched_attr *attr, unsigned flags);
|
||||
# define sched_setattr missing_sched_setattr
|
||||
#endif
|
9
src/include/override/signal.h
Normal file
9
src/include/override/signal.h
Normal file
@ -0,0 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include_next <signal.h>
|
||||
|
||||
#if !HAVE_RT_TGSIGQUEUEINFO
|
||||
int missing_rt_tgsigqueueinfo(pid_t tgid, pid_t tid, int sig, siginfo_t *info);
|
||||
# define rt_tgsigqueueinfo missing_rt_tgsigqueueinfo
|
||||
#endif
|
11
src/include/override/sys/bpf.h
Normal file
11
src/include/override/sys/bpf.h
Normal file
@ -0,0 +1,11 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <linux/bpf.h> /* IWYU pragma: export */
|
||||
#include <stddef.h>
|
||||
|
||||
/* Supported since kernel v3.18 (749730ce42a2121e1c88350d69478bff3994b10a). */
|
||||
#if !HAVE_BPF
|
||||
int missing_bpf(int cmd, union bpf_attr *attr, size_t size);
|
||||
# define bpf missing_bpf
|
||||
#endif
|
@ -33,6 +33,20 @@ def parse_syscall_tables(filenames):
|
||||
return {filename.split('-')[-1][:-4]: parse_syscall_table(filename)
|
||||
for filename in filenames}
|
||||
|
||||
HEADER = '''\
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* This file is generated by src/include/override/sys/generate-syscall.py. Do not edit!
|
||||
*
|
||||
* Use 'ninja -C build update-syscall-tables' to download new syscall tables,
|
||||
* and 'ninja -C build update-syscall-header' to regenerate this file.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include_next <sys/syscall.h>
|
||||
|
||||
#include <assert.h>
|
||||
'''
|
||||
|
||||
DEF_TEMPLATE_A = '''\
|
||||
|
||||
#ifndef __IGNORE_{syscall}
|
||||
@ -97,7 +111,7 @@ DEF_TEMPLATE_C = '''\
|
||||
/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
|
||||
# if defined __NR_{syscall} && __NR_{syscall} >= 0
|
||||
# if defined systemd_NR_{syscall}
|
||||
_Static_assert(__NR_{syscall} == systemd_NR_{syscall}, "");
|
||||
static_assert(__NR_{syscall} == systemd_NR_{syscall}, "");
|
||||
# endif
|
||||
# else
|
||||
# if defined __NR_{syscall}
|
||||
@ -128,16 +142,7 @@ def print_syscall_def(syscall, tables, out):
|
||||
file=out)
|
||||
|
||||
def print_syscall_defs(syscalls, tables, out):
|
||||
print('''\
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
* This file is generated by src/basic/missing_syscalls.py. Do not edit!
|
||||
*
|
||||
* Use 'ninja -C build update-syscall-tables' to download new syscall tables,
|
||||
* and 'ninja -C build update-syscall-header' to regenerate this file.
|
||||
*/
|
||||
#pragma once
|
||||
''',
|
||||
file=out)
|
||||
print(HEADER, file=out)
|
||||
print(ARCH_CHECK, file=out)
|
||||
for syscall in syscalls:
|
||||
print_syscall_def(syscall, tables, out)
|
14
src/include/override/sys/ioprio.h
Normal file
14
src/include/override/sys/ioprio.h
Normal file
@ -0,0 +1,14 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <linux/ioprio.h> /* IWYU pragma: export */
|
||||
|
||||
#if !HAVE_IOPRIO_GET
|
||||
int missing_ioprio_get(int which, int who);
|
||||
# define ioprio_get missing_ioprio_get
|
||||
#endif
|
||||
|
||||
#if !HAVE_IOPRIO_SET
|
||||
int missing_ioprio_set(int which, int who, int ioprio);
|
||||
# define ioprio_set missing_ioprio_set
|
||||
#endif
|
11
src/include/override/sys/kcmp.h
Normal file
11
src/include/override/sys/kcmp.h
Normal file
@ -0,0 +1,11 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <linux/kcmp.h> /* IWYU pragma: export */
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Supported since kernel v3.5 (d97b46a64674a267bc41c9e16132ee2a98c3347d). */
|
||||
#if !HAVE_KCMP
|
||||
int missing_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2);
|
||||
# define kcmp missing_kcmp
|
||||
#endif
|
20
src/include/override/sys/keyctl.h
Normal file
20
src/include/override/sys/keyctl.h
Normal file
@ -0,0 +1,20 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <linux/keyctl.h> /* IWYU pragma: export */
|
||||
#include <stddef.h>
|
||||
|
||||
#if !HAVE_KEYCTL
|
||||
long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);
|
||||
# define keyctl missing_keyctl
|
||||
#endif
|
||||
|
||||
#if !HAVE_ADD_KEY
|
||||
key_serial_t missing_add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid);
|
||||
# define add_key missing_add_key
|
||||
#endif
|
||||
|
||||
#if !HAVE_REQUEST_KEY
|
||||
key_serial_t missing_request_key(const char *type, const char *description, const char *callout_info, key_serial_t destringid);
|
||||
# define request_key missing_request_key
|
||||
#endif
|
14
src/include/override/sys/mempolicy.h
Normal file
14
src/include/override/sys/mempolicy.h
Normal file
@ -0,0 +1,14 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include <linux/mempolicy.h> /* IWYU pragma: export */
|
||||
|
||||
#if !HAVE_SET_MEMPOLICY
|
||||
int missing_set_mempolicy(int mode, const unsigned long *nodemask, unsigned long maxnode);
|
||||
# define set_mempolicy missing_set_mempolicy
|
||||
#endif
|
||||
|
||||
#if !HAVE_GET_MEMPOLICY
|
||||
int missing_get_mempolicy(int *mode, unsigned long *nodemask, unsigned long maxnode, void *addr, unsigned long flags);
|
||||
# define get_mempolicy missing_get_mempolicy
|
||||
#endif
|
41
src/include/override/sys/meson.build
Normal file
41
src/include/override/sys/meson.build
Normal file
@ -0,0 +1,41 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
arch_list = [
|
||||
'alpha',
|
||||
'arc',
|
||||
'arm',
|
||||
'arm64',
|
||||
'i386',
|
||||
'ia64',
|
||||
'loongarch64',
|
||||
'm68k',
|
||||
'mips64',
|
||||
'mips64n32',
|
||||
'mipso32',
|
||||
'parisc',
|
||||
'powerpc',
|
||||
'powerpc64',
|
||||
'riscv32',
|
||||
'riscv64',
|
||||
's390',
|
||||
's390x',
|
||||
'sparc',
|
||||
'x86_64'
|
||||
]
|
||||
|
||||
run_target(
|
||||
'update-syscall-tables',
|
||||
command : [update_syscall_tables_sh, meson.current_source_dir()] + arch_list)
|
||||
|
||||
syscall_list_txt = files('syscall-list.txt')
|
||||
|
||||
syscall_lists = []
|
||||
foreach arch: arch_list
|
||||
syscall_lists += files('syscalls-@0@.txt'.format(arch))
|
||||
endforeach
|
||||
|
||||
generate_syscall_py = find_program('generate-syscall.py')
|
||||
|
||||
run_target(
|
||||
'update-syscall-header',
|
||||
command : [generate_syscall_py, files('syscall.h')] + syscall_lists)
|
@ -8,10 +8,6 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "missing_syscall_def.h"
|
||||
|
||||
/* Since glibc-2.37 (774058d72942249f71d74e7f2b639f77184160a6), sys/mount.h includes linux/mount.h, and
|
||||
* we can safely include both headers in the same source file. However, we cannot do that with older glibc.
|
||||
@ -43,67 +39,56 @@ extern int umount2(const char *__special_file, int __flags) __THROW;
|
||||
|
||||
/* Open the filesystem referenced by FS_NAME so it can be configured for
|
||||
mouting. */
|
||||
/* Defined since glibc-2.36.
|
||||
* Supported since kernel v5.2 (24dcb3d90a1f67fe08c68a004af37df059d74005). */
|
||||
#if HAVE_FSOPEN
|
||||
extern int fsopen(const char *__fs_name, unsigned int __flags) __THROW;
|
||||
#else
|
||||
static inline int missing_fsopen(const char *fsname, unsigned flags) {
|
||||
return syscall(__NR_fsopen, fsname, flags);
|
||||
}
|
||||
int missing_fsopen(const char *fsname, unsigned flags);
|
||||
# define fsopen missing_fsopen
|
||||
#endif
|
||||
|
||||
/* Create a mount representation for the FD created by fsopen using
|
||||
FLAGS with ATTR_FLAGS describing how the mount is to be performed. */
|
||||
/* Defined since glibc-2.36.
|
||||
* Supported since kernel v5.2 (93766fbd2696c2c4453dd8e1070977e9cd4e6b6d). */
|
||||
#if HAVE_FSMOUNT
|
||||
extern int fsmount(int __fd, unsigned int __flags, unsigned int __ms_flags) __THROW;
|
||||
#else
|
||||
static inline int missing_fsmount(int fd, unsigned flags, unsigned ms_flags) {
|
||||
return syscall(__NR_fsmount, fd, flags, ms_flags);
|
||||
}
|
||||
int missing_fsmount(int fd, unsigned flags, unsigned ms_flags);
|
||||
# define fsmount missing_fsmount
|
||||
#endif
|
||||
|
||||
/* Add the mounted FROM_DFD referenced by FROM_PATHNAME filesystem returned
|
||||
by fsmount in the hierarchy in the place TO_DFD reference by TO_PATHNAME
|
||||
using FLAGS. */
|
||||
/* Defined since glibc-2.36.
|
||||
* Supported since kernel v5.2 (2db154b3ea8e14b04fee23e3fdfd5e9d17fbc6ae). */
|
||||
#if HAVE_MOVE_MOUNT
|
||||
extern int move_mount(int __from_dfd, const char *__from_pathname, int __to_dfd, const char *__to_pathname, unsigned int flags) __THROW;
|
||||
#else
|
||||
static inline int missing_move_mount(
|
||||
int from_dfd,
|
||||
const char *from_pathname,
|
||||
int to_dfd,
|
||||
const char *to_pathname,
|
||||
unsigned flags) {
|
||||
|
||||
return syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd, to_pathname, flags);
|
||||
}
|
||||
int missing_move_mount(int from_dfd, const char *from_pathname, int to_dfd, const char *to_pathname, unsigned flags);
|
||||
# define move_mount missing_move_mount
|
||||
#endif
|
||||
|
||||
/* Set parameters and trigger CMD action on the FD context. KEY, VALUE,
|
||||
and AUX are used depending ng of the CMD. */
|
||||
/* Defined since glibc-2.36.
|
||||
* Supported since kernel v5.2 (ecdab150fddb42fe6a739335257949220033b782). */
|
||||
#if HAVE_FSCONFIG
|
||||
extern int fsconfig(int __fd, unsigned int __cmd, const char *__key, const void *__value, int __aux) __THROW;
|
||||
#else
|
||||
static inline int missing_fsconfig(int fd, unsigned cmd, const char *key, const void *value, int aux) {
|
||||
return syscall(__NR_fsconfig, fd, cmd, key, value, aux);
|
||||
}
|
||||
int missing_fsconfig(int fd, unsigned cmd, const char *key, const void *value, int aux);
|
||||
# define fsconfig missing_fsconfig
|
||||
#endif
|
||||
|
||||
/* Equivalent of fopen for an existing mount point. */
|
||||
#if HAVE_FSPICK
|
||||
extern int fspick(int __dfd, const char *__path, unsigned int __flags) __THROW;
|
||||
#endif
|
||||
|
||||
/* Open the mount point FILENAME in directory DFD using FLAGS. */
|
||||
/* Defined since glibc-2.36.
|
||||
* Supported since kernel v5.2 (a07b20004793d8926f78d63eb5980559f7813404). */
|
||||
#if HAVE_OPEN_TREE
|
||||
extern int open_tree(int __dfd, const char *__filename, unsigned int __flags) __THROW;
|
||||
#else
|
||||
static inline int missing_open_tree(int dfd, const char *filename, unsigned flags) {
|
||||
return syscall(__NR_open_tree, dfd, filename, flags);
|
||||
}
|
||||
int missing_open_tree(int dfd, const char *filename, unsigned flags);
|
||||
# define open_tree missing_open_tree
|
||||
#endif
|
||||
|
||||
@ -112,21 +97,20 @@ static inline int missing_open_tree(int dfd, const char *filename, unsigned flag
|
||||
directory referred to by the file descriptor dirfd. Otherwise if DFD is
|
||||
the special value AT_FDCWD then PATH is interpreted relative to the current
|
||||
working directory of the calling process. */
|
||||
/* Defined since glibc-2.36.
|
||||
* Supported since kernel v5.12 (2a1867219c7b27f928e2545782b86daaf9ad50bd). */
|
||||
#if HAVE_MOUNT_SETATTR
|
||||
extern int mount_setattr(int __dfd, const char *__path, unsigned int __flags, struct mount_attr *__uattr, size_t __usize) __THROW;
|
||||
#else
|
||||
static inline int missing_mount_setattr(int dfd, const char *path, unsigned flags, struct mount_attr *attr, size_t size) {
|
||||
return syscall(__NR_mount_setattr, dfd, path, flags, attr, size);
|
||||
}
|
||||
int missing_mount_setattr(int dfd, const char *path, unsigned flags, struct mount_attr *attr, size_t size);
|
||||
# define mount_setattr missing_mount_setattr
|
||||
#endif
|
||||
|
||||
/* Not defined in glibc yet as of glibc-2.41.
|
||||
* Supported since kernel v6.15 (c4a16820d90199409c9bf01c4f794e1e9e8d8fd8). */
|
||||
#if HAVE_OPEN_TREE_ATTR
|
||||
extern int open_tree_attr(int __dfd, const char *__filename, unsigned int __flags, struct mount_attr *__uattr, size_t __usize) __THROW;
|
||||
#else
|
||||
static inline int missing_open_tree_attr(int dfd, const char *filename, unsigned int flags, struct mount_attr *attr, size_t size) {
|
||||
return syscall(__NR_open_tree_attr, dfd, filename, flags, attr, size);
|
||||
}
|
||||
|
||||
int missing_open_tree_attr(int dfd, const char *filename, unsigned int flags, struct mount_attr *attr, size_t size);
|
||||
# define open_tree_attr missing_open_tree_attr
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user