Commit graph

2340 commits

Author SHA1 Message Date
Adrian Reber
dfea64c759 test/zdtm: avoid overwriting superclass attributes in userns_flavor
Pass name and uns as parameters to ns_flavor.__init__() instead
of overwriting them after the super constructor sets them. This
avoids the attribute-overwrite pattern flagged by CodeQL while
keeping the same behavior.

Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-16 09:34:29 +01:00
Adrian Reber
afea0d7a05 test/zdtm: add explicit returns in __criu_act
Add explicit 'return None' to all code paths in __criu_act() so
that explicit returns (returning ret on the nowait path) are not
mixed with implicit fall-through returns.

Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-16 09:34:29 +01:00
Adrian Reber
a78378a95f test/zdtm: rename unused loop variable to _
The loop iteration variable 'i' in cr() is never used inside
the loop body. Rename it to '_' to indicate it is intentionally
unused and silence the CodeQL warning.

Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-16 09:34:29 +01:00
Adrian Reber
e0ab0dba69 scripts, test: replace exit() with sys.exit()
exit() is provided by the site module for interactive use.
Use sys.exit() which is the proper way to exit from scripts.

Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-16 09:34:29 +01:00
Adrian Reber
55a55d34e8 test/shell-job: remove unreachable sys.exit()
The sys.exit(1) after a while True loop can never be reached.

Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-16 09:34:29 +01:00
Adrian Reber
3179290ca3 test/zdtm: remove unnecessary pass statements
The pass statements are redundant since the except blocks
already contain a print() call.

Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-16 09:34:29 +01:00
Adrian Reber
185f9e63ff test/exhaustive: catch Exception instead of
BaseException

Replace bare except clauses with except Exception to avoid
catching BaseException subclasses like SystemExit and
KeyboardInterrupt.

Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-16 09:34:29 +01:00
Ahmed Elaidy
b47c692bb3 zdtm: add sk-unix-dgram-cred test for SCM_CREDENTIALS checkpoint/restore
Test that SCM_CREDENTIALS ancillary messages queued in a unix
socket are correctly saved and restored by CRIU.

Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
2026-07-14 11:40:40 +02:00
Pavel Tikhomirov
8897a0fb25 zdtm: add scm10 test for scm sent unix sk with closed sender
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>

(cherry picked from commit a9b546c74f6c1e817b0790bd9621cc137bb719f3)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
2026-07-14 11:40:40 +02:00
Pavel Tikhomirov
a4f00387b8 zdtm: add scm08 test having several SCM_RIGHTS and SCM_CREDENTIALS
This allows us to catch long standing bug in vzcriu when scm-s were not
dumped properly - scm-s from second packet contained both scm-s from
first and second packet. This happenes in case there several SCM_RIGHTS
packets and at least one SCM_CREDENTIALS packets were sent to unix
socket at the same time.

Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>

(cherry picked from commit 65ea504a97506355c0a5a4d9612a4827a58d6631)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
2026-07-14 11:40:40 +02:00
Alexander Mikhalitsyn
fdd6c8ccc9 zdtm: add scm07 SCM_RIGHTS & SCM_CREDENTIALS case
Reproducer for the next problem:

When unix socket contains SCM with SCM_CREDENTIALS
cmsg_type we have to postpone saving this packet to
CR_FD_SK_QUEUES image because we need to have information
about process which creds was transfered in this message.
But if this SkPacketEntry already contains data from
SCM_RIGHTS messages (file descriptors was transfered
through unix socket) we will lose this data because of
incorrect queue_packet_entry function implementation.

This problem tends to inconsistent CRIU dump and on
restore we will get:

Error (criu/files.c:230): Empty list on file desc id 13(5)
Error (criu/files.c:232): BUG at criu/files.c:232

Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>

(cherry picked from commit 6aa13217721db06b7cbd873e615580f0a455d5a7)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
2026-07-14 11:40:40 +02:00
Cyrill Gorcunov
0dcfa267e2 zdtm: add ucreds test for unix stream sockets
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>

(cherry picked from commit ce7e4398f851d5fd2cd191134a6a7830b1f7fb94)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
2026-07-14 11:40:40 +02:00
Radostin Stoyanov
56aecf2594 test/others: Run compression benchmark in CI
The benchmark and its five data generators otherwise remain standalone
tooling, so normal CI would not notice broken integrity checks,
statistics accounting, or compression configuration.

Add a bounded smoke run for zero, mixed, pseudorandom, text, and
ELF-derived mappings. Compare uncompressed, per-page LZ4, and 64 KiB
region images with one warmup and one measured iteration, print the
results, and fail on checksum, accounting, or configuration errors.

Run the helper tests first, then build the pycriu bindings needed by the
live benchmark. Leave the host page cache untouched and enforce a
five-minute timeout. Gate the run on compression support.

Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
2026-07-14 10:17:01 +01:00
Radostin Stoyanov
deeb0f8a82 test/others: Cover all-raw compression entries
Compression can fall back to raw storage for every block in an entry.
The writer then omits compression metadata so restore can use ordinary
I/O, but that fast path also depends on a page-aligned payload.

Add per-page and region tests with an incompressible mapping. Inspect
the pagemap for an aligned 56-page entry without compression metadata,
while requiring another genuine LZ4 block to prove compression was
active. Restore through direct image I/O, require native AIO when
O_DIRECT is available, and verify the workload contents.

Run the test in CI when page compression is available.

Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
2026-07-14 10:17:01 +01:00
Radostin Stoyanov
f5fc0ddb56 test/others: Cover mixed compression chains
Successive layers in an incremental dump can use different compression
modes. Restore must interpret each layer through its own inventory and
pagemap metadata instead of applying the final image mode to the parent
chain.

Add chains with two pre-dumps and a final dump for plain-to-page,
page-to-plain, plain-to-region, and region-to-plain transitions. Toggle
a page between layers so every image carries real payload, check the
exact inventory version and compression settings, and restore the ZDTM
workload to verify its memory contents.

Run the test in CI when both page compression and memory dirty tracking
are available.

Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
2026-07-14 10:17:01 +01:00
Radostin Stoyanov
ce933af777 test/others: Test compression benchmark tooling
Benchmark output can look credible even when command construction,
configuration recovery, archive inspection, accounting, or cleanup has
drifted. Full Podman and model-serving trials are too expensive for
focused checks of those helpers.

Add fast tests that load both serving frontends against their shared
implementation while keeping their mutable state separate. Cover CRIU
option isolation, explicit automatic decompression, port-derived URLs,
inventory validation, runc.conf locking and crash recovery, metadata
preservation, secret redaction, container failure detection, response
integrity, signal handling, and cleanup.

Also verify deterministic workload generation, report normalization,
cache-control failures, and the pagemap evidence required by the
region-cache benchmark. Add the compression benchmark tree to ruff and
provide a dedicated unit target.

Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
2026-07-14 10:17:01 +01:00
Radostin Stoyanov
2d1335b755 contrib: Benchmark vLLM compression
Serving engines have different memory layouts and restore behavior, so
SGLang results do not establish the cost or correctness of compression
for vLLM.

Add a vLLM frontend to the shared Podman benchmark. Support CPU and GPU
images and the supported server entrypoint forms, compare uncompressed,
per-page LZ4, and region LZ4 images, and verify deterministic inference
after restore. Report archive, checkpoint, restore, and post-restore
request costs, and add a bounded CPU test runner.

Reuse the shared runc.conf transaction, CRIU configuration isolation,
inventory validation, secret redaction, failure diagnostics, and
cleanup semantics so both serving benchmarks follow the same
methodology.

Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
2026-07-14 10:17:01 +01:00
Radostin Stoyanov
52d5baecc8 contrib: Benchmark SGLang compression
Process-only measurements do not show how compressed pages affect a
containerized inference server, where Podman configuration, model
startup, and service readiness are part of the restore path. SGLang
also needs content validation so a quick restore cannot hide damaged
state.

Add a CPU and GPU SGLang benchmark that checkpoints through Podman.
Compare uncompressed, per-page LZ4, and region LZ4 images. Send the same
deterministic chat request before and after restore, compare response
hashes, measure archive and operation costs, and verify the compression
mode and region size recorded in the exported inventory. Derive the
local serving URL from the selected port unless one is supplied.

Podman passes CRIU options through the host-wide runc.conf. Serialize
updates with a canonical lock and crash-recovery journal, preserve file
metadata and xattrs, refuse to overwrite external changes, and restore
the original configuration on success and during error or signal
cleanup. Isolate CRIU from ambient defaults, keep access tokens out of
arguments and diagnostics, detect stopped containers during health
checks, and preserve failed artifacts. Add a bounded CPU test runner.

Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
2026-07-14 10:17:01 +01:00
Radostin Stoyanov
47f14e9469 crit: Convert memory page compression offline
CRIT can edit image metadata but cannot convert the matching page
payloads as one consistent image set. Changing either side alone can
leave pagemap, inventory, and payload data incompatible.

Add compress and decompress commands for checkpoint directories. Match
CRIU's block encoding, raw threshold, alignment, image version, parent
compatibility, and validation rules. Keep hugetlb and external-plugin
ranges raw because CRIU cannot premap them generically, and add the
Python LZ4 binding to supported dependencies.

Stage every output before replacing any image. Preserve ownership,
permissions, timestamps, xattrs, ACLs, and security metadata; create
exclusive hard-link backups; synchronize directory changes; and defer
terminating signals until the transaction has a definite result. Roll
back the complete image set after a failure and retain the recoverable
source if rollback or cleanup also fails.

Reject symlinks, non-regular images, unsupported versions, inconsistent
compression metadata, unknown modes, and truncated payloads. Recheck
source identities before replacement so a changed pathname is not
overwritten. Cover page and region images, parent chains, exceptional
mappings, metadata preservation, signals, races, and rollback failures.

Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
2026-07-14 10:17:01 +01:00
Radostin Stoyanov
b7b5052e87 test: Cover compressed page restore paths
Existing memory tests do not deliberately produce every compression
storage form or cross compression-specific batch and transport
boundaries. Regressions in zero, LZ4, raw, and mixed handling could
therefore go unnoticed.

Add neutral pages_content workloads and use them through symlinked
per-page and region-compressed variants. The same contents now run
uncompressed in ordinary sweeps, while NO_LZ4 builds skip only the
compressed variants.

Exercise compressible, incompressible, zero, mixed, file-backed, COW,
and exceptional mappings. Keep a large private zero range over nonzero
file contents so automatic restore exercises parallel zero filling when
the host has at least two available CPUs, and cannot pass by leaving an
untouched zero mapping. Size the compressible mapping at 33 MiB so
restore handles one full 32 MiB batch followed by 1 MiB of useful work.
This crosses the batch boundary with enough work to exercise read/decode
overlap. Cover pre-dump, deduplication, lazy pages, stream, direct I/O,
page server, RPC, region boundaries, incremental parent chains, and
repeated batches beyond 32 MiB. Verify restored contents in every case.

Pass both syntaxes for restore-only decompression options through the
ZDTM RPC runner. Exercise automatic concurrency in per-page and region
variants; the remaining variants retain the serial default.

Suggested-by: Andrei Vagin <avagin@google.com>
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
2026-07-14 10:17:01 +01:00
Radostin Stoyanov
3441f66b24 crtools/rpc/libcriu: Expose page compression
The compression paths have no supported user or RPC controls, and
clients cannot discover whether CRIU was built with LZ4.

Expose per-page and region compression, LZ4 acceleration, and worker
concurrency for LZ4 decoding and eligible large zero fills through the
CLI, configuration files, RPC, and libcriu. Add compression to the
feature-check API and document each interface.

Define --decompress-threads=0 as automatic worker concurrency and one as
the serial default with zero-fill workers disabled. Values above one
bound aggregate worker concurrency. Automatic mode derives a useful
width from CPU affinity and the work in each batch. Reduce explicit
requests above the available CPU count with a warning.

Document the independent two-slot encoded-input budget. A local restore
overlaps its next read only when it can reserve the second slot without
waiting; otherwise it keeps synchronous I/O.

Use the compression mode as the source of truth and validate every
related value. An explicit RPC OFF clears ambient compression settings
and rejects conflicting fields. Reject combinations unsupported by page
server, stream, TLS, and image-format paths, and cover option and RPC
precedence in the tests.

Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
2026-07-14 10:17:01 +01:00
Andrei Vagin
1325b8a3b3 apparmor: fix write check, and implement runtime fallback
When checkpointing tasks confined by stacked AppArmor profiles inside an
AppArmor namespace, CRIU compiles a permissive parasite profile using
apparmor_parser and writes it to the namespace policy replacement
interface
(/sys/kernel/security/apparmor/policy/namespaces/<ns>/.replace).

Previously, get_suspend_policy() invoked apparmor_parser with flags
(-QWL) requesting cache file generation and read the resulting cache
file. On modern AppArmor 4.x kernels, cache files include cache metadata
headers that cause the kernel policy unpacker to reject the binary blob
with EPROTONOSUPPORT (-93, "invalid profile format"). Replace the cache
mechanism by invoking apparmor_parser with the -o flag to output a clean
binary policy stream directly.

Furthermore, when writing a replacement profile blob to an AppArmor
.replace interface, successful writes return the total size of the
profile load data structure consumed or updated in the kernel (e.g.,
5233 bytes for stacked profiles), rather than the exact byte length of
the input payload (e.g., 727 bytes for a parasite profile). Checking if
(n != len) erroneously treats a successful replacement write as a
failure. Fix policy write validation to check if (n < 0).

Across Linux kernel versions, AppArmor enforces different requirements
for policy replacement blobs written to a namespace .replace interface:
- Older kernels (AppArmor 3.x / early 4.x on Ubuntu 22.04) expect blobs
  compiled without namespace headers (-n <ns>); specifying -n causes
  the kernel to load the replacement into a nested sub-namespace
  (<ns>//<ns>), leaving the active profile unchanged and causing socket
  permission failures during dump.
- Modern kernels (AppArmor 4.x on Ubuntu 26.04) reject blobs compiled
  without namespace headers with EPROTONOSUPPORT (-93, "invalid profile
  format").

Update get_suspend_policy() and write_aa_policy() to implement runtime
fallback: first try compiling without -n <ns> and writing directly to
the namespace interface for older kernels. If writing fails (n < 0),
retry compilation passing -n <ns> and write to the root interface to
satisfy modern kernels.

In addition, when restoring tasks confined by profiles inside an
AppArmor namespace on AppArmor 4.x kernels, the host root unconfined
profile remains stacked with the target namespace profile when viewed
from the root namespace (e.g., "unconfined//&:ns:profile"). Update
checkprofile() in the apparmor_stacking test to recognize and allow the
"unconfined//&" prefix when verifying restored profiles.

Assisted-by: Gemini
Signed-off-by: Andrei Vagin <avagin@google.com>
2026-07-08 20:27:12 -07:00
Dan Feigin
2e238fc652 zdtm: exercise --image-io-mode=direct in the test suite
Add an --image-io-mode passthrough to zdtm.py, set on both dump and restore
like --stream and translated into the RPC request like --pre-dump-mode. Run
maps04 with --image-io-mode=direct and maps00 with --image-io-mode=direct --rpc
in run-ci-tests.sh so the O_DIRECT dump/restore paths and the RPC handler are
exercised.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
2026-07-08 09:52:16 +01:00
Adrian Reber
1e2f7b55aa test/inhfd: remove redundant mnt_id initialization
Remove C-style pre-initialization of mnt_id to -1. The
variable is always assigned inside the loop, and the for/else
construct raises an exception if it is never set.

Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-08 09:51:25 +01:00
Adrian Reber
d85af7219a test/zdtm: remove redundant variable initializations
Remove C-style pre-initializations of variables that are always
set before use. Python does not require variables to be declared
before assignment, so sentinel values like `pid = -1`,
`status = -1`, and `stats_written = -1` are unnecessary when
the variable is unconditionally assigned in the following code.
Also drop the unused capture of __dump_process.wait() return
value in fini().

Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-08 09:51:25 +01:00
Adrian Reber
e86d144705 test: filter known harmless errors in grep_errors()
Add a regex-based ignore list to grep_errors() so that known
harmless log messages do not trigger "ERROR OVER" output. This
reduces noise when running tests with ns/uns flavors where
"Address already assigned" messages are expected and benign.

This reduces CI output by at least 14400 lines (8*450*2*2):
8 lines per occurrence, ~450 tests, 2 flavors (ns and uns),
each running with and without --mntns-compat-mode.

Assisted-by: Claude Code:claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-07 18:03:39 -07:00
Adrian Reber
b0057d1873 test/rpc: fix file handle leak in status fd reader
Use 'with' statement instead of manual open/read/close to
ensure the file is closed if read() raises an exception.

Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-07 15:02:33 +01:00
Adrian Reber
1f78f31bcd test/exhaustive: fix file handle leak in get_pipe_rw
Use 'with' statement for opening /proc fdinfo to ensure the
file handle is closed after iteration.

Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-07 15:02:33 +01:00
Adrian Reber
e54a06498c test/zdtm: fix file descriptor and handle leaks
Close the fd from os.open("/dev/null") after dup2, matching
the pattern used for stdout/stderr a few lines above. Also
convert __dump_meta() and dump() to use 'with' statements
for all file opens.

Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-07 15:02:33 +01:00
Adrian Reber
c40d1b8b10 test/crit-recode: fix file handle leak in image read
Use 'with' statement instead of open().read() to ensure the
file handle is properly closed.

Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-07 15:02:33 +01:00
Adrian Reber
a951237e25 test: adapt RPC test for restricted socket permissions
The service socket now defaults to 0600 (owner-only). Since the
test runs the setuid criu binary as a non-root user (uid 1000),
the socket ends up owned by root. Chown the socket to the test
user after service startup so it can connect, mirroring what an
administrator would do in production.

Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default

Generated with Claude Code (https://claude.ai/code)

Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-01 23:50:04 -07:00
Adrian Reber
2f846140f8 test/rpc: remove unused sys import from setup_swrk.py
Assisted-by: Claude Code (claude-opus-4-6@default)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-07-02 01:05:21 +01:00
Andrei Vagin
f298837dd6 mem: exclude not-accountable VMAs from COW
A not-accountable VMA cannot hold restored pages. If such a VMA is
matched into the COW chain, a child can inherit a parent's PROT_NONE
reservation as the target for its restored memory.

Reject not-accountable VMAs when preparing COW relationships. This makes
the child restore its pages through a separate writable premap, while the
parent's PROT_NONE reservation can still be mapped without write access.

Signed-off-by: Andrei Vagin <avagin@google.com>
Signed-off-by: Bhavik Sachdev <b.sachdev1904@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
2026-06-29 14:15:40 +01:00
Dan Feigin
8992fdb06a zdtm: test restoring many memfd mappings
Add a memfd mmap test that keeps many independent memfds alive across
checkpoint and restore, with shared and private mappings for each one.

Verify restored fd flags and offsets, mapping devices, shared mapping
contents, private COW contents, and post-restore shared/private write
semantics.

Assisted-by: Codex:gpt-5
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
2026-06-25 17:14:38 -07:00
Adrian Reber
a666df2b65 test: remove unnecessary lambda wrapper in list_tests
Pass show_test_info directly to map() instead of wrapping it
in a redundant lambda.

Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-06-19 09:01:36 -07:00
Adrian Reber
6233eaa5f0 test: replace insecure tempfile.mktemp with mkstemp
tempfile.mktemp is deprecated because it only generates a filename
without creating the file, introducing a TOCTOU race condition where
another process could create a file with the same name between the
mktemp call and the subsequent file operation.

Replace it with tempfile.mkstemp, which atomically creates the file
and returns a file descriptor, eliminating the race window.

Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-06-19 09:01:36 -07:00
Adrian Reber
9e6a535ab4 zdtm: add inotify_overlayfs test
Add a ZDTM test that verifies inotify watches on files inside an
overlayfs mount survive checkpoint/restore.

The test uses the external mount pattern (like mnt_ext_auto): in
the ZDTM_NEWNS=1 phase it creates an overlay mount before
unshare(CLONE_NEWNS), so CRIU treats it as an external mount and
does not attempt to reconstruct the overlay on restore.  After
restore the test opens the watched file and reads back the inotify
event to confirm the watch is intact.

This is needed because the test/others/overlayfs test only checks
that the process survives C/R.  This ZDTM test validates that the
inotify watch itself is properly dumped and restored by exercising
the overlay directory walk fallback added in fsnotify.c.

The test is restricted to the 'ns' flavor because the overlay
setup requires the ZDTM_NEWNS=1 lifecycle and root privileges
for mounting overlayfs.

Assisted-by: Claude Code (claude-opus-4-6):default
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-06-16 09:53:58 +01:00
Adrian Reber
40da8cea73 test/others/overlayfs: add inotify C/R test
Add a test that exercises checkpoint/restore of a process with an
inotify watch on a file inside an overlayfs mount.

The test compiles inotify_test.c (a simple program that sets up an
inotify watch and blocks reading events), starts it watching a file
on an overlay mount, dumps and restores via criu, then verifies the
restored process is still alive.

Run with: make -C test/others/overlayfs run-inotify

Assisted-by: Claude Code (claude-opus-4-6):default
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-06-16 09:53:58 +01:00
Radostin Stoyanov
d3f88bb58d zdtm: add cow02 to cover a PROT_NONE COW root
Add a test for the SIGSEGV fixed by "mem: keep COW root VMAs writable
when premapping".

The parent reserves an address range with PROT_NONE and never touches
it, so the kernel does not account it (no "ac" flag in smaps). After
fork(), the child turns the same range into a writable mapping and fills
it with data. CRIU matches COW VMAs by start/end and flags but ignores
their protection bits, so the parent's PROT_NONE, not-accountable VMA
becomes the COW root of the child's data VMA.

On restore the child inherits the root's mapping. Without the fix that
mapping is PROT_NONE, so restoring the child's pages into it faults and
the test fails at restore; with the fix it passes.

Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
2026-06-16 09:51:29 +02:00
Adrian Reber
abc9b4b1c1 test: fix unused variable warnings reported by CodeQL
Fix four "unused local/global variable" alerts reported by CodeQL:

- zdtm.py: drop unused assignment to print_next in the tail-printing
  loop at the end of grep_errors(). The return value of print_error()
  is not needed here since no further iterations follow.

- crit-recode.py: remove duplicate pycriu.images.dumps(pb) call
  inside the except handler. The same call just raised the exception,
  so re-executing it would raise again and prevent the error message
  from being printed.

- exhaustive/unix.py: drop unused msg variable. The recv() call is
  used for its blocking side effect to synchronize with the parent,
  the received data is not needed.

- others/mounts/mounts.py: rename unused loop variable i to _ in
  the range(10) iteration.

Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-06-12 09:58:15 +01:00
Adrian Reber
130df83851 test: don't build test binaries for clean command
The tst.available() and criu.available() calls were running
unconditionally for every zdtm.py subcommand (clean, list,
group, run). The zdtm_test.available() method builds umount2,
zdtm_ct, the zdtm test library, and potentially other targets.
This caused "make -C test clean" to first build all these
binaries via "./zdtm.py clean nsroot" before deleting them.

Skip the available() calls only for the clean subcommand, as
list and group still need the test binaries to be built.

Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-06-12 09:54:46 +01:00
Adrian Reber
00d38702d8 test: fix clean target paths for libcriu, rpc, and crit
The clean target referenced libcriu, rpc, and crit directories
directly, but these are located under others/. This caused
"make -C test clean" to fail with "No such file or directory"
when reaching the sub-make calls.

Fix the paths to others/libcriu, others/rpc, and others/crit.

Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-06-12 09:54:46 +01:00
Adrian Reber
ecc91dbd1f test: another clang compilation error fix
test_iters.c:29:1: error: non-void function does not return a value [-Werror,-Wreturn-type]
   29 | }
      | ^
1 error generated.
make: *** [Makefile:48: test_iters.o] Error 1

Signed-off-by: Adrian Reber <areber@redhat.com>
2026-06-11 10:03:11 +01:00
Adrian Reber
39040f44e3 test: fix compilation with clang
make[1]: Leaving directory '/criu'
clang -c test_sub.c -I/criu/test/others/libcriu/.install/include/criu -o test_sub.o -Werror
clang -c lib.c -I/criu/test/others/libcriu/.install/include/criu -o lib.o -Werror
lib.c:52:1: error: non-void function does not return a value [-Werror,-Wreturn-type]
   52 | }
      | ^
1 error generated.
make: *** [Makefile:48: lib.o] Error 1
make: Leaving directory '/criu/test/others/libcriu'

Signed-off-by: Adrian Reber <areber@redhat.com>
2026-06-11 08:51:47 +01:00
Adrian Reber
6673c9a172 test/libcriu: use CC variable instead of hardcoded gcc
If running with CC=clang it should now correctly pickup the right
compiler.

Signed-off-by: Adrian Reber <areber@redhat.com>
2026-06-11 08:51:47 +01:00
Adrian Reber
cb8d1bec11 zdtm: retry pthread_create on EAGAIN in thread-bomb
The thread-bomb test frequently fails during setup with
pthread_create() returning EAGAIN (errno 11).  The test creates
1024 threads in a tight loop from main(), and each of those
threads immediately spawns another thread that joins its
predecessor, resulting in a burst of ~2048 simultaneous thread
creations with 64KB stacks.

This burst causes transient EAGAIN errors from clone() due to
kernel resource pressure (VMA allocator contention, temporary
memory fragmentation, etc.).  The failure is not related to hard
resource limits — ulimit, threads-max, max_map_count and cgroup
pids limits are all well above the required values.  The failure
occurs both inside and outside containers and is worse on hosts
with fewer resources.

Measured failure rates on a 16GB / 9-CPU host:
  Before fix: 65% failure rate (13/20 outside container)
  After fix:  ~2.5% failure rate (1/40), and that failure was
              a C/R issue, not a pthread_create EAGAIN

Fix this by adding a pthread_create_retry() wrapper that retries
pthread_create() up to 50 times with a 10ms delay when it returns
EAGAIN.  This gives the kernel time to reclaim resources between
attempts while keeping the total worst-case retry time under one
second per thread creation.

Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-06-10 12:29:26 +01:00
Rocker Zhang
fc29bfef9d zdtm: add test for SO_SNDTIMEO and SO_RCVTIMEO
CRIU dumps and restores the SO_SNDTIMEO and SO_RCVTIMEO socket
send/receive timeout options in dump_socket_opts()/restore_socket_opts()
(criu/sockets.c), but the ZDTM suite has no dedicated coverage for them:
SO_SNDTIMEO is not exercised by any test, and SO_RCVTIMEO is only used
incidentally as a receive timeout in socket_icmp, never asserted across
checkpoint/restore.

Add socket-timeo, which sets distinct send and receive timeouts on a
socket, performs checkpoint/restore, and verifies both values survive.
Whole-second timeouts are used because the kernel stores these options
with jiffy granularity: setsockopt() may round a sub-second value to the
nearest tick depending on HZ, so a literal sub-second expectation could
fail to match the stored value regardless of checkpoint/restore. The
send and receive values differ so a mix-up between the two options is
caught.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Rocker Zhang <zhang.rocker.liyuan@gmail.com>
2026-06-10 09:55:42 +01:00
Adrian Reber
da5b7bf829 zdtm: unregister rseq before zeroing the rseq area
Starting with Linux 7.1, the kernel enforces strict read-only field
protection for the rseq V2 ABI. Userspace is no longer allowed to
modify kernel-managed fields (cpu_id_start, cpu_id, node_id, mm_cid)
while rseq is registered. Violations are detected on the next context
switch and the offending process is killed with SIGSEGV.

The rseq01 test was zeroing the entire glibc-registered rseq area
with memset() before calling test_init(), which internally calls
fork(). This corrupted the read-only fields while the glibc rseq
registration was still active, causing the kernel to send SIGSEGV
during the fork.

Fix this by calling unregister_old_rseq() before the memset in both
main() and thread_routine(), so the kernel is no longer monitoring
those fields when they are zeroed. The subsequent register_thread()
call re-registers rseq with the clean area.

Link: 7f00232152

Assisted-by: Claude Code (https://claude.ai/code):claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-05-22 11:00:24 -07:00
Bhavik Sachdev
b0b89a94f3 zdtm: check reservation mmaps are restored correctly
mmaps done just for reserving address space something like

void *addr = mmap(NULL, SIZE, PROT_NONE,
	      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

Ensure that these do not have ac flag set in /proc/pid/smaps.

Signed-off-by: Bhavik Sachdev <b.sachdev1904@gmail.com>
2026-05-07 11:45:34 -07:00
Adrian Reber
5546c06a12 zdtm: Fix rseq01 test for kernel 7.0 rseq changes
Starting with Linux 7.0, the rseq feature size has grown to 33 bytes
and AT_RSEQ_ALIGN has increased to 64.  This causes sizeof(struct rseq)
from the uapi header to be 64 (33 bytes padded to aligned(32)), while
the actual registration size used by glibc (__rseq_size) is 33.

The rseq01 test was using sizeof(struct rseq) as the registration
size and a test-local __rseq_abi variable (with only 32-byte
alignment from the uapi header) as the rseq area.  Both are
wrong on kernel 7.0:

 - The kernel now checks alignment against __alignof__(struct rseq)
   which is 64 internally; the 32-byte-aligned test variable may
   not satisfy this.

 - sizeof(struct rseq) = 64 does not match the feature size of 33
   that glibc registered with, so re-registration with a different
   size fails.

Fix by:

 - Using __rseq_size (the feature size reported by glibc) as the
   registration size instead of sizeof(struct rseq).

 - Using the glibc-provided rseq area (at thread_pointer() +
   __rseq_offset) which is allocated with proper AT_RSEQ_ALIGN
   alignment, instead of a test-local variable.

Both fall back to the previous behavior when glibc rseq support
is not available.

This mirrors the glibc fix:

    https://sourceware.org/cgit/glibc/commit/?id=67f303b47dc584f204e3f2441b9832082415eebc

Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Signed-off-by: Adrian Reber <areber@redhat.com>
2026-04-22 10:35:31 +02:00