1932 Commits
Author SHA1 Message Date
LoGin ba1694602a fix(tty): preserve raw flags across termios ABI conversions (#2267)
TCSETS and the legacy TCSETA family discard flag bits that are not named
in the kernel bitflags definitions. This differs from Linux 6.6, which
copies the raw flag words and preserves the upper 16 bits when merging
legacy termio settings.

Preserve all four raw flag words at both ABI conversion boundaries while
leaving hardware normalization to the existing driver callbacks. Keep
legacy control-character merging and baud-rate extraction unchanged.

Use bitflags difference() when restoring old hardware settings after an
unsupported driver callback. Unlike the bitflags complement operator,
it preserves unnamed bits outside the software-controlled mask, matching
tty_termios_copy_hw().

Extend the existing dunitest suite to cover all six set commands, raw
flag preservation, legacy control-character tails, input flush behavior,
EFAULT without state changes, the 18-byte page-boundary termio ABI and
zeroed padding, and console stdin settings.

Validation:
- Reproduced raw flag loss before the fix: 25 of 26 tty_termios tests
  passed, with only the new flag-preservation case failing.
- After the fix, QEMU x86_64 passed tty_termios (26), tty_tcflush (6),
  tty_pty_hangup (36), and the existing C termios smoke test.
- Verified TCSAFLUSH and legacy settings on ttyS0 stdin, plus a successful
  apt install of a local test package without the TCSAFLUSH error.
- All five added tests passed on host Linux with a PTY.
- Kernel build, Rust formatting and whitespace checks passed.

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-08 21:33:05 +08:00
LoGin 6a7c3656c6 fix(fs): correct ext4 initialization, FAT traversal and truncation (#2265)
* fix(fs): initialize ext4 block bitmaps and guard atomic truncation

Treat BLOCK_UNINIT as uninitialized allocation state before validating or
scanning a block bitmap. Previously, crossing into a lazily initialized
ext4 group could fail delayed writeback with EIO, including when chmod
forced pending CodeBuddy installation data to disk.

Reuse the mounted system metadata ranges to construct the first bitmap,
protect metadata and out-of-group bits, authenticate group descriptors,
and verify the free-block count. Share this preparation between the
transactional and direct allocators. Publish the initialized bitmap,
cleared BLOCK_UNINIT flag, counters and checksums together through the
existing transaction path, and retain the original direct rollback image.
Keep initialized-bitmap checksum validation and unrelated group flags.

Move the temporary O_TRUNC writer guard to the VFS open caller so it spans
filesystem open hooks and post-open truncation. This prevents an atomic
FUSE O_RDONLY|O_TRUNC open from modifying an executing image before the
later ETXTBSY check. Release the temporary guard before returning a
read-only descriptor; preserve writable descriptors' existing ownership.

Add real-image ext4 regression coverage for both allocation paths,
remount/data/fsck consistency, corrupt initialized checksums and an I/O
failure during first-initialization preparation. Add dunitest coverage
for cross-group write/chmod/fsync/remount and atomic FUSE truncation of a
running ELF, including read-only descriptor lifetime.

Validation:
- make kernel and formatting/diff checks passed.
- another_ext4 library: 168 tests passed.
- Host ext4 image regression: both allocation paths, checksum rejection
  and preparation failure/retry passed, with clean e2fsck checks.
- DragonOS Ext4InodeIdentity: 37 tests passed.
- DragonOS exec write-access coverage: 8 tests passed.
- Related FUSE tests: 15/17 passed; the two flag-mask failures also fail
  on the baseline with identical values. The new regression fails on
  the baseline and passes after this fix.

The FUSE destructive-open behavior also reproduces on Linux 6.8; preserve
ETXTBSY while preventing the destructive side effect. Fault injection
covers preparation failure, not an exhaustive power-loss matrix.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(fat): bound sequential reads and detach truncated cluster tails

Cold page reads restarted FAT traversal at the first cluster. Reading the
32 MiB ext4 fixture exceeded the FAT entry cache and repeatedly scanned
long prefixes, causing the Dunitest timeout before ext4 allocation began.
Keep one logical/physical read cursor under the existing inode mutex and
invalidate it when the chain can change. Forward reads now traverse only
the remaining distance without extra locks or an unbounded index.

The new fragmented-read regression also exposed an existing truncate bug:
the retained chain still referenced freed clusters. Write EOC before
freeing a nonzero truncated tail under the existing FAT lock, reuse the
locked deallocation helper, and invalidate both cached chain positions.
Correct the FAT16 EOC encoding to 0xffff.

Cover cold forward/backward reads, tail reuse, shrink/regrow and rename.
The new regression reproduces the truncate failure on the old kernel.
Validation: kernel build and formatting checks; Linux FAT32 reference;
all 3 DragonOS FAT32 tests; all 37 ext4 inode-identity tests. An independent
32 MiB cold read improved from 59.448 s to 0.311 s. FAT16 runtime testing
remains blocked by its existing fixed-root-directory support limitation.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(fat): retain unlinked files and publish truncation before reclaim

Unlink and replacement rename freed cluster chains still owned by open
files, mappings and asynchronous writeback. A live read cursor could then
return another file's data. Detach the directory entry without freeing
the chain, reuse VFS semantic retention, and reclaim only after admission
closes and the last owner releases it. Perform fallible cleanup on the
existing workqueue mechanism and integrate its completion/error state
with sync and unmount. Never retry a partially freed chain.

Centralize short-entry submission so detached files can still grow and
truncate without writing a directory slot reused by another file. Remove
a detached replacement victim from the directory cache even when a later
rename step fails.

Publish the smaller short entry before cutting and freeing the truncated
tail. Keep the new size on reclamation failure and synchronize outer
metadata on both outcomes. Continue flushing other files even when
reclamation reports a sticky error.

Add FAT regressions for cold reads after unlink/replacement, writes and
truncate/regrow through the old fd, mmap retention after close, and space
reclamation after final munmap and syncfs. Both lifetime cases fail on the
old kernel and pass on Linux FAT32 and DragonOS. Final validation passed
all five FAT tests, all 37 ext4 inode-identity tests, the kernel build and
format checks. Identical post-EOC reclamation EIO injection changes the
remounted length from the incorrect 32768 to the expected 4096 bytes.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(vfs): release inode retention before final mount shutdown

File dropped its mount pin before its writer guard. The latter still owns
canonical inode Operation retention, so lazy unmount could seal the FAT
eviction queue before the final writer release publishes reclamation.
Release writer and open-description retention before the mount pin,
matching Linux __fput access/dentry release before mntput.

Audit and repair the same ordering across the other ownership boundaries:
- ResolvedPath releases its operation pin before its mount pin.
- Failed File construction releases the transferred operation pin inside
  the constructor, before its mount-pin parameter is destroyed.
- A retained resolved-path owner covers temporary O_TRUNC admission even
  if File construction or post-open truncation fails.
- Exec loading and MM executable-image ownership release deny-write
  protection before the associated File and its mount pin.

Keep the eviction seal protocol and existing close callbacks unchanged;
no new lifecycle framework is needed.

Validation: kernel build and formatting; DragonOS exec 8/8, FAT32 5/5 and
ext4 inode identity 37/37. A manual lazy-unmount/last-writer-close/remount
check passed 64 rounds with reclaimed space. The baseline also passed
64 stress rounds, so the race is supported by the destruction-order and
ownership audit rather than a claimed deterministic runtime reproduction.
Independent agents reviewed the complete PR and follow-up before commit.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(fat): isolate reclamation workers by filesystem

The global single-worker FAT eviction queue made a fast filesystem's
syncfs and unmount wait behind another device's slow chain reclamation.
Give each FAT filesystem its own serial queue while retaining the existing
FIFO epoch, error reporting and eviction seal contracts.

Add an owned WorkQueue constructor whose worker waits with a weak queue
reference. Pending FAT work retains the filesystem until completion; when
the last queue owner disappears, Drop wakes the worker and it exits.
This avoids leaking a permanent thread per mount without introducing a
new stop protocol or changing existing global workqueues. Return worker
creation failure to the mount caller.

Validation: kernel build and formatting; FAT32 5/5 and ext4 inode identity
37/37; 64 lazy-unmount/remount rounds with no residual FAT workers. In the
same two-volume sample, fast syncfs improved from 367.392 ms to 15.812 ms
while slow reclamation continued for another 360.468 ms. Worker count
returned from two mounted-filesystem workers to zero after unmount.
Independent agents reviewed the complete PR and this follow-up before
commit, including empty queues and last-job filesystem destruction.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-08 14:47:33 +08:00
LoGin 87271de2a6 feat(mm): unify shared anonymous mappings with internal shmem files (#2266)
* feat(mm): unify shared anonymous mappings with internal shmem files

Give shared anonymous mmap and writable-capable shared /dev/zero mappings
one authoritative vm_file backed by the existing tmpfs shmem PageCache.
Independent mmap calls create independent unlinked inodes; fork, VMA splits
and mremap retain the file identity, page offsets and initial backing size.

Generalize the internal shmem constructor to accept a diagnostic name and
retain its state through an Arc<File>. Remove wrapper-owned logical-size
charges and use existing page-cache membership accounting and teardown.
Reuse the constructor for System V SHM while keeping IPC permissions,
attach accounting, IPC_RMID and SHM_LOCK in the IPC layer. Derive SYSV names
from the 32-bit IPC key.

Let the inode mmap hook return the final mapping file after originating
access checks. Forward this contract through mount, overlayfs and FUSE.
Require readable mapping fds even for PROT_NONE, and preserve Linux's
VM_SHARED/VM_MAYSHARE distinction for read-only shared mappings.

Remove AnonSharedMapping and its fault, futex, mincore, msync and mremap
branches. Use ordinary file-cache paths for shared memory and describe
retained anonymous-page inodes explicitly so read-only /dev/zero shared
futex operations return EFAULT instead of using the device inode key.
Render unlinked diagnostic names from real inode metadata in procfs.

For architectures without demand paging, populate shared shmem from the
same cache and roll back unpublished PTEs, reverse mappings and reservations
on failure. Existing architecture-level fault/SIGBUS limitations remain.

Add 20 dunitest cases covering mapping identity, sparse and concurrent
faults, MAP_POPULATE, fork, split/remap offsets and EOF, futex behavior,
permissions, final-reference accounting, and System V diagnostic names.
Register the suite in the CI whitelist and no-skip list.

Validation:
- make kernel and Rust formatting/whitespace checks passed.
- All 20 new tests passed on Linux and in an x86_64 QEMU/KVM guest.
- The guest regression run passed 276 tests, skipped 5 prerequisite-bound
  cases and failed none across 13 dunitest/gVisor binaries.
- Non-x86 architecture runtime and dedicated FUSE/overlay integration
  tests were not run.

Refs: #2186
Signed-off-by: longjin <longjin@dragonos.org>

* style(mm): use div_ceil for the shmem page count

Replace the handwritten rounded-up division in the eager shmem mapping
path with usize::div_ceil. This preserves the page count and EOF checks
while satisfying the manual_is_multiple_of lint enforced by make fmt.

Validation: make fmt completed and kernel formatting/Clippy passed.
Some existing user application directories lack fmt targets; their
formatting steps cannot be treated as passing.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-08 11:59:12 +08:00
LoGin b0c037e634 fix(elf): preserve file backing for writable load segments (#2264)
* fix(elf): preserve file backing for writable load segments

Writable PT_LOAD segments were copied into anonymous mappings. When a
standalone Bun executable discarded its embedded source with
MADV_DONTNEED, subsequent faults returned zero-filled pages instead of
reloading the executable, causing CodeBuddy to fail with a NUL syntax
error.

Map executable and interpreter file segments through the existing private
file-mmap lifecycle. Remove the duplicate eager mapping interface, reserve
the image only for the first PT_LOAD, and preserve anonymous BSS handling.
Keep explicit population for architectures without user page faults and
handle short reads and protected user-copy failures.

Use a single unevictable shmem page cache for RamFS file contents so lazy
ELF faults preserve RamFS execution and buffered/shared/private mapping
semantics. Serialize size changes and retain truncate invalidation and
fallocate allocation behavior.

Allow user buffers within the final partial file page while rejecting
pages beyond EOF. Initialize CR0.WP during x86 AP startup: removing eager
ELF copies exposed reliance on their incidental write-protection enable.

Add 13 dunitest cases covering ELF discard/refault, private writes, fork,
BSS, EOF buffers, and RamFS execution and data consistency.

Validation:
- make kernel; RISC-V and LoongArch kernel compile checks
- New regression suite: 13/13 on Linux and DragonOS
- DragonOS focused regression suites: 48/48 total
- Identical CodeBuddy 2.147.0 binary: pre-fix NUL syntax error and exit 1;
  post-fix default startup reports version and exits 0
- Both x86 CPUs have CR0.WP enabled; exec ABI and clear_child_tid pass
- Targeted rustfmt and git diff --check

Cross-architecture guest execution, full initramfs boot, and the complete
gVisor suite were not run.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ramfs): roll back failed page preallocation

RamFS fallocate published each new unevictable page before the entire
allocation completed. An intermediate ENOMEM left pages beyond the old
EOF resident even though inode size and metadata were not committed.

Extract the existing tmpfs preallocation loop into PageCacheManager and
reuse it from both filesystems. Track only newly created page identities,
reserve rollback metadata fallibly, and discard transaction-private pages
on failure through the existing lifecycle helper. Retain pages acquired,
mapped or dirtied by other users and publish inode metadata only after
successful allocation. Keep tmpfs quota admission in the filesystem.

Extend the accounting selftest with an isolated backend that fails page
admission with ENOMEM. Verify repeated partial failures do not accumulate
pages, existing data and identity survive, dirty and pinned pages are
protected, retry succeeds, and teardown releases accounting.

Validation:
- Original allocation loop fails the injected rollback check in DragonOS
- make kernel, targeted rustfmt, and git diff --check pass
- DragonOS accounting dunitest: 1/1, including the new rollback assertions
- DragonOS fallocate semantics: 8/8; ELF/RamFS regression suite: 13/13
- Tmpfs ENOSPC/data/EOF preservation and retry check passes on Linux and
  DragonOS
- Independent adversarial review found no remaining blocking issues

Signed-off-by: longjin <longjin@dragonos.org>

* fix(mm): roll back uncommitted page-cache write preparation

Preparing a multi-page write could leave newly allocated pages in the
cache when allocation or a later pre-publication check failed. For
unevictable RamFS mappings, pages beyond unchanged EOF then remained
resident without user-visible data being committed.

Keep write preparation in a private owner shared by all four write entry
points. Record creation status while acquiring the entry pin, reserve
copy and lock vectors fallibly, and check range arithmetic before page
creation. On failure, release pins before retiring only newly created,
still-discardable pages through the existing lifecycle helper. Preserve
existing, mapped, pinned and dirty pages. Disable cleanup after successful
publication; do not attempt to undo already published user data.

Extend the accounting selftest with isolated ENOMEM injection, rejection
by before_dirty, failed retention admission for ordinary and single-page
writes, data preservation, successful retry and balanced teardown.

Validation: the original implementation fails write_prepare_rollback in
DragonOS. make kernel, rustfmt and diff checks pass; updated accounting
selftest passes in the guest. Independent adversarial review completed
before commit with no remaining blocking issues.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ramfs): clear the EOF tail on every truncate

Full-PR review found that same-size and growing ftruncate skipped page
cache truncation, leaving shared mmap writes beyond the new EOF visible.
Linux ramfs simple_setattr calls truncate_setsize, which always truncates
the page cache after publishing the new size.

Reuse the existing page-cache resize path unconditionally while keeping
the RamFS size lock and releasing the inode mutex before MM operations.
Add a regression covering same-size and growing truncation, preserving
the first data byte while clearing the new EOF tail.

Validation: the new test passes on Linux ramfs and fails both tail-byte
assertions on the original DragonOS implementation. The fixed guest
passes ELF/RamFS 14/14, accounting 1/1, fallocate 8/8 and truncate/COW 2/2
(25 total). Kernel build and formatting checks pass. Full-PR and final
adversarial reviews found no remaining blocking issues.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(exec): retain inode write exclusion for executable images

File-backed executable pages must not be modified or truncated by another
writer. Introduce a VFS inode-wide writer/deny owner returning ETXTBSY on
conflicting admission. Reuse canonical alias coordinators as stable
identity and retain the inode across ownership; single-edge pseudo inodes
use canonical allocation identity. Registry locking never spans filesystem
operations or object destruction.

Writable regular File descriptions hold writer admission through final
close, including dup, fork and mmap references. Truncate and O_RDONLY with
O_TRUNC acquire temporary admission. No checks are added to write hot paths.

ExecParam acquires temporary deny protection before reading binary headers.
The main image transfers shared File/deny ownership to its address space;
fork inherits it and last-user mm teardown releases it after unmapping,
even when external proc-mem references remain. Script recursion releases
the old loading protection and PT_INTERP protection remains temporary,
rather than following its VMAs for their entire lifetime.

Add seven synchronized regression tests for existing writable descriptions,
running-image writes/truncate/hardlinks, fork and exec, shared mappings,
failed loads, scripts and proc-mem lifetime. Before the fix four core
exclusion tests fail in DragonOS; all seven pass on Linux and the fixed
DragonOS kernel.

Validation: make kernel, rustfmt and diff checks pass. DragonOS focused
suites pass 43/43, including exec ABI, ELF/RamFS, fallocate, proc exec,
dumpability and accounting. Full-PR and final adversarial reviews were
completed before commit with no remaining blocking issues.

Signed-off-by: longjin <longjin@dragonos.org>

* test(ramfs): verify mapped bytes exposed by file growth

Extend the EOF-tail regression to distinguish bytes newly covered by EOF
from bytes remaining beyond it. Linux ramfs preserves earlier explicit
shared-mmap writes in the newly exposed interval and clears only the tail
past the new EOF. Verify this through both the mapping and pread.

The added assertions pass on Linux ramfs and DragonOS without changing the
production growth path. Linux ramfs does not implement fallocate, so its
unsupported operation is not used as evidence for different growth rules.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ramfs): preallocate only the requested fallocate range

The resize-backed fallocate helper discarded the starting offset. After
RamFS became sparse, a small request near the end of a large hole could
therefore allocate every page from zero to the request end as unevictable
memory.

Pass the original offset through the existing atomic filesystem callback
alongside the checked end. RamFS now preallocates only intersecting pages,
matching the range used by Linux shmem_fallocate. Reject empty requests
before entering the callback and document its validated range contract.
Keep the existing size serialization, rollback helper, metadata commit,
and non-shrinking EOF behavior. Ext4 and FAT retain their resize fallback.

Add a bounded regression through a real RamFS inode to the page-cache
accounting selftest and require its result in dunitest. Cover sparse
growth, unaligned ranges, existing data, repeated allocation, preserved
EOF, and page-aligned extension across a hole.

Validation:
- The same guest regression failed before the fix at ramfs_fallocate_range.
- make kernel, rustfmt --check, and git diff --check passed.
- QEMU: accounting 1/1, fallocate 8/8, ELF/RamFS 14/14, and executable
  write protection 7/7 passed (30 tests total).
- Independent full-PR review and final-diff adversarial review found no
  additional blocking issues.

Signed-off-by: longjin <longjin@dragonos.org>

* test(vfs): cover overlay executable write exclusion lifetime

Add an actual overlay mount case alongside the executable write-access
regressions. Verify ETXTBSY while the outer writable descriptor remains
open, successful exec after closing it with a shared mapping still alive,
and successful exec after unmapping.

Linux 6.6.139 ovl_mmap replaces the VMA file with the backing file. Its
writer count belongs to the real inode, while exec deny_write_access
checks the outer overlay inode. Retaining an additional outer writer
through the mapping would change that behavior. Keep the existing kernel
semantics and record this distinction in an automated native mmap test.

Reuse the executable fixture and add bounded overlay mount cleanup. Use
native mmap/close so no library-held duplicate descriptor affects the
lifetime being tested.

Validation:
- Static musl test compilation and git diff --check passed.
- Linux 6.8 host: executable write-access suite passed 8/8, without skips.
- DragonOS QEMU with the unchanged kernel: the same suite passed 8/8.
- Independently checked the Linux 6.6.139 source paths, reviewed the full
  PR, and adversarially reviewed the final test change before commit.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-08 09:31:28 +08:00
LoGin ecef888198 fix(process): release clear_child_tid in the correct address space (#2263)
Process exit attempted to clear the registered userspace TID before checking
whether the mm had another user, and successful exec retained the old
registration. This produced EFAULT warnings for invalid addresses, could
write through an obsolete address in the new image, and omitted the wake
when writing a read-only TID word failed.

Share robust-list and clear-child-TID cleanup between exit and exec. Consume
the registration once, skip NULL and single-user-mm accesses, and attempt
the shared futex wake independently of the protected clear result, matching
Linux 6.6.139 mm_release semantics. Keep all faultable accesses outside PCB
locks and perform exec cleanup with the old mm installed through the
existing address-space switch helper. Preserve the existing mmput and
vfork completion points; consume the exit completion before waking it.

Add eight dunitests covering private/shared mm exits, NULL cancellation,
failed and successful exec, invalid mappings, and wake after a failed clear.
The read-only wake case uses an explicit phase and proc task state to prove
the waiter is blocked, without timing sleeps or requeue dependencies.

Validation:
- make kernel, rustfmt checks, and git diff --check passed on x86_64.
- Linux: 8/8 new tests passed; read-only wake passed 100 repetitions.
- DragonOS QEMU/KVM, 2 vCPUs: new tests improved from 5/8 to 8/8.
- ExecAbi 9/9, SpawnExecPipeRace 3/3, and ExecDumpableSemantics 1/1 passed
  on both the baseline and fixed kernel.
- A separate libc-free exec address-reuse probe changed from corrupting
  the new image's shared sentinel to preserving it.
- No clear-tid EFAULT warnings occurred in the fixed regression run.

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-07 17:25:06 +08:00
LoGin 27066965ac refactor(net): remove noisy debug log in rtnetlink attr parsing (#2262)
Drop an accidentally committed log::info!() call inside convert_one_from_raw_buf(), which spammed an unrelated length message on every netlink route attribute decode.

Signed-off-by: longjin <longjin@DragonOS.org>
2026-09-07 17:22:29 +08:00
LoGin 3b2d876451 feat(epoll): implement Linux-compatible epoll_pwait2 (#2261)
* feat(epoll): implement Linux-compatible epoll_pwait2

Implement syscall 441 with the native __kernel_timespec ABI and share the
wait engine with epoll_wait and epoll_pwait. Previously, valid raw calls
returned ENOSYS, preventing native event loops from using epoll_pwait2.

Convert relative timeouts into a single monotonic nanosecond deadline at
the syscall boundary, saturating oversized values at KTIME_MAX. Preserve
NULL infinite waits and zero-timeout polls. Use existing timers as wakeup
sources and verify the deadline before reporting expiry, without resetting
the timeout budget on spurious readiness.

Parse all six epoll_pwait arguments, validate non-NULL signal-mask sizes,
and share temporary-mask handling with epoll_pwait2. Restore the saved mask
on success, timeout and ordinary errors; preserve deferred restoration for
EINTR so signal delivery and sigreturn retain the original mask. Check
pending signals before expired nonzero deadlines, including 1 ns waits.

Replace direct user-buffer slices with protected per-field event writes.
Use the native epoll_event layout on each architecture without exposing
padding. Preserve unsent entries after faults or maxevents truncation,
return partial progress, and consume ET/ONESHOT state only after delivery.
Requeue unprocessed entries ahead of delivered LT entries for fairness.

Correct sigpending to intersect pending signals with the blocked mask,
as required by Linux and exposed by the pending-signal regression test.

Add 13 dunitest cases and register them in whitelist/no_skip. Cover timeout
bounds, infinite and huge waits, errno ordering, six-argument ABI, temporary
masks, SIGKILL/SIGSTOP, EINTR, protected writes and ready-list preservation.

Validation:
- Reproduced ENOSYS with raw syscall 441 on the unmodified SMP guest.
- make kernel and formatting/diff checks passed.
- All 13 new tests passed on Linux and a 4-vCPU x86_64 DragonOS guest.
- All 21 gVisor epoll tests passed, including EpollPwait2Timeout.
- All 11 existing epoll/poll/eventfd regression cases passed in the guest.

Cross-architecture guest execution and CodeBuddy startup were not tested.

Fixes #2238

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-07 16:26:42 +08:00
LoGin 747eec23e4 fix(net): implement Linux-compatible transmit queue length queries (#2259)
BusyBox ip address reports SIOCGIFTXQLEN as unimplemented for every
interface. The netdevice sysfs attribute also has no read implementation,
and rtnetlink link messages omit IFLA_TXQLEN.

Store an immutable tx_queue_len property in IfaceCommon with the Linux
6.6 default of 1000, including loopback and virtio-net. Read the same
property from the generic socket ioctl query path, rtnetlink link message
construction, and the read-only sysfs attribute.

Reuse existing ifreq copying, name normalization, socket namespace lookup,
and integer encoding so queries remain unprivileged, preserve unrelated
union bytes, and return ENODEV or EFAULT through the established paths.
Remove the sysfs attribute's unimplemented store override. Keep hardware
descriptor counts, packet processing, and queue reconfiguration unchanged.

Extend existing dunitest suites with queue-length ABI, alias, socket-family,
capability, namespace, DOWN-interface, and user-copy fault coverage. Check
that link dumps, individual link queries, ioctl, and sysfs agree even for
interfaces without IPv4 configuration.

Validation:
- make kernel and Rust formatting checks passed.
- Linux host: 8 ioctl query tests and 1 cross-interface consistency test
  passed.
- DragonOS x86_64 QEMU: 8 ioctl query, 11 rtnetlink link, and 9 ioctl
  mutation tests passed with no skips after satisfying the existing
  IPv4 enumeration fixture prerequisite.
- BusyBox ip address reports qlen 1000 for loopback and virtio-net without
  the previous warning, including an unconfigured virtio-net interface.

Fixes #2258

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-07 15:58:00 +08:00
LoGin 3ce437ee2d feat(rootfs): deterministic sysconfig payload for disk images (#2260)
- Introduce tools/build_sysconfig_payload.py, which renders a deterministic bin/sysconfig.tar from user/sysconfig-metadata.toml with numeric owner/group, explicit modes and a fixed mtime, so the payload no longer leaks host UID/GID/umask into the image.
- Replace the copy_sysconfig step (cp -r of the sysconfig tree into bin/sysroot) with prepare_sysconfig_payload, and bump the sysroot layout version so stale files left by the old copy step are never imported again as app files.
- Import the payload last in tools/write_disk_image.sh, extract with --numeric-owner/--preserve-permissions, then audit every member's type/uid/gid/mode against the tar headers; delete the image and rebuild when the payload schema version changes.
- Add a CI job that runs the payload generator's unit tests.

Signed-off-by: longjin <longjin@DragonOS.org>
2026-09-07 15:57:22 +08:00
Yuming Jiangandlongjin d53fdc91a7 feat(ipc/sem): add semaphore support for dragonOS (#2172)
* refactor(ipc): extract generic SysV IPC permission module

* feat(ipc): implement System V semaphore syscalls

* test(ipc): add SysV semaphore dunitest suite

* style(ipc): satisfy kernel formatting checks

* style(ipc): translate SysV semaphore comments to English

* fix(ipc): make IPC_SET permission updates atomic

* fix(ipc): make semaphore set allocation fallible

* feat(ipc): implement SysV SEM_UNDO lifecycle

* fix(ipc): mark allocated IDs in release builds

* fix(ipc): prioritize const semaphore waiters

* fix(process): preserve reaped PID identity

* fix(process): preserve exec locking in prepared namespace publication

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ipc): harden semaphore allocation and Linux syscall semantics

Signed-off-by: longjin <longjin@dragonos.org>

* test(fuse): handle background writeback in direct-drain assertions

Validate complete cached-page coverage before direct writes without assuming a fixed writeback partition. Cover tail-first writeback deterministically and close open files on failure to avoid contaminating later mount-isolation tests.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ipc): make bulk semaphore buffers fallible and prepare queue growth unlocked

Return ENOMEM for SETALL and GETALL buffer allocation failures. Prepare spare waiting-queue capacity only after a blocked operation needs growth, then revalidate and publish without allocating under the namespace lock. Preserve FIFO order and release replaced storage outside the lock. Add a 32000-element SETALL/GETALL regression.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ipc): prepare undo registry growth outside the namespace lock

Request spare capacity before publishing a first-time undo group. Allocate outside the manager lock, then revalidate the set and registration state before moving Weak entries into the prepared buffer. Keep replaced storage for unlocked disposal and preserve mark-after-insertion and duplicate prevention. Add coverage for competing growth and repeated registration.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ipc): scope semaphore undo cleanup and defer wakeups

Associate undo groups with each semaphore set so control operations no longer scan unrelated groups. Reuse published records for the registration fast path and preserve unlocked spare-capacity preparation.

Publish queued results under the namespace lock and drain an allocation-free completion batch after unlocking across semop, semctl and exit replay. Keep completed entries alive and detach links iteratively.

Add set-local undo and bulk removal regressions. Validate with make kernel, kernel workspace tests, 69 Linux host tests, 69 DragonOS guest tests and 20 complete guest repeats.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ipc): reclaim unused semaphore undo registry storage

Unlink retired groups using their existing records and release failed or canceled missing associations only when no published record or shared waiter remains. Preserve the original whole-group replay critical section.

Reclaim empty registries without allocation and shrink sparse registries through unlocked fallible preparation and locked revalidation. Keep allocation failure and competing growth outside syscall success semantics.

Add persistent-set undo churn and shrink revalidation coverage. Kernel and workspace builds, host capacity/failure checks, 70 Linux tests, 70 DragonOS tests and 20 full guest repeats passed.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ipc): skip empty unshare installs and cache the maximum ID index

Return no prepared install when unshare has no replacement state or undo detachment. Preserve validation and required SYSVSEM/NEWIPC work.

Track the highest used index in the existing IPC allocator, using its bitmap only when removing the maximum. Make semaphore information queries read the cache without scanning the object table.

Add allocator and syscall regressions. Validate kernel/workspace builds, four allocator tests, 50000 randomized allocator steps, installation failure injection, Linux and guest semaphore 72/72, 20 full guest repeats, and SHM 61 passed with four environment skips.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(namespace): make prepared fs copies fallible

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ipc): prepare semaphore storage outside the lock and unlink waiters directly

Signed-off-by: longjin <longjin@dragonos.org>

* fix(dunitest): use real deadlines when collecting child output

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ipc): reuse live undo records and replay one set at a time

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ipc): defer semaphore removal reclamation until after unlock

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ipc): cache wait counts and retain zero undo records

Signed-off-by: longjin <longjin@dragonos.org>

* docs: remove sem undo implementation plan and design spec

Signed-off-by: longjin <longjin@dragonos.org>

* refactor(ipc): separate semaphore state, operations and undo lifecycle

Split semaphore ABI, namespace management, atomic execution and wait queues into focused modules. Centralize terminal publication without rescanning known queues, and represent undo retirement with an explicit phase.

Preserve syscall paths, locking and deferred reclamation. Move existing tests with their owning modules and add atomic-attempt regression coverage.

Signed-off-by: longjin <longjin@dragonos.org>

* perf(ipc): preindex semaphore scratch and reclaim undo record storage

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ipc): correct semaphore ABI and index undo records

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ipc): replay detached undo outside fs publication barrier

Preserve the old IPC namespace and actor across namespace publication, then release the fs reference guard before replay. Validate copied SETALL values before checking for concurrent removal.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ipc): skip semaphore queue scans when waiter state is unchanged

Track both committed semaphore values and shared undo adjustments in the existing completion result. Preserve the result through the immediate undo path and use it for immediate scans and queued retries.

Debt-only changes must still retry waiters because they can turn a blocked shared SEM_UNDO operation into ERANGE. Add user-space coverage for immediate and queued debt-only changes.

Signed-off-by: longjin <longjin@dragonos.org>

* test(ipc): preserve creator group access after semaphore IPC_SET

Cover creator and current group membership through both primary and supplementary groups after changing gid. Check read/write access, unrelated-group denial, and the separate owner-only IPC_SET/IPC_RMID boundary.

Linux 6.6 ipcperms checks both cgid and gid, so retain the existing kernel behavior.

Signed-off-by: longjin <longjin@dragonos.org>

* perf(ipc): index semaphore set undo associations

Keep dense association storage and its group-identity index together. Prepare both buffers outside the manager lock, recheck capacity before publication, and repair moved slots on constant-time expected removal.

Preserve Weak identity lifetimes, deferred RMID cleanup, geometric growth and best-effort unlocked reclamation. Extend registry regression coverage for removal, deduplication and concurrent capacity changes.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ci): match syscall boot markers literally

The rcS marker contains brackets that were incorrectly interpreted as a regex character class, causing the monitor to misclassify a system that had already entered userspace.

Add host tests executing the actual predicate against literal, binary, CRLF, missing and misleading log inputs. Keep existing timeout and failure policies unchanged.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: mistcoversmyeyes <mingjiangyu1@qq.com>
Signed-off-by: longjin <longjin@dragonos.org>
Co-authored-by: longjin <longjin@dragonos.org>
2026-09-07 11:16:17 +08:00
LoGin 56fb0d67d1 feat(net): add namespace-aware netdevice sysfs projection (#2257)
* feat(net): add namespace-aware netdevice sysfs projection

Give netdevices in every network namespace a real kobject and sysfs lifecycle. Tag direct net class children with their owning namespace and bind each sysfs mount view to the mount-time namespace and owning user namespace.

Extend kernfs with namespace-keyed child buckets and allocation-free identity-preserving rename transactions. Route all VFS lookup and enumeration entry points through the filesystem view so same-named interfaces remain isolated without global scans or temporary lookup allocations.

Unify fresh namespace device registration, deliver uevents to the device owner, and defer final namespace device teardown to a dedicated workqueue to avoid NAPI self-wait. Return ENODEV for stale weak sysfs callbacks and roll back partially published class glue objects.

Expand rtnetlink dunitest coverage for mounted namespace projections, inode-preserving rename, stale attribute descriptors, and owner-namespace move events.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): harden namespace sysfs teardown

Keep links inside tagged netdevice directories relative to the shared sysfs hierarchy so alternate namespace-bound mounts cannot escape to the boot /sys view.

Replace the workqueue VecDeque with an intrusive pending list and preallocate each network namespace cleanup work item and payload slot during construction. Final netns release can now transfer devices and enqueue teardown without allocating or risking an allocator panic.

Extend the namespace sysfs regression test to follow the per-device subsystem link after rename and verify it resolves to the same device inode through the alternate mount.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-05 19:37:11 +08:00
LoGin 502fb750f4 refactor(net): unify link mutations across rtnetlink and ioctl (#2256)
* refactor(net): unify link mutations across rtnetlink and ioctl

Centralize link name, MTU, and configurable flag changes in an ABI-independent RTNL transaction shared by RTM_SETLINK and legacy socket ioctls.

Add Linux-compatible validation and namespace capability ordering, identity-preserving sysfs rename, runtime MTU and NOARP projection, and coherent route, neighbor, and link notifications.

Model administrative link transitions with reversible NAPI pause and driver lifecycle hooks so DOWN waits for in-flight data-plane work without conflating it with permanent teardown. Preserve device-specific VirtIO and E1000 receive semantics.

Add dunitest coverage for transaction rollback, name and flag semantics, namespace ownership, ioctl mutation, AF_PACKET down behavior, sysfs identity, and uevent delivery.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): enforce packet transmit lifecycle and MTU

Validate AF_PACKET sends against the selected interface's runtime MTU before and after copying user data. Preserve the selected interface across the copy, apply Linux-compatible Ethernet 802.1Q length handling, and share the path across send, sendto, and sendmsg.

Add a netdevice-core TX admission gate so administrative DOWN is linearized with raw driver submission instead of relying on a racy flag check. Keep fresh namespace loopback devices Linux-compatible by bringing lo up in the gVisor runner after unshare.

Cover RAW and DGRAM MTU boundaries, VLAN device-type rules, scatter-gather sendmsg, and DOWN error ordering in dunitest.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): defer constructor routes until link up

Do not publish address-derived FIB entries when a device is registered administratively down. Keep bootstrap routes independent, and let the first link-up transaction materialize every missing derived route while preserving idempotent notifications on later transitions.

Extend the fresh network namespace loopback test to verify Linux-compatible IPv4 and IPv6 route visibility, local send behavior, broadcast withdrawal, and route restoration across down/up transitions.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): support the Linux loopback MTU

Expose the standard 64 KiB loopback MTU through both ioctl and rtnetlink while expanding the software loopback packet limit to match.

Keep the configured MTU as the sole authoritative value and project it into smoltcp through an interface hook. Loopback caps that projection at the IPv4 16-bit total-length limit, avoiding malformed native IPv4 packets without introducing a second mutable MTU state.

Add dunitest coverage for the fresh-network-namespace default and for 65535-to-65536 transitions through both control-plane APIs.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): align poll retries and loopback MTU semantics

Replace recursive interface poll revalidation with fixed-frame retry loops so sustained administrative state churn cannot exhaust the kernel stack. Preserve authoritative routing upgrades across retries and release all snapshot guards before restarting.

Separate loopback's Linux-visible MTU range from smoltcp's protocol-safe projection. Apply low-MTU address teardown, FIB/source reconciliation, rename metadata, link state, and notifications as one prepared control-plane transaction. Revalidate every IPv4 UDP send against the current FIB and enforce the configured MTU at routed and loopback submission boundaries.

Match Linux IPv4 lifecycle semantics by rejecting new published IPv4 addresses with ENOBUFS while MTU is below 68. Extend rtnetlink and ioctl dunit coverage for low MTUs, rollback, address/FIB withdrawal, fixed-source and broadcast sends, and recovery.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): restore IPv4 loopback send semantics

Centralize IPv4 loopback-subnet locality and broadcast classification in the address authority so bind placement, source validation, and candidate address transactions use one policy.

Keep receive-side multicast and broadcast bind addresses separate from transmit source constraints, matching Linux inet_bind_sk behavior and allowing the route to select a valid unicast source. This restores the gVisor unbound UDP loopback and directed-broadcast cases while preserving stale-source rejection after low-MTU address withdrawal.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-05 02:23:28 +08:00
LoGin 972c818ba7 docs: migrate the documentation site from Sphinx to VitePress (#2255)
Keep English and Chinese as first-class locales, store frozen historical
versions in the repository, and remove the machine-translation pipeline.

Signed-off-by: longjin <longjin@DragonOS.org>
2026-09-04 18:06:03 +08:00
LoGin 9efb85e761 refactor(net): centralize rtnetlink neighbor state (#2253)
* refactor(net): centralize rtnetlink neighbor state

Introduce a per-network-namespace authoritative neighbor table and split neighbor responsibilities into focused Rust modules. Keep control-plane existence distinct from Ethernet data-plane eligibility so headerless devices and non-Ethernet addresses retain correct netlink lifecycle semantics without creating synthetic MAC mappings.

Align RTM_NEWNEIGH, RTM_DELNEIGH, and RTM_GETNEIGH parsing, mutation, dump, notification, and error ordering with Linux 6.6 behavior. Route IPv4 configured-neighbor output through a read-only policy view, serialize deletion with targeted smoltcp cache invalidation, and preserve lock ordering across deferred output restarts.

Update smoltcp to the merged targeted invalidation API and add QEMU dunitest coverage for lifecycle flags, strict validation, notifications, namespaces, procfs projection, control-only entries, and real Ethernet destination selection.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(tests): make neighbor UAPI checks host-independent

Use test-local Linux 6.6 wire ABI values for neighbor attributes and extended flags that are absent from older build-runner headers. This keeps the netlink serialization coverage independent of the host UAPI package without introducing a repository-wide compatibility layer.

Add regression coverage proving that fresh ordinary Ethernet PERMANENT and NOARP neighbors require a link-layer address, matching Linux __neigh_update semantics.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): support neighbor master dump filters

Normalize NDA_MASTER into Linux-compatible any, nomaster, and exact-master filter states. Since DragonOS does not yet expose a Linux-visible master/upper topology, nomaster selects current configured neighbors while exact master queries complete successfully with an empty dump instead of returning EOPNOTSUPP.

Keep filter matching and NLM_F_DUMP_FILTERED decisions in one object, preserve whole-filter fallback for malformed non-strict requests, and replace the dunitest dump helper positionals with an options object. Cover exact, nomaster, zero, and malformed master selectors.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-04 14:58:50 +08:00
LoGin 6d16d6f4ff refactor(net): make route state authoritative (#2250)
refactor(net): make route state authoritative

Implement the network control-plane architecture tracked by #2233.

- Add an authoritative per-netns FIB and indexed longest-prefix lookup.
- Make rtnetlink route, address, and link operations transactional.
- Synchronize socket routing, software forwarding, and smoltcp projections.
- Preserve Linux-compatible transport ownership, ingress identity, and TX backpressure behavior.
- Harden namespace publication, TCP registration, PCI BAR resources, and scheduler deadline handling against races and allocation failures.
- Add focused rtnetlink, networking, scheduler, and scalability coverage.

Refs: #2233

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-04 10:33:14 +08:00
LoGin 1e16411e73 feat(sched): implement sched_setparam semantics (#2252)
* feat(sched): implement sched_setparam semantics

Add the sched_setparam syscall with Linux-compatible validation, error ordering, ownership, capability, and RLIMIT_RTPRIO checks.

Route parameter-only scheduler updates through the existing queue transaction while preserving policy, reset-on-fork state, and RR slice state. Retry validation when a concurrent policy change invalidates the prepared update.

Extend scheduler dunitests for ABI boundaries, permission rules, policy preservation, no-op queue ordering, remote running tasks, and concurrent FIFO/RR policy transitions.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(sched): revalidate setparam priority at commit

Carry the RT priority observed during sched_setparam authorization into the scheduler transaction and reject the prepared update when either policy or priority changed before the runqueue-locked commit point.

This closes the stale-authorization window where a concurrent lowering could be followed by an unprivileged raise based on the older priority. Add concurrent writers coverage for the zero-RLIMIT_RTPRIO case.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-02 02:04:04 +08:00
LoGin 907ed50658 feat(sched): implement SCHED_RR timeslicing (#2251)
* feat(sched): implement SCHED_RR timeslicing

Expose SCHED_RR through the legacy scheduler ABI with Linux-compatible realtime priority validation, permission checks, policy reporting, reset-on-fork behavior, and procfs labeling.

Track the remaining round-robin quantum per task and rotate an expired task only when another runnable peer exists at the same realtime priority. Preserve the shared realtime runqueue, FIFO ordering, runtime bandwidth accounting, and migration model without introducing a parallel scheduler path.

Keep policy-only and reset-only updates aligned with Linux queue placement semantics, including full FIFO/RR transitions and an in-place reset-on-fork flag update when policy and priority are unchanged.

Extend scheduler semantics coverage for RR round trips, bounds, fork behavior, authorization, FIFO/RR transitions, equal- and mixed-policy ordering, blocking and wakeup, throttling, remote runqueues, and CPU affinity migration.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(sched): expose the RR interval query

Register sched_rr_get_interval on every supported 64-bit architecture and return the configured SCHED_RR quantum as a Linux-compatible timespec. Preserve zero intervals for FIFO and the currently sub-jiffy Fair slice.

Resolve the target before validating the userspace output buffer so negative IDs, missing TIDs, and invalid pointers follow Linux error ordering. Snapshot the policy under the existing scheduler task lock without touching the mutable remaining quantum or taking a runqueue lock.

Add dunitest coverage for raw and libc entry points, policy-specific intervals, other TIDs, invalid IDs, missing targets, bad pointers, and the exact 100 ms RR quantum.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-02 00:06:53 +08:00
LoGin 1bb5ca6453 feat(sched): expose Linux-compatible SCHED_FIFO to userspace (#2249)
Allow sched_setscheduler(2) callers to select SCHED_FIFO with the Linux priority range and permission model. Convert userspace priorities through the shared RT mapping and commit policy, priority, queue placement, and reset-on-fork state through the existing scheduler transaction.

Share resource limits across CLONE_THREAD tasks while preserving fork snapshots. Serialize hard-limit authorization and replacement, return coherent prlimit64 old values, and keep RLIMIT_NOFILE table resizing as a lock-safe best-effort optimization. Enforce CAP_SYS_RESOURCE in the initial user namespace so nested namespace capabilities cannot raise the realtime hard limit.

Extend scheduler semantics coverage for FIFO round trips, reset-on-fork, owner and target-limit authorization, thread-group limit sharing, concurrent hard-limit updates, nested user namespaces, yield ordering, runtime throttling, and remote policy-change preemption.

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-01 22:41:03 +08:00
LoGin 6685c4672b feat(sched): enforce realtime runtime bandwidth (#2248)
Add per-CPU realtime bandwidth accounting with Linux-compatible default period and runtime limits. Track elapsed RT execution under the runqueue lock, throttle exhausted RT queues, and restore their eligibility after period replenishment.

Integrate bandwidth updates into task selection, scheduler ticks, RT enqueue transitions, and class switch lifecycle. Keep throttled tasks queued locally while excluding them from the top-level runnable count and preemption decisions.

Extend the FIFO scheduler demo with a deterministic Fair observer scenario that verifies both throttling and tick-driven RT recovery on each exercised CPU.

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-01 17:44:15 +08:00
LoGin d6684b6f63 refactor(net): move boot DHCP policy to userspace (#2247)
* refactor(net): move boot DHCP policy to userspace

Complete the issue #2233 control-plane cutover by removing the kernel DHCP boot worker and selecting the primary Ethernet interface from userspace.

Add an explicit default policy, fail-closed per-interface override selection, committed DHCP policy ownership, and regular-file resolver regeneration suitable for both ext4 and the default FAT root filesystem.

Keep lease application transactional under the per-interface state lock, including active-policy validation, and schedule virtio NAPI after raw packet transmission so userspace DHCP receives immediate replies without polling unrelated drivers.

Preserve rtnetlink as the single address mutation path and remove the kernel-only DHCP ownership APIs that are no longer reachable.

Validated with make fmt, make kernel, shell syntax checks, Linux namespace integration including DHCP renew and policy races, default FAT image boot in QEMU, no-server boot, static and unmanaged transitions.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): validate network configuration ancestors

Reject network policy loads when any Unix-mode directory in the path from the root through the containing configuration directory is writable by group or other.

Reuse the existing filesystem-aware directory validator so the default FAT rootfs keeps its verified synthesized-mode exception while ext4 policy paths become resistant to ancestor replacement races.

Update the shipped operator documentation for automatic boot policy selection, explicit-policy precedence, resolver ownership, the FAT permission boundary, and the public command surface.

Validated with a pre/post writable-ancestor chroot reproducer, the full host DHCP integration matrix, make fmt and clippy, a complete default FAT image build and QEMU DHCP boot, and a fresh three-role adversarial review.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-01 17:13:40 +08:00
LoGin 43f4d72808 refactor(sched): make scheduler changes atomic (#2246)
* refactor(sched): make scheduler changes atomic

Introduce a single scheduler-change transaction that holds the task PI lock and a stable runqueue lock while updating policy, class, priority, queue placement, and reset-on-fork state.

Preserve Linux 6.6 scheduler semantics by aging and transferring Fair PELT accounting across class changes, removing dead-task contributions, honoring realtime head placement on priority drops, and requesting the required local or remote reschedule.

Centralize affinity publication under the same PI-lock boundary and make IRQ-time cross-CPU reads sound with atomic totals plus owner-local accounting.

Extend the bounded fifo_demo coverage for remote queued and running tasks, realtime ordering, policy-affinity publication and migration, policy-exit races, cleanup results, and 1/2/3-CPU behavior.

Validation:

- make fmt ARCH=x86_64 (including all-features clippy)

- x86_64 default and fifo_demo kernel builds

- x86_64 fifo_demo boots with 1, 2, and 3 vCPUs

- scheduler, affinity, tracepoint, process, and RCU dunitests

- loongarch64 kernel build

- riscv64 kernel compile, link, and ELF generation

Signed-off-by: longjin <longjin@dragonos.org>

* fix(sched): preserve migration state through switch tail

Keep running tasks marked as migrating from source runqueue dequeue until the context-switch tail owns the task PI lock. This prevents concurrent scheduler class changes from accounting against a stale source runqueue.

Make scheduler changes wait for the migration owner without contending on the PI lock, mirroring Linux task_rq_lock semantics. The switch tail now clears the transient state only while committing the destination enqueue or a completed stop, so no migrating state leaks past the transaction.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(sched): migrate fair PELT accounting between runqueues

Use the task-level migrating state to detach Fair PELT contributions from the source runqueue and reset the entity timestamp before rebinding it. Preserve ENQUEUE_MIGRATED through destination activation so the contribution is attached before the task becomes queued.

Handle queued, current, and sleeping Fair migrations under the appropriate runqueue locks, and restore the source attachment when an asynchronous stop cancels a current-task migration. Keep dormant realtime entities and new-task placement outside the Fair migration transaction.

Extend the scheduler feature test with deterministic Fair and FIFO migrations and enforce the migrated Fair timestamp invariant before destination enqueue.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-01 16:42:39 +08:00
LoGin 564b3cb412 feat(user): add dormant userspace DHCP service (#2245)
Introduce an opt-in dragon-network control plane for DHCP, static, and externally managed interfaces without changing the default kernel DHCP owner.

The service validates root-owned data-only configuration, serializes per-interface control and lease mutations, records crash-recoverable network transactions, preserves external address and route ownership, and derives managed DNS atomically under /run.

Add bounded and identity-checked udhcpc lifecycle handling, including DragonOS-compatible zombie detection, and mount /run as tmpfs during early userspace initialization. No interface configuration or startup hook is installed by default.

Validated with make fmt, make kernel, make user, isolated Linux network namespaces using BusyBox, fault-injected transaction and route-ownership scenarios, and DragonOS QEMU boot plus DHCP lifecycle smoke tests.

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-01 15:05:59 +08:00
LoGin c00c0cc51c refactor(net): centralize interface address mutations (#2243)
* refactor(net): centralize interface address mutations

Introduce a typed, RTNL-protected address mutation core that commits interface addresses, connected routes, and the router compatibility projection under one smoltcp lock. Capacity failures now roll back without exposing partial state, and runtime callers can no longer bypass the centralized path.

Route rtnetlink and the one-shot DHCP client through the core, preserve Linux 6.6 address identity and notification semantics, and keep construction-only initialization explicitly separated from published-interface mutations.

Add focused dunitest coverage for duplicate, replace, delete, parser, invalid-address, multi-address data-plane, route ownership, and capacity rollback behavior.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): preserve address and route ownership

Track in-kernel address leases with opaque generations so DHCP cannot delete a userspace-recreated address after a cross-event ABA.

Persist Linux IFA_LABEL metadata across dumps, notifications, deletes, replaces, and interface renames, including length and empty-label semantics.

Share canonical smoltcp route projections across address and rtnetlink owners, retain them until the final logical owner disappears, and isolate DHCP default-route updates from userspace defaults.

Extend dunitest coverage for both owner orders, full-table rollback and sharing, alias labels, canonical prefixes, same-subnet addresses, and failed route replacement atomicity.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): align address label policies with Linux

Preserve raw IFA_LABEL payloads until the address-family adapter can apply the matching Linux policy. Validate IPv4 labels before address and interface processing, retain explicit empty labels for deletion matching, and omit empty labels from rtnetlink output. Ignore IFA_LABEL for IPv6 requests and notifications as Linux does.

Extend rtnetlink address semantics coverage for empty and malformed IPv4 labels, error priority, IPv6 ignored labels, and attribute presence in dumps and notifications.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-01 11:05:08 +08:00
LoGin 0210af8096 refactor(sched): unify realtime runqueue model (#2244)
Rename the FIFO-specific scheduler and per-CPU queue to represent the shared realtime scheduling class while preserving the currently supported FIFO policy behavior.

Harden realtime queue invariants by validating internal priorities, deleting exactly one matching task, moving only queued tasks during yield, and checking bitmap, bucket, and running-count consistency in diagnostic builds.

Replace the unbounded FIFO demo with a feature-gated per-CPU smoke test that deterministically covers same-priority yield ordering, blocking, wakeup, task exit, and remote CPU runqueues without leaving runnable realtime workers behind.

Validation includes x86_64, riscv64, and loongarch64 kernel builds; one- and two-vCPU FIFO smoke tests; scheduler policy, affinity, tracepoint, fork/signal, and RCU dunitests.

Refs: #760

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-01 10:45:34 +08:00
LoGin 3466f18cf2 refactor(sched): separate policy from scheduler class (#2242)
Introduce explicit LinuxSchedPolicy and SchedClass types so the user-visible scheduling policy no longer doubles as the scheduler's runtime dispatch class.

Store policy and effective class separately in ProcessSchedulerInfo, initialize idle tasks before publication, and dispatch scheduler operations, accounting, RCU idle detection, PELT, and migration by class. Preserve policy-based syscall and procfs behavior without pre-modeling unsupported policies.

Remove redundant FIFO hot-path policy checks and obsolete policy branches. Extend dunitest coverage for idle/iowait accounting and the legacy proc status scheduler label.

Signed-off-by: longjin <longjin@dragonos.org>
2026-09-01 01:29:11 +08:00
LoGin 379d2fe381 test(net): cover AF_PACKET DHCP client socket semantics (#2240)
* test(net): cover AF_PACKET DHCP client socket semantics

Add deterministic AF_PACKET coverage for the socket contract used by BusyBox udhcpc.

Verify SOCK_DGRAM ETH_P_IP broadcast transmission, kernel-generated Ethernet headers, peer ingress decapsulation, sockaddr_ll metadata, and PACKET_AUXDATA fields on the built-in veth pair. Build valid DHCP-shaped IPv4/UDP packets with checksums so the tests exercise the same framing assumptions as the client without requiring a DHCP server or external network.

Keep interface indices and MAC addresses dynamic and bound all receive loops by monotonic deadlines.

Refs: #2233
Signed-off-by: longjin <longjin@dragonos.org>

* test(net): validate complete AF_PACKET DHCP frame length

Use MSG_TRUNC when observing the outgoing SOCK_DGRAM frame so recvfrom reports the complete on-wire packet length instead of the copied byte count. This prevents an oversized Ethernet frame from satisfying the exact-length assertion after silent buffer truncation.

Bound DHCP transaction matching to the bytes actually copied into the receive buffer while retaining the full returned length for the final assertion.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-31 23:59:25 +08:00
LoGin 21b7405d4a feat(sched): add legacy scheduler priority queries (#2241)
Implement sched_get_priority_min and sched_get_priority_max with the Linux 6.6 policy matrix. Keep the policy-to-range mapping in the legacy scheduler ABI layer and derive the real-time upper bound from MAX_RT_PRIO.

Decode the syscall argument as a signed 32-bit policy so raw syscall calls follow the Linux int ABI. Reject unknown policies and reset-on-fork flag combinations with EINVAL.

Extend sched_policy_semantics dunitest coverage for every supported policy, invalid values, and nonzero high syscall argument bits.

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-31 23:59:15 +08:00
LoGin 9f8eabca93 feat(sched): support reset-on-fork scheduler semantics (#2239)
* feat(sched): support reset-on-fork scheduler semantics

Align the legacy sched_getparam and sched_getscheduler interfaces with Linux by using the four-byte kernel ABI, signed TID lookup, unrestricted query semantics, consistent policy snapshots, and strict RT priority conversion.

Implement the SCHED_OTHER reset-on-fork fast path for sched_setscheduler with Linux-compatible validation ordering, owner and CAP_SYS_NICE checks, protected-flag clearing rules, and per-task fork and clone reset behavior. Keep unsupported class transitions explicit and outside the runqueue mutation path.

Tighten the internal FIFO priority endpoint, update the virtio block worker priority, and add dunitest coverage for ABI boundaries, errno ordering, other-TID access, credentials, fork, clone, and task lifetime behavior.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): reserve ifindex one for loopback

Linux assigns interface index 1 to the loopback device in every network namespace. DragonOS allocated the root loopback index from a global counter shared with device initcalls, so link-order changes could place lo after enough test interfaces that a bounded SIOCGIFCONF result omitted it.

Define the loopback index invariant once, construct loopback devices with that index, and start dynamic root-device allocation at 2. Remove the allocation-based loopback constructor and strengthen the ioctl dunitest to assert the Linux ABI value.

This restores all 41 ioctl_test cases while preserving normal interface enumeration semantics.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): avoid veth ingress MAC lock recursion

AF_PACKET classifies unicast ingress while the smoltcp interface lock is already held. VethInterface::mac previously reacquired that lock, deadlocking the NAPI worker and every later user of the interface.

Keep the immutable veth MAC address in the interface metadata and make mac() a lock-free read. Document the data-path locking contract and extend the SO_BINDTODEVICE regression to verify the interface remains usable after ingress processing.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-31 22:34:17 +08:00
LoGin 8c6f8a888e feat(net): implement SO_BINDTODEVICE for UDP sockets (#2237)
* feat(net): implement SO_BINDTODEVICE for UDP sockets

Add a reusable ifindex-based socket device binding abstraction with Linux-compatible set/get, capability, rename, and device removal semantics. Reuse the same authoritative state for raw sockets without expanding raw data-path scope.

Move UDP port ownership and demultiplexing into a network-namespace binding table. Account for bound-device overlap, dynamic SO_REUSEADDR, bind-time SO_REUSEPORT groups, and efficient per-port lookup and removal.

Honor the selected device across bind, connect, send, multicast selection, socket migration, local delivery, and receive demultiplexing. Preserve queued datagrams while moving sockets between interface socket sets and release resources on failure paths.

Add focused dunitest coverage for getsockopt behavior, invalid devices, loopback traffic, device-scoped port conflicts, dynamic reuse settings, and CAP_NET_RAW authorization.

Refs: #2233
Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): enforce UDP bound-device isolation

Prevent the UDP local-delivery fast path from crossing the interface selected by SO_BINDTODEVICE. Snapshot the effective delivery interface and source endpoint while the socket state is stable so disconnects and concurrent state changes cannot corrupt loopback metadata.

Reserve ifindex 1 for loopback in the root namespace, matching Linux and keeping SIOCGIFCONF discovery deterministic when many interfaces are present. Add focused dunitest coverage for cross-interface isolation, wildcard source selection, and the loopback ifindex contract.

Remove the PR-local interface transition gate and retain the pre-existing IP_MULTICAST_IF behavior. SO_BINDTODEVICE permanently places the UDP socket on its selected interface, so the gate was unnecessary for this feature and did not solve per-datagram egress for asynchronous NAPI devices.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(page-cache): synchronize writeback budget selftest

Wait for production asynchronous writeback to quiesce before the debug selftest claims the global batch budget. Reserve every slot while holding the retry queue lock so normal acquisition and retry registration cannot race the selftest setup.\n\nThis removes the test-ordering failure seen when page-cache accounting runs immediately after overlayfs activity, while leaving production scheduling unchanged.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): serialize UDP interface placement updates

Model the smoltcp UDP socket's interface placement as a per-socket read/write transaction. Ordinary unicast sends retain shared concurrency, while multicast interface moves and control or lifecycle updates use exclusive ownership.\n\nThis prevents a concurrent SO_BINDTODEVICE update, multicast-interface publish, close, disconnect, or socket recreation from being overwritten by a stale post-send interface restore. Connected destination changes also participate in the transaction so send classification remains coherent.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-31 17:42:24 +08:00
LoGin f8239b1310 feat(time): support timerfd syscalls (#2231)
* feat(time): support timerfd syscalls

Implement Linux 6.6-compatible timerfd_create, timerfd_settime, and timerfd_gettime for realtime, monotonic, boottime, and alarm clock domains.

Add one-shot and periodic expiration accounting, relative and absolute deadlines, nonblocking and close-on-exec flags, poll/epoll readiness, realtime clock-change rebasing, CANCEL_ON_SET handling, and safe final-close cleanup.

Integrate timerfd with VFS open-file flags and Linux noop_llseek/read semantics. Add focused dunitest coverage and enable the corresponding gVisor timerfd test target in the whitelist.

Validated with make kernel, the timerfd dunitest in DragonOS QEMU, and related eventfd, poll, epoll, and timekeeping regression suites.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(time): make timer rebasing scalable

Replace the globally sorted timer vector with a BTreeMap keyed by the immutable expiration and stable timer address. This keeps activation and cancellation logarithmic, preserves independent timers with identical deadlines, and removes the self-referential Weak pointer from Timer.

Add coverage for identical-deadline timerfd cancellation. Align dunitest startup monitoring with its configured startup budget, and raise the actively progressing gVisor suite budget to 55 minutes while retaining idle and job-level bounds.

This avoids quadratic timerfd clock-change rebasing and fixes the two CI failures without changing timerfd disarm semantics or adding a test whitelist.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(timerfd): linearize clock-set notifications

Record a timekeeping clock-set epoch whenever the realtime offset actually changes. Capture realtime and the epoch atomically when arming an absolute realtime timerfd, then ignore delayed notifications for the epoch already observed by that configuration.

This prevents a timerfd armed after a wall-clock update from being canceled or redundantly rebased by the update's late notification. The epoch also avoids offset-token ABA across consecutive clock changes while preserving existing cancellation consumption semantics.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(vfs): preserve record readv fault semantics

Defer iovec mapping and permission faults until the protected data copy, matching Linux import_iovec behavior.

Route record-oriented readv calls through the existing direct-user read path one iovec at a time. This preserves legacy scalar-read segmentation while allowing timerfd and inotify to retain their consume-before-copy ordering. Publish ACCESS once at the vector syscall boundary and cover timerfd split and invalid-buffer behavior with dunitest.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(timerfd): prune expired realtime registrations

Remove expired non-cancel realtime timerfds during the first clock-change traversal so stale entries do not impose repeated O(N) scans.

Re-register periodic timers before sampling the realtime epoch when lazy forwarding needs them again, while keeping CANCEL_ON_SET membership intact. Add realtime-absolute periodic regression coverage for lazy rearm and subsequent expiration.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(vfs): preserve socket readv fault semantics

Route socket readv through a vectored UserBuffer so the receive operation copies directly into the caller iovecs and reports only a committed socket read.

Make AF_UNIX stream, TCP, and AF_VSOCK stream consumption transactional with protected user copies, while retaining Linux datagram-style consumption for AF_UNIX seqpacket faults. Wake blocked peer writers whenever a seqpacket record is consumed.

Add Linux-compatible regressions for later-iovec faults, short reads, empty socket error ordering, TCP retention, and seqpacket record consumption.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): preserve recvmsg stream data on faults

Copy TCP, AF_UNIX stream, and AF_VSOCK stream recvmsg payloads through protected vectored user buffers before committing receive-queue consumption.

Preserve TCP MSG_WAITALL, MSG_PEEK, and MSG_TRUNC behavior, retain AF_UNIX stream record metadata across partial receives, and report EFAULT for incomplete seqpacket scatter while keeping datagram consumption semantics.

Extend socket vector regressions for TCP and Unix stream recvmsg faults, TCP WAITALL continuation, and seqpacket recvmsg faults.

Signed-off-by: longjin <longjin@dragonos.org>

* style(net): simplify recvmsg wake condition

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): retain partial TCP reads on later faults

Preserve bytes copied by an earlier smoltcp receive iteration when a subsequent iteration fails. This matches Linux TCP short-read semantics and prevents an EFAULT from hiding already-consumed stream data after the receive ring wraps.

Add a deterministic dunitest that wraps the TCP receive ring, faults the later iovec, and verifies both the returned prefix and the unread tail. Enable the suite in the dunitest whitelist.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): reject partial datagram recvmsg copies

Return EFAULT when a record-oriented recvmsg cannot copy the complete selected payload into userspace. Keep stream short-read behavior unchanged, preserve records for MSG_PEEK, and retain Linux-compatible consumption after non-peeking faults.

Cover UDP and Unix datagram fault semantics for both consuming and peeking receives.

Signed-off-by: longjin <longjin@dragonos.org>

* test(net): isolate AF_PACKET receive traffic

Create explicitly bound packet receivers with protocol zero so they cannot queue wildcard traffic before bind. Give the fanout test a dedicated experimental EtherType so delayed frames from earlier cases cannot enter before group membership is complete.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): copy TCP receive data outside interface lock

Serialize TCP receive transactions per socket and stage direct user-buffer reads through a bounded kernel buffer. This keeps faultable user copies out of the interface-wide SocketSet critical section while preserving copy-before-consume semantics across EFAULT and terminal TCP transitions.\n\nAdd a concurrent readv regression test to verify that two readers neither duplicate nor lose stream data during peek-and-commit transactions.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-31 14:24:21 +08:00
LoGin 094fa1b877 feat(net): support Linux network device query ioctls (#2236)
* feat(net): support Linux network device query ioctls

Add a shared, query-only socket ioctl adapter for SIOCGIFINDEX, SIOCGIFFLAGS, SIOCGIFMTU, and SIOCGIFHWADDR. Resolve devices through the namespace captured by each socket so descriptors retain Linux sock_net() behavior across namespace changes.

Move SIOCGIFCONF into the adapter, serialize its multi-device snapshot with RTNL, remove synthetic loopback ordering, and copy data after releasing the lock. Only write back ifc_len, matching Linux while avoiding structure-padding disclosure.

Add host/DragonOS coverage for ABI field widths, aliases, user-copy faults, unprivileged access, socket namespace stability, and ifconf padding. Remove the AF_PACKET hardware-address fallbacks so the standard ioctl path is exercised directly.

Part of #2233.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): derive user-visible interface flags

Derive IFF_RUNNING, IFF_LOWER_UP, and IFF_DORMANT from the interface lifecycle, operational, and carrier state instead of returning cached initialization flags.

Keep administratively configured receive-mode flags separate from AF_PACKET reference-counted effective modes, and use one projection for SIOCGIFFLAGS and RTM_GETLINK. Synchronize the interface START state when RTM_NEWLINK changes IFF_UP.

Add cross-ABI link state coverage and verify packet memberships update rtnetlink counters without changing configured PROMISC or ALLMULTI flags.

Signed-off-by: longjin <longjin@dragonos.org>

* test(packet): isolate fanout frames across runs

Tag each fanout load-balancing test invocation with a process- and run-specific marker so delayed frames from earlier AF_PACKET traffic cannot be counted as current input.

Continue checking the 8/8 distribution while also asserting that every current sequence is delivered exactly once, preserving coverage for broadcasts, duplicates, and drops.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-31 11:21:55 +08:00
LoGin ffe0f367fa refactor(net): serialize network control mutations with RTNL (#2235)
Add a network-owned RTNL guard and use it to serialize rtnetlink handlers, DHCP lease commits, and AF_PACKET membership updates under one explicit control-plane boundary.

Keep parsing, polling, packet registry rebuilding, and netlink response delivery outside the global lock. Make route replacement failure-atomic at fixed table capacity and add isolated dunitest coverage for concurrent mutations, same-key linearization, and ENOSPC rollback semantics.

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-31 01:41:54 +08:00
LoGin 892017b5f2 fix(net): enforce capabilities for rtnetlink mutations (#2234)
* fix(net): enforce capabilities for rtnetlink mutations

Capture immutable credentials when a netlink socket is opened and for each send operation. Carry explicit-destination metadata through the netlink datagram path so route authorization matches Linux opener and sender semantics.

Authorize every non-GET message in the Linux RTM range against the user namespace owning the socket network namespace before parsing handlers or attributes. Return per-message EPERM acknowledgements without affecting GET requests or privileged control paths.

Add dunitest coverage for mutation classes, GET dumps, opener and sender credentials, explicit destinations, user and network namespaces, unsupported RTM types, and batched requests.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(net): handle empty rtnetlink payloads

Match Linux 6.6 rtnetlink dispatch ordering by completing RTM requests with an empty payload before capability checks and message parsing. Emit a success acknowledgment only when NLM_F_ACK is requested while preserving EOPNOTSUPP precedence above RTM_MAX.

Extend the rtnetlink permission regression suite to cover empty payloads for both implemented and unsupported mutation types.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-31 00:34:32 +08:00
LoGin 151864c204 feat(rcu): implement SRCU support (#2232)
* feat(rcu): implement SRCU support

Add independent sleepable RCU domains with two-bank per-CPU reader accounting, grace-period progression, deferred callbacks, barriers, polling, and explicit lifecycle management.

Integrate SRCU with notifier chains, reboot notifiers, and tracepoints so sleepable read-side callbacks and snapshot reclamation follow Linux-compatible lifetime rules.

Extend RCU diagnostics and self-tests, add dunitest coverage, and document the architecture and correctness invariants in both Chinese and English.

Validated with make fmt and make kernel.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(rcu): reject unsafe SRCU wait contexts

Reject synchronous SRCU waits and cleanup from any deferred SRCU callback. All domains share one executor, so waiting on a different domain from that executor deadlocks just like a same-domain wait.

Make bounded task-side reader tracking fail closed after overflow so an untracked same-domain reader cannot bypass deadlock detection. Add runtime regression coverage for overflow and cross-domain callback waits, and document the shared-executor constraint.

Validated with make fmt, make kernel, and the DragonOS rcu_selftest dunitest in QEMU.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(rcu): harden SRCU reclamation ownership

Keep user-owned notifier and tracepoint destructors outside publication locks by retaining external ownership across every fallible preparation path and reclaiming snapshots only after the corresponding grace period.

Record perf tracepoint callbacks immediately after publication using pre-reserved capacity, before any fallible logging, so release can always find and unregister published BPF/JIT resources.

Restrict raw SRCU callback and in-place cleanup contracts, and document the COW notifier update boundary in both Chinese and English design documents.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-30 22:21:33 +08:00
LoGin d91156384c perf(smp): reduce maximum CPU count to 16 (#2227)
Lower the global per-CPU allocation ceiling to 16 for lightweight agent-oriented workloads. This reduces the static kernel footprint and the runtime memory reserved by scheduler, RCU, IRQ, TLB, and other per-CPU structures.

Resize the x86_64 GDT TSS descriptor area to match the new limit. Keeping the assembly table synchronized with the Rust TSS table preserves the early-boot GDT size invariant.

Validated with make kernel and a QEMU nographic boot to the DragonOS shell with two vCPUs.

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-30 17:37:58 +08:00
LoGin fd4d8fcd45 test(rcu): add reproducible regression validation (#2226)
* test(rcu): add reproducible regression validation

Add deterministic Linux-style RCU grace-period, reader-handoff, and cross-thread Arc-slot regression coverage.

Introduce an SMP torture harness with seeded logical decisions, concurrent readers and publishers, synchronous and callback reclamation, per-generation callback completion, and barrier-prefix validation. Expose bounded runs through debugfs and exercise fixed seeds through dunitest.

Keep intrusive objects in a stable boxed slice and isolate worker lifecycle ownership. If callback ownership cannot be proven, quarantine storage and poison later runs instead of risking use-after-free.

Validated with make fmt, x86_64 and RISC-V kernel builds, and the rcu_selftest_test and rcu_torture_test suites in x86_64 QEMU.

Signed-off-by: longjin <longjin@dragonos.org>

* test(rcu): handle uniprocessor selftest reports

Accept the explicit no-remote-CPU skip only when sysconf reports a single online CPU. Continue requiring the SMP litmus to complete on multi-CPU guests so CPU discovery and remote-worker regressions cannot be hidden.

Validated with make fmt and rcu_selftest_test in rebuilt one-CPU and two-CPU x86_64 QEMU guests; both configurations pass all five cases.

Signed-off-by: longjin <longjin@dragonos.org>

* test(rcu): support uniprocessor torture runs

Validate the torture report CPU count against the runtime online topology while allowing the harness to retain one reader on uniprocessor guests. Keep the multi-reader requirement for SMP and preserve all reclamation, callback, barrier, and corruption checks in both configurations.

Validated with make fmt and rcu_torture_test in rebuilt one-CPU and two-CPU x86_64 QEMU guests; both fixed seeds pass.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-30 17:30:11 +08:00
LoGin bcf46ccaea fix(tty): implement TCXONC flow control (#2225)
* fix(tty): implement TCXONC flow control

Implement the four TCXONC actions in N_TTY with job-control checks, committed termios snapshots, atomic output state transitions, and a driver xchar hook with a generic fallback.

Teach serial8250 to pause ordinary output while prioritizing flow-control characters, keep TX interrupt decisions consistent across console and IRQ paths, and reset private flow state across the first-open/last-close lifecycle. Preserve PTY packet notifications and gate virtual-terminal writes on the shared stopped state.

Add dunitest coverage for action validation, blocked-writer wakeups, custom and disabled control characters, output-postprocessing bypass, and idempotent PTY packet notifications.

Validation:
- make fmt
- make kernel
- tty_termios: 20/20 passed in DragonOS
- tty_tcflush: 6/6 passed in DragonOS
- tty_pty_hangup: 36/36 passed in DragonOS
- Python Ctrl+C produced KeyboardInterrupt without a kernel panic

Signed-off-by: longjin <longjin@dragonos.org>

* fix(tty): address flow-control races

Serialize the xchar fallback snapshot behind the TTY write lock and track external flow-control transitions. Restore a temporary stop only when no concurrent start or stop request superseded it, and issue deferred write readiness after dropping all re-entrant locks when a racing start observed the temporary running state.

Match Linux tty_port_close_start semantics for serial8250 by discarding a TCO-stopped software TX queue before waiting for already-submitted hardware bytes. This prevents last close from waiting for the fixed 30-second close timeout on a queue that cannot drain.

Add a DragonOS dunitest regression that queues serial output under TCOOFF and verifies last close completes promptly.

Validation:
- make fmt
- make kernel
- tty_termios: 21/21 passed in DragonOS
- tty_tcflush: 6/6 passed in DragonOS
- tty_pty_hangup: 36/36 passed in DragonOS
- Python Ctrl+C twice produced KeyboardInterrupt without a kernel panic

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-30 17:14:57 +08:00
LoGin 6cbf2f4c30 fix(rcu): guarantee grace-period forward progress (#2224)
* fix(rcu): guarantee grace-period forward progress

Track active grace-period progress with deterministic soft-request, reschedule-IPI, and stall-report deadlines. Healthy CPUs can now drive escalation without relying on CPU0 jiffies or a bound worker.

Keep timer hardirq work allocation-free by handing worker wakeups to an RCU softirq and performing stall validation and diagnostics in worker context. Bound callback batches by count and elapsed time, expose read-only state and statistics, and make x86 cycle conversion overflow-safe.

Add deterministic policy and candidate-validation coverage together with a two-CPU production-path escalation test, slow-callback coverage, and debugfs dunitests. The selftest report is owner-only and cached after its first serialized run.

Validated with make kernel and the 2-vCPU QEMU rcu_selftest_test suite (5/5 passing).

Signed-off-by: longjin <longjin@dragonos.org>

* fix(rcu): gate IPI selftest by architecture support

Expose the generic KickCpu capability from the SMP layer and skip the hardware-dependent escalation selftest when an architecture does not implement that IPI path. Deterministic policy and failure-accounting coverage remains active on every architecture.

Bundle grace-period pump callbacks into a focused hook structure and use checked division for statistics so the follow-up passes the repository's clippy gate without suppressing lints.

Validated with formatting checks, RISC-V and LoongArch64 cross-builds, an x86_64 kernel build, and the 2-vCPU RCU dunitest suite.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(rcu): harden cross-cpu progress timing

Normalize x86 sched clocks per CPU against the global tick epoch while preserving monotonic local progress across stalled ticks and CPU hotplug. Couple remote clock reads through corrected values instead of mixing TSC offsets.

Replace runtime u128 time conversion with an overflow-safe 64-bit quotient/remainder calculation. Track cacheline-isolated receive-side KickCpu events and require both target-specific RCU submission and delivery in the production-path selftest.

Add deterministic coverage for counter offsets, backward motion, wraparound, resumed ticks, and monotonic reset behavior.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-30 15:05:19 +08:00
LoGin b6096d7bcc fix(rcu): move context trackers out of lazy state (#2223)
RcuState embedded the full per-CPU context tracker array. The spin::Once lazy initialization path consequently reserved about 17 KiB of kernel stack even after initialization, which could exhaust a 32 KiB task stack when reached through IRQ and softirq wakeup paths.

Build the tracker array directly in heap storage and retain it as a fixed boxed slice. This preserves tracker indexing, alignment, lifetime, synchronization, and hotplug semantics while removing the CPU-count-sized object from the lazy state value.

Validated with a release kernel build, RCU PR1/PR2/PR3/PR5 selftests, three cold-cache apt update runs, one cached update, and a 200-process execution stress run.

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-30 10:23:02 +08:00
LoGin c2ba5d209e refactor(rcu): segment callback queues per CPU (#2222)
* refactor(rcu): segment callback queues per CPU

Replace the globally serialized callback tracker and FIFO with cache-line-aligned per-CPU queues split into done, wait, next-ready, and next segments. Keep raw callback admission allocation-free and restrict its shared work to the local queue plus a coalesced worker kick.

Advance callback generations as whole segments, execute bounded round-robin batches outside RCU locks, and implement rcu_barrier() with per-CPU tail markers that cover queued and executing callbacks. Serialize barrier scans with CPU lifecycle migration while preserving the upstream participating-CPU state as the single hotplug authority.

Add per-CPU callback queue debugfs snapshots and extend RCU selftests for segment transitions, migration, callback requeue, multi-batch floods, all-online-CPU admission, concurrent barriers, and the upstream CPU lifecycle protocol.

Tests: make kernel

Tests: make run-nographic (2 vCPUs)

Tests: /opt/tests/dunitest/bin/normal/rcu_selftest_test (3/3 passed)
Signed-off-by: longjin <longjin@dragonos.org>

* docs(rcu): document segmented callback queues

Explain the per-CPU four-segment callback model, grace-period advancement, bounded execution, barrier markers, CPU lifecycle migration, and concurrency invariants without coupling the design to issue history or implementation details.

Add a matching English translation and register both documents in their respective RCU documentation indexes.

Signed-off-by: longjin <longjin@dragonos.org>

* docs(rcu): clarify callback lifecycle

Update the Chinese and English RCU architecture overviews with the per-CPU segmented callback lifecycle, its ordering boundaries, and the distinction between grace-period waits and callback barriers.

Keep the overview concise and link both languages to the detailed segmented callback queue design.

Signed-off-by: longjin <longjin@dragonos.org>

* style(rcu): format callback imports

Signed-off-by: longjin <longjin@dragonos.org>

* fix(rcu): hand off barriers when worker exits

Wake barrier waiters unconditionally after publishing that the callback worker has stopped. This lets a barrier that observed the old worker state recheck its predicate and take over bounded inline execution instead of sleeping forever with queued markers.

Drain a small per-CPU callback quantum before resuming round-robin selection. This avoids rescanning every possible CPU for each callback in a single-CPU backlog while preserving a strict fairness bound for other CPUs.

Tests: make fmt

Tests: make kernel

Tests: make run-nographic

Tests: dunitest normal/rcu_selftest (3/3 passed)
Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-30 01:23:01 +08:00
LoGin ea5d81fb1c feat(rcu): support CPU hotplug lifecycle (#2220)
* feat(rcu): support CPU hotplug lifecycle

Track RCU participation independently from the generic online mask so incoming CPUs join only future grace-period snapshots and dying CPUs transfer active responsibilities before stopping.

Bind the callback worker to its creation CPU, add per-CPU kthread affinity protection, and publish explicit SMP Dying and Dead transitions for the architecture stop path.

Cover repeated and concurrent lifecycle transitions while preserving the intrusive callback queue semantics introduced on the latest master.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(rcu): make CPU teardown non-failing

Remove the runtime policy assertion from the target CPU's RCU dying hook so fatal StopCpu and reboot teardown cannot panic while the system is still marked Running.

Publish terminal CPU state only after local interrupt sources are disabled, target only the CPUs captured by the reboot barrier, and preserve target-owned terminal states when AP bring-up races with shutdown.

Publish per-CPU kthread creation flags before task visibility so userspace cannot race sched_setaffinity against the worker bootstrap.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-30 00:14:52 +08:00
LoGin bc88ffc24d fix(net): prevent TCP self-connect shutdown deadlock (#2221)
Release TcpSocket inner read guards before invoking interface polling or event notification callbacks. Rust extends temporary guards in if-let expressions, so a concurrent shutdown writer could make a nested reader wait behind that writer while the writer waited for the outer reader.

Snapshot owned interface references inside short critical sections and poll only after guard release. Apply the same locking invariant to receive, send, connect, and accept paths, keep self-connected sockets off smoltcp polling, and move self-connect send notification outside the guard.

Add a bounded IPv4 and IPv6 regression test that validates concurrent reads, a complete 1 MiB transfer, SHUT_WR, payload integrity, and EOF delivery.

Tests: make fmt; make kernel; make test-dunit DUNITEST_PATTERN=tcp_self_connect_semantics; tcp_socket_test 184/184; SelfConnectSendRecv IPv4 and IPv6 10000 iterations each; make test-syscall 128/128.

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-29 22:30:57 +08:00
LoGin f6f02096e3 refactor(rcu): make raw callback admission intrusive (#2217)
* refactor(rcu): make raw callback admission intrusive

Replace the growable pending and ready callback queues with one global intrusive FIFO backed by RcuHead. Raw callback publication now performs bounded pointer and sequence updates under the IRQ-saving RCU lock without reserving container capacity.

Detach callback metadata before invocation so embedded heads can be destroyed or requeued safely. Preserve FIFO, grace-period, exactly-once, and barrier sequencing through the existing callback tracker, while keeping allocating closure helpers explicitly separate from the raw path.

Tighten worker progress and lifecycle handling, avoid unnecessary wakeups while a grace period is blocked, and add deterministic coverage for allocation failure, duplicate claims, IRQ-disabled admission, embedded destruction, callback requeue, and sequence wraparound.

Validated with make fmt, make kernel, the QEMU debugfs RCU selftest, and the rcu_selftest dunitest.

Closes #2212

Signed-off-by: longjin <longjin@dragonos.org>

* fix(rcu): fail boot when callback worker creation fails

Treat the RCU callback worker as required boot infrastructure. Continuing after kthread creation failure leaves intrusive callback heads and deferred closures queued without an asynchronous drainer, so their resources can remain retained indefinitely.

Fail fast before the kernel continues initialization, while preserving the existing disabled, idempotent, successful-start, and shutdown paths. This avoids introducing retry state, fallback executors, or callback execution in unsafe contexts.

Validated with make fmt, make kernel, a QEMU failure-injection boot, normal QEMU boot, two debugfs RCU selftest runs, and the rcu_selftest dunitest.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-29 17:40:21 +08:00
LoGin 1102f6c913 feat(rcu): add persistent CPU context tracking (#2218)
* feat(rcu): add persistent CPU context tracking

Introduce a cacheline-aligned per-CPU context state machine for kernel, user, idle, IRQ, and NMI contexts. Track quiescent-state generations so grace periods can exclude CPUs already in extended quiescent states and credit CPUs that pass through one after a grace period starts.

Wire the context boundaries into x86_64 and RISC-V entry, interrupt, idle, and user-return paths. Keep architecture code limited to paired transition hooks, preserve nested interrupt semantics with typed tokens, and retain the grace-period waiting mask as the source of truth.

Add deterministic transition and grace-period selftests, debug-only misuse diagnostics, and a dedicated RCU architecture document covering the stable context, grace-period, callback, ordering, and integration principles.

Validated with make fmt, make kernel, a RISC-V kernel link, and two consecutive 2/2 RCU dunitest passes in a two-vCPU x86_64 QEMU guest.

Closes #2210

Signed-off-by: longjin <longjin@dragonos.org>

* docs(rcu): add English architecture guide

Add the English RCU chapter and architecture guide alongside the Chinese source documentation. Preserve the same subsystem structure, context model, grace-period proofs, callback lifecycle, integration principles, and design boundaries in both language trees.

Link the new chapter from the English kernel documentation index and keep all diagrams and section ordering aligned with the source document.

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-29 15:28:24 +08:00
LoGin d227ec56d1 refactor(rcu): extract grace period state machine (#2216)
Replace the redundant grace-period fields with a small deterministic state machine that owns sequence advancement, request coalescing, waiting CPU snapshots, and wrap-safe completion checks.

Track callback generations with wrap-safe tickets and serialize lock-free callback draining through a single owner so rcu_barrier cannot observe out-of-order completion. Keep the existing worker, queue layout, public APIs, and debug snapshot contract unchanged.

Document the ordinary non-preemptible RCU contract in code, make read guards task-bound, and place full memory barriers only at GP start, real quiescent-state reports, GP completion, and synchronous return boundaries.

Add deterministic coverage for nested requests, empty masks, consecutive grace periods, sequence wraparound, callback ticket wraparound, drainer ownership, and callbacks admitted during an active GP.

Tests:
- make fmt
- make kernel
- /opt/tests/dunitest/bin/normal/rcu_selftest_test (QEMU, twice)

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-29 14:08:33 +08:00
aLinCheandlongjin 5a0707b6b2 feat(ptrace): implement Linux-compatible tracing and remote access (#2198)
feat(ptrace): implement Linux-compatible tracing and remote access

Implement a Linux 6.6-compatible ptrace subsystem and integrate it with
signal delivery, syscall dispatch, seccomp, process lifecycle events,
wait semantics, remote memory access, x86 debug traps, and uprobes.

Replace the original monolithic implementation with ownership-oriented
modules:

- define ptrace ABI types, options, events, and syscall-info separately;
- model active stops, pending events, completed resumes, and request
  freezes as typed state with explicit generation ownership;
- maintain bidirectional tracer relationships with O(1) slot-based
  link and unlink operations;
- centralize attach, seize, detach, wait, exit, fork, group-stop, and
  SIGCONT transactions in the lifecycle layer;
- expose registers, siginfo, sigmask, event messages, and remote memory
  only through a session-and-stop-generation-bound request guard.

Make tracing lifecycle transitions race-safe:

- bind stops, events, waits, debug handoffs, and fork inheritance to the
  exact tracing session that created them;
- wait for the tracee to become inactive before accessing its kernel
  stack TrapFrame;
- revoke request freezes and replay deferred fatal wakeups exactly once;
- preserve group-stop state across detach and tracer exit;
- prevent EXITKILL, EXEC, SECCOMP, SIGCONT, and pending-stop events from
  leaking into a replacement tracing session;
- hand traced zombies from exactly one tracer waiter to the real parent;
- prepare fallible allocations outside IRQ-disabled relation
  transactions and commit only after capacity and ownership revalidation.

Implement the ptrace execution and event ABI, including TRACEME, ATTACH,
SEIZE, DETACH, CONT, SYSCALL, SINGLESTEP, SYSEMU, INTERRUPT, LISTEN,
GET/SETREGS, NT_PRSTATUS GET/SETREGSET, PEEK/POKEUSER, signal and sigmask
access, event messages, syscall information, and fork/clone/vfork,
exec, exit, seccomp, and group-stop events.

Introduce a shared remote-memory engine for ptrace, /proc/<pid>/mem, and
process_vm_readv/writev. Preserve Linux permission checks, precise short
copy results, forced-access COW, MAP_PRIVATE isolation, shared
page-cache dirty accounting, and RISC-V executable-memory I-cache
synchronization. Continue rejecting unsupported special or external-PFN
VMAs instead of adding an unsafe generic provider workaround.

Complete x86_64 tracing state support:

- virtualize and context-switch hardware debug registers;
- coordinate #BP/#DB routing between ptrace and uprobe XOL execution;
- preserve hardware breakpoint, watchpoint, single-step, DR6, and RF
  semantics;
- validate and restore CS, SS, DS, ES, FS, and GS selectors according to
  Linux rules;
- preserve FS/GS selectors and bases across ptrace writes, context
  switches, signal return, and VMX host transitions;
- recover safely from missing data descriptors and preserve the original
  fault frame on invalid iret selectors.

Align siginfo conversion, tracer identity, syscall-number rewriting,
regset partial-copy behavior, dumpability, user-namespace capability
checks, Yama policy, and procfs TracerPid reporting with Linux 6.6.

Add deterministic dunitest and gVisor coverage for ptrace lifecycle,
group-stop, concurrent ownership, EXITKILL, syscall information,
seccomp TRACE, x86 debug state, segment registers, process_vm access,
proc-mem, page-cache persistence, and remote I-cache synchronization.
Remove the ptrace Int3 blocklist and declare only the verified
INT3:TRUE gVisor platform capability.

Validation on the final head includes:

- x86_64, RISC-V, and LoongArch build, format, and static checks;
- successful x86_64 Dunitest and integration workflows;
- 1172 local Ubuntu 24.04 two-vCPU dunitests with 0 failures and
  0 timeouts;
- 12/12 targeted x86 ptrace register/debug tests on both Linux and
  DragonOS;
- successful MM host tests and final adversarial architecture,
  correctness, concurrency, security, and performance review.

PTRACE_O_SUSPEND_SECCOMP and non-NT_PRSTATUS regsets remain explicitly
unsupported. Remote access to special/external-PFN VMAs continues to
require a future safe provider contract.


Signed-off-by: aLinChe <1129332011@qq.com>
Signed-off-by: longjin <longjin@dragonos.org>
Co-authored-by: longjin <longjin@dragonos.org>
2026-08-28 16:42:48 +08:00
火花andlongjin 05a568fd39 feat(uprobe): implement uprobe breakpoint support (#2150 phase 1) (#2163)
* feat(uprobe): implement uprobe breakpoint support (#2150 phase 1)

Implement userspace breakpoint probes (uprobe), phase 1 of issue #2150,
enabling agentsight to instrument SSL_read/SSL_write entry points.

The design is XOL-based rather than reusing kprobe's kernel-buffer
single-step (impossible at CPL=3). Key pieces:

- per-mm uprobe table guarded by an irqsave SpinLock (not the global
  KPROBE_MANAGER lock nor the mm RwSem; the #BP/#DB hit path is IRQ-off)
- breakpoint page install replicates do_wp_page private COW:
  copy_page_as_normal + single atomic set_entry + rmap attach/detach
  + flush_tlb_range. No transient empty PTE; each mm gets a private copy
  so writeback never persists 0xcc into the shared page-cache (.so)
- XOL: a per-mm user slot page executes the saved instruction copy with
  RIP-relative relocation (yaxpeax-x86), validated at registration time
- do_int3/do_debug gain is_from_user() dispatch. The #BP handler runs
  pre_handler + BPF (rip kept as the original probe address), then jumps
  rip to the pre-filled XOL slot, sets TF and NEED_UPROBE. The #DB handler
  recognizes XOL completion via NEED_UPROBE and restores rip; unconsumed
  user #BP is delivered as SIGTRAP(TRAP_BRKPT)
- perf: PERF_TYPE_MAX dispatches to uprobe when the name contains '/';
  UprobePerfEvent mirrors KprobePerfEvent and reuses BPF_PROG_TYPE_KPROBE

Delivered in four batches: uprobe crate (x86 instruction analysis), mm
integration (per-mm table / XOL / breakpoint page), exception dispatch,
and perf attach.

Verified: `make kernel` builds with 0 error / 0 warning; `cargo test -p
uprobe` passes 7/7. An independent reviewer confirmed the F1-F10 review
findings are satisfied with no kprobe/fork regression, and flagged two
bugs that are fixed: re-registering the same probe_vaddr no longer reads
0xcc as the original instruction, and a RIP-relative displacement overflow
now fails fast at registration instead of panicking at hit time.

Out of scope: uretprobe (phase 2) and the QEMU runtime integration test.

Refs: #2150

test(uprobe): add dunitest suite for uprobe breakpoint probes

Add suites/normal/uprobe.cc covering the userspace perf_event_open
uprobe path (issue #2150 phase 1):
- RegisterAndTriggerSurvivesHit: perf_event_open(type=PERF_TYPE_MAX,
  config1=path, config2=offset) on the current process, then call the
  probed function and assert it survives the #BP -> XOL -> #DB -> resume
  hit path and returns the correct value
- InvalidPathIsRejected / InvalidOffsetIsRejected: error inputs return
  negative errno

Target offset is resolved from /proc/self/maps (executable segment +
file pgoff), so the suite works regardless of PIE layout.

Compiles cleanly via `make build-suites`; the gtest framework runs (the
two negative cases pass on host Linux; the core trigger case is
DragonOS-specific and is validated at runtime under QEMU).

Refs: #2150

fix(uprobe): resolve CI failures - format check and cross-arch build

- Apply rustfmt to uprobe integration code (reorder modules, imports,
  line width) to pass format-check on all arches
- Add #[cfg(target_arch = "x86_64")] gates to uprobe integration points
  (exception/perf/mm-ucontext modules, AddressSpace fields, fork path,
  perf dispatch arm) so riscv64/loongarch64 build succeeds
- Non-x86_64 perf dispatch returns ENOSYS for uprobe paths
- Fix unused_mut on phys_addr in fork path for non-x86_64

* fix(uprobe): address P1 review findings (threads 1/2/3/5)

- Thread 1: add ptrace access check (check_process_vm_access) before
  taking a target mm for cross-process uprobe, preventing unprivileged
  users from instrumenting arbitrary processes
- Thread 2: reject control-flow instructions (call/jmp/ret/jcc/loop/int/
  syscall) at registration time — XOL cannot safely single-step them
- Thread 3: read_user_insn_bytes now continues into the next page when
  the probe is near a page boundary, returning real bytes instead of
  zero-padding that could decode to a different instruction
- Thread 5: build_xol_slot fills trailing slot bytes with int3 (0xcc) so
  that a racy unregister during the XOL single-step window re-triggers
  #BP instead of executing zero-filled garbage

* fix(uprobe): address maintainer review (12 findings, R1-R12)

Security & correctness:
- R1: pid==-1 (system-wide) now requires CAP_SYS_PTRACE; pid<-1
  returns EINVAL. Per-pid path keeps check_process_vm_access.
- R4: user #DB not consumed by uprobe now falls through to the normal
  DebugException path (restores pre-PR master behavior for
  ptrace/hardware breakpoints/single-step).
- R5: original RFLAGS.TF is saved per-thread before XOL redirect and
  restored on completion (previously cleared unconditionally, silently
  disabling a program's own single-step mode).
- R6: old_instruction copy now covers the full decoded instruction
  across page boundaries (was limited to first-page remainder).
- R7: the breakpoint byte is restored only when the LAST consumer at
  that address unregisters (previously restored on every unregister,
  silently disabling remaining same-address consumers).
- R8: unregister writes the original byte on the CURRENT mapped page
  instead of remapping the registration-time page, preserving the
  program's own writes to other bytes of that page.
- R10: reject MOV SS (suppresses #DB) and POPF (overwrites RFLAGS/TF)
  at registration, in addition to control-flow instructions.
- R11a: honor perf_event_attr.disabled (event starts disabled).

Architecture (per-thread state, R2/R3/R12):
- ActiveXol per-thread state on the PCB: probe_vaddr, return_addr,
  orig_tf, xol_page_base. Saved at #BP before rip redirect, consumed
  at #DB: O(1) completion independent of uprobe_list (racy unregister
  between #BP and #DB no longer corrupts resume), abort path when rip
  is outside the XOL page (signal/fault diversion), callbacks run
  outside the per-mm spinlock.

Durable probe identity (R9):
- Global registry keyed by inode+offset with consumer ids. New file
  mappings (dlopen/mmap via file_mapping_with_file_ext) and fork get
  late-applied probes; exec starts with an empty table. Consumer close
  drops registry entries plus late handles (per-mm unregister via the
  existing UprobeHandle::Drop with R7/R8 semantics). fork inherits
  instances with privatized child breakpoint pages.

Verified: make kernel 0 error/0 warning; make fmt (clippy) clean;
cargo test -p uprobe 9/9; QEMU dunitest uprobe 6/6, exec_abi 6/6,
process_signal_fork 10/10.

* fix(uprobe): align perf lifecycle with Linux semantics

Match the uprobe PMU ABI with Linux for event type discovery, perf_event_attr validation, PID and CPU selection, path resolution, unsupported options, BPF attachment, and file descriptor behavior.

Refactor definitions, consumers, sites, and XOL state so canonical file identity, enable and disable transitions, concurrent teardown, callback snapshots, and instruction restoration have explicit ownership and locking rules.

Reconcile probes across mmap, mremap, mprotect, madvise, fork, exec, signal, fault, and exit paths while revalidating VMA identity after page faults and preserving strict error reporting for eligible mappings.

Add dunitest coverage for lifecycle control, invalid attributes, aliasing, relative paths, tmpfs-backed probes, multiple consumers, and unsupported operations.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): close teardown and task scope races

Filter task-scoped callbacks by exact task identity and make the breakpoint entry atomic with teardown rendezvous. Keep the kernel-owned XOL mapping immutable across VMA operations and reject unsafe repeated string instructions during registration.

Preserve MREMAP_FIXED failure atomicity and add guest coverage for repeated instructions and concurrent final-consumer teardown.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): serialize runtime snapshots and reject pushf

Serialize participant snapshot collection and publication, and release retired callbacks after leaving the IRQ-disabled registry lock.

Reject PUSHF/PUSHFQ in phase-1 XOL so the temporary trap flag cannot leak into user-visible flags. Preserve Linux MADV_DONTNEED per-VMA side-effect ordering while using range-indexed probe lookup.

Apply rustfmt to the touched perf, BPF, and ucontext sources.

Tests:

- make fmt FMT_CHECK=--check

- cargo test --manifest-path kernel/Cargo.toml -p uprobe

- make kernel

- DragonOS QEMU uprobe suite (20/20)

- DragonOS QEMU Madvise suite (1/1)

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): reject xbegin and deduplicate installs

Reject XBEGIN from phase-1 XOL execution because its relative abort target cannot be preserved by the current exact-end single-step state machine.

Move same-consumer idempotence checking into the existing mm write-locked registration path so concurrent enable and VMA apply operations cannot publish duplicate callbacks.

Keep LSS supported: Intel documents that it does not suppress events like MOV SS or POP SS, matching Linux 6.6.139.

Tests:

- make fmt FMT_CHECK=--check

- cargo test --manifest-path kernel/Cargo.toml -p uprobe

- make kernel

- DragonOS QEMU uprobe suite (21/21)

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): preserve XOL fault addresses

Report the original probed instruction in SIGFPE siginfo when a divide fault occurs during XOL execution.

Pass the registry snapshot consumer directly into installation so matching probes do not rescan the global registry for every site.

Add a DragonOS regression test for the fault address and use a lock-free atomic result channel in its signal handler.

Tests:

- make fmt

- make fmt FMT_CHECK=--check

- cargo test --manifest-path kernel/Cargo.toml -p uprobe

- make kernel

- DragonOS QEMU uprobe suite (22/22)

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): harden BPF attachment

Reject duplicate PERF_EVENT_IOC_SET_BPF attachments atomically with EEXIST, matching Linux semantics. Allocate size-aware JIT memory fallibly and release it on every failure path. Add regression coverage for duplicate attachment and large JIT programs.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): serialize fork breakpoint restoration

Restore inherited breakpoint bytes while the child address space is still write-locked, before file-rmap registration scans can enter it. Replay enabled consumers after publication and add bounded concurrent fork coverage for system-wide registration.

Signed-off-by: longjin <longjin@dragonos.org>

* perf(uprobe): scope task mapping scans

Enumerate only the target address space for task-scoped open and enable, while retaining inode file-rmap traversal for system-wide consumers.

Reuse the common enable lifecycle for initial activation and remove the duplicate open scan.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): preserve instruction mapping semantics

Synchronize same-page breakpoint publication across active CPUs, validate complete instruction mappings and bytes, and track instruction-tail VMA changes.

Drain and deduplicate consumer site references so repeated enable and disable does not grow stale attachment state.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): reject unsupported loop branches

Classify the complete x86 LOOP-family as unsupported control flow so phase-one XOL cannot retry a taken branch after mutating the counter.

Cover the decoder variants and perf event error contract with regression tests.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): expose perf hit counts

Provide the raw singleton perf read ABI for uprobe events, keep advanced read formats explicitly unsupported, and serialize counter shutdown with in-flight callbacks. Also remove empty address keys when breakpoint installation rolls back.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): validate relocation and perf attributes

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): preserve identity across VMA splits

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): close perf event lifecycle gaps

Signed-off-by: longjin <longjin@dragonos.org>

* refactor(uprobe): consolidate probe lifecycle architecture

Split the MM uprobe implementation into definition, consumer, site, reconciliation, and XOL ownership domains. Replace per-consumer site instances with one installed site per address and publish immutable RCU hit snapshots for the exception path.

Model enable, disable, close, task exit, and exec through one-shot consumer epochs with explicit install and delivery admission. Move the authoritative XOL phase into task-owned state, keep BPF/JIT ownership in the perf adapter, and prevent heavyweight teardown from escaping into interrupt or RCU contexts.

Restructure live VMA operations around fallible planning, precise probe withdrawal, infallible mutation, and best-effort reconciliation. Install probes for new executable mappings while holding the MM write guard and use a fixed-capacity mremap execution-publication transaction to close normal source and destination execution windows without post-commit allocation.

Extend dunitest coverage for lifecycle transitions, fork and exec interactions, mapping splits, MAP_FIXED, mprotect, madvise, mremap move and DONTUNMAP behavior, locked mappings, in-place growth, BPF delivery, counter reset, and concurrent execution.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): grow the per-mm XOL slot pool

Replace the fixed single-page XOL area with a lazily growing per-mm pool so registered probe sites are no longer capped at 256 addresses. Keep slot allocation and page creation on the registration path, preserving the allocation-free exception hot path and lifetime-pinned slots.

Reserve pool capacity before mapping each additional XOL page, protect every page from user VMA changes, and prefer the newest page while still reusing released slots. Add a guest regression that registers 257 distinct sites and executes the first site backed by the second XOL page.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): synchronize VMA publication and hit lookup

Keep uprobe state consistent across executable VMA mutations and high-volume site updates.

- split VMA validation, withdrawal, commit, locked reconciliation, and permission publication into explicit phases

- hold temporary execute/write barriers across mprotect, madvise, mmap, and mremap publication, including installed-site teardown windows

- revalidate stale user protection faults against stable leaf permissions without masking genuine protection faults

- replace full BTreeMap hit snapshots with a persistent Patricia index and serialize RCU publication with control mutations

- accept CAP_PERFMON alongside the legacy CAP_SYS_ADMIN capability

- add DragonOS regressions for permission transitions, VMA concurrency, DONTNEED, alias mappings, and capability checks

Signed-off-by: longjin <longjin@dragonos.org>

* fix(perf): harden probe inputs and remote writes

Bound dynamic probe names according to the Linux perf ABI and return E2BIG when uprobe paths or kprobe symbols are not terminated within their type-specific limits.

Rework process_vm_writev around remote writable-page acquisition: validate VM_WRITE, resolve remote write faults and COW, preserve private-page fork isolation, pin shared page-cache entries, publish dirty state before copying, and retain exact partial-write accounting. Reject writes to active read-only uprobe mappings instead of bypassing their protection.

Restore an original uprobe opcode only while the software breakpoint is still present, so teardown cannot overwrite a newer byte. Add dunitest coverage for bounded probe names, active uprobe write rejection, anonymous and private COW writes, shared-file persistence, and partial-copy semantics.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): stabilize instruction installation

Allocate XOL slots within the exact disp32 relocation range and keep the pool ordered so distant aliases neither reuse unreachable slots nor degrade into full-pool scans. Roll back unpublished XOL mappings on failed installation.

Build breakpoint COW pages from a stable source snapshot, validate the bytes that will actually be published, and defer RCU hit metadata until all fallible preparation has completed. Propagate Page contention so strict registration waits outside mm.write and then fully revalidates.

Reject SYSENTER and SYSEXIT probes, and return ENODEV only for offline per-CPU events while preserving Linux task-event semantics.

Add regression coverage for distant RIP-relative aliases and fast system-call instructions.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): keep fork replay best-effort

Keep inherited-breakpoint sanitization inside the fallible fork transaction, but treat consumer replay as observational work that cannot change fork's result.

Mapping and fork reconciliation now attempt contended pages once, while explicit consumer activation retains strict wait and rollback semantics.

Add a regression covering a privately modified MAP_PRIVATE instruction page under a system-wide uprobe.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): preserve rseq restart semantics across XOL

Expose the original probe address as rseq's logical instruction pointer while XOL is active. When rseq commits an abort redirect, consume the XOL state first so single-step completion cannot overwrite the abort target and the original trap flag and slot lease are restored correctly.

Add an x86 regression that forces preemption between the uprobe callback and XOL execution and distinguishes active-XOL aborts from legitimate pre-probe rseq aborts.

Signed-off-by: longjin <longjin@dragonos.org>

* perf(uprobe): bound reconciliation overhead

Scope executable publication barriers to consumers that permit the target address space and skip fork replay when no system-wide consumer is active, while retaining inherited breakpoint sanitization.

Replace per-mutation participant vector rebuilds with an RCU-published structurally shared chain, per-site membership liveness, and proportional compaction so registration and teardown no longer accumulate quadratic copying.

Add task-scoped fork coverage to verify that child execution is sanitized without inheriting event counts or disarming the parent site.

Signed-off-by: longjin <longjin@dragonos.org>

* perf(uprobe): scope exec reconciliation

Avoid full address-space replay when active uprobes cannot target the exec task. Reuse the task consumer index and system-wide activity counter to gate reconciliation without allocation.

Move replay out of the ELF loader and into stable exec success and recoverable rollback points, preserving task-scoped events across exec while closing concurrent enable publication gaps. Add a task-scoped exec regression test.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): retain sites across writable mprotect

Keep Linux's distinction between new uprobe installation eligibility and the lifetime of an existing site. A writable private VMA still rejects a new installation, while adding WRITE through mprotect no longer withdraws an already armed breakpoint. Removing WRITE continues to reconcile a persistent consumer.

Add dunitest coverage for both the retained-site transition and delayed installation after WRITE is removed, and remove the obsolete installed-site intersection helper.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): bound teardown and classify XOL completion

Index task-scoped consumers by their stable consumer IDs and remove only the known empty inode-offset bucket during teardown. This avoids quadratic scans while preserving weak ownership and existing lifecycle ordering.

Treat a Running XOL at its exact slot endpoint as completed even when a virtualized debug exception omits DR6.BS. Continue forwarding hardware breakpoint causes and reject ICEBP from XOL analysis.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(uprobe): quiesce events on final close

Close install and delivery admission synchronously when the final perf file reference is released, while leaving sleepable epoch draining, site teardown, and BPF retirement to the existing release worker. Split release admission from worker ownership so late ioctls and callbacks cannot outlive close.

Fix the admission guard's eager construction bug, which decremented a closed gate without a matching acquire and could leave teardown waiting forever. Index same-offset consumers by stable ID to reduce repeated close from quadratic irq-disabled scans to O(N log N), while preserving contiguous reconciliation snapshots.

Validated with make fmt, a full x86_64 kernel build, the 60-case uprobe dunitest suite, and a three-persona adversarial review.

Signed-off-by: longjin <longjin@dragonos.org>

* docs(uprobe): document architecture and execution model

Replace temporary implementation notes and planning material with reader-facing bilingual design documentation. Explain the file-offset identity model, per-mm sites, private breakpoint pages, XOL execution, VMA transactions, lifecycle ordering, performance characteristics, and Linux-compatible boundaries, and link both versions from the tracing indexes.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(mm): serialize mremap mapping validation

Signed-off-by: longjin <longjin@dragonos.org>

---------

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
Signed-off-by: longjin <longjin@dragonos.org>
Co-authored-by: longjin <longjin@dragonos.org>
2026-08-26 01:03:20 +08:00
火花andlongjin 6ef75fc963 feat(fs): implement inotify filesystem event notification (#2164)
* feat(fs): implement inotify filesystem event notification

Implements inotify (issue #2151): the fsnotify core notification layer,
the inotify pseudo-device, 4 syscalls (init/init1/add_watch/rm_watch),
and VFS write-path hooks for all standard events (create/delete/move/
modify/access/close/attrib/self events).

Architecture:
- fsnotify/ unified dispatch layer: global (inode_id, dev_id) index,
  TOTAL_WATCHES atomic fast-path (zero cost when no watches), lock-family
  separation (global index lock / events lock / wd lock never nested).
- inotify.rs device: InotifyInode implements IndexNode + PollableInode,
  epoll-integrated via LockedEPItemLinkedList, exact inotify_event layout
  (name field aligned to sizeof(inotify_event)=16, matching Linux ABI).
- VFS hooks placed in syscall-core layer (vcore/open/rename_utils/...),
  NOT per-filesystem: single anchor covers ext4/tmpfs/overlayfs/fuse.
  Hooks fire only after success and never alter syscall return values.

Review fixes incorporated:
- Directory watches receive child content events (issue B): IN_MODIFY/
  ACCESS/OPEN/CLOSE delivered to parent dir watch with child name.
  MountFSInode::as_any_ref() returns the inner inode's Any, so use
  downcast_arc instead of downcast_ref for parent resolution.
- Guard DELETE_SELF on hardlink unlink/rename-over: only emit when
  i_nlink reaches 0, matching Linux fsnotify_link_count() semantics.
- Composite mark index key (inode_id, dev_id): prevents FUSE cross-mount
  event leakage when multiple mounts reuse same inode number.
- Remove has_any_watch() gate on File::inotify_parent resolution so
  watches added after open receive content events.
- Tolerate metadata failure after unlink/rename-over (FUSE GETATTR can
  return ENOENT); cache nlinks before the namespace operation.
- SYS_INOTIFY_INIT only registered on x86_64 (generic syscall ABI uses
  inotify_init1); riscv64/loongarch64 lack the legacy init syscall.
- Skip MOVED events on no-op rename; EOF reads no longer deliver
  IN_ACCESS; reject mask==0 and IN_MASK_ADD|IN_MASK_CREATE.

Test: dunitest inotify_dir_watch (2 tests) + inotify_events (6 tests)
covering content/namespace/self events, multi-instance, and poll.

Design doc: docs/kernel/filesystem/inotify.md

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>

* fix(fsnotify): harden inotify lifecycle and semantics

Linearize mark publication, dispatch, and removal around stable object identities so watch updates, one-shot delivery, inode deletion, and final unmount cannot race.

Make queue overflow, read consumption, allocation rollback, user quotas, and dentry snapshots safe under concurrency and memory pressure. Align VFS event routing with Linux semantics for open, close, links, rename, attributes, exclusion of unlinked paths, and deletion ordering.

Add dunitest coverage for namespace events, inode lifecycle, O_PATH, hard links, rename aliases, multi-instance delivery, and poll readiness.

Validated with make kernel and 12 passing inotify tests on both host Linux and a DragonOS QEMU guest.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(fsnotify): address follow-up semantic reviews

Close lifecycle epoch races when final deletion notifications overlap relink and keep FUSE atomic-truncate cache invalidation atomic.

Match Linux mount-boundary rename handling, lookup error precedence, no-op ordering, open and truncate event order, exec open notification, EXCL_UNLINK data kinds, and chown ABI/symlink semantics.

Extend inotify and FUSE regression coverage for bind mounts, rename precedence, O_TRUNC, exec, chown flags and symlinks, event merging, and cache refresh.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(fsnotify): address quota and event review findings

Charge inotify usage through ancestor user namespaces and serialize rename notifications with conflicting namespace commits without holding the global topology lock during dispatch.

Emit missing mknod and utimes events, preserve pathname O_TRUNC semantics, and extend the focused regression coverage.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(fsnotify): avoid global lookups for unwatched objects

Track watch presence in the existing per-object state shared by inode aliases. Event dispatch and final detach can now bypass the global mark index when neither target is watched, while add, removal, shutdown, and OOM rollback keep the hint synchronized with mark publication.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(fsnotify): report successful xattr changes

Emit IN_ATTRIB from the shared setxattr and removexattr success paths so path, fd, and no-follow syscalls notify both inode and parent watches. Cover successful, repeated, and failed mutations and document the event source.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(fsnotify): address review findings and test timeout

Handle directory rename-over deletion, release the inotify reader mutex before waiting, and add watch-presence hints for anonymous pipes.

Report killpriv attribute changes with Linux-compatible masks and ordering, close the empty-queue read race, and make synchronous inotify tests drain without fixed delays.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(fsnotify): complete zero-copy I/O notifications

Make final-mark index removal allocation-free so low-memory cleanup cannot retain empty object keys. Keep the immutable multi-mark snapshot rebuild fallible and protect replacement with the existing Arc identity check.

Publish splice and tee content events only after positive transfer progress, preserve Linux event ordering, and defer regular-file ACCESS for file-to-pipe transfers to avoid premature or duplicate events.

Retain pathname identity when File substitutes a runtime special inode so named FIFO and procfd watches target the same object, while suppressing special-file content events on parent directory watches. Add shared-queue ordering and pipe/file/FIFO regression coverage.

Tests:
- make kernel
- FMT_CHECK=1 make fmt
- make -C user/apps/tests/dunitest bin/normal/inotify_events_test -j2
- inotify_events_test --gtest_filter='InotifyAnonymousObjects.*Splice*'

Signed-off-by: longjin <longjin@dragonos.org>

* fix(fsnotify): preserve mknod event ordering

Queue mknod CREATE notifications while the parent mutation gate still serializes competing namespace changes. Share the commit-aware path between mknod and mknodat, add a bounded concurrency regression test, and avoid directory notification snapshots when no watches exist.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(inotify): close review lifecycle gaps

Reject pathname reopening of inotify anonymous files so a procfd open cannot tear down the original instance. Preserve Linux hard-link notification order under concurrent namespace mutations and drain unmount marks from a single fallible snapshot.

Add regression coverage for procfd reopen, hard-link event order, and concurrent link/unlink publication.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(inotify): serialize regular file create events

Publish O_CREAT notifications at the backing namespace commit point while the parent children gate is still held. This prevents a concurrent unlink from queuing IN_DELETE before IN_CREATE.

Cover both atomic create-and-open and the generic create fallback, and add a bounded concurrency regression for create/delete event ordering.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(inotify): serialize namespace mutation events

Publish mkdir, symlink, unlink, and rmdir notifications at their MountFS namespace commit boundaries while the parent children gate remains held. Preserve internal idempotent mkdir behavior while enforcing syscall EEXIST under the gate.

Add bounded concurrency coverage for delete/recreate ordering and same-name mkdir.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(inotify): align transfer and fallocate events

Defer copy_file_range and sendfile data notifications until positive syscall-level progress while preserving write-side metadata events and partial-success semantics.

Propagate committed fallocate metadata changes for ordered ATTRIB/MODIFY delivery and correct FUSE rename-over directory link counts. Add focused regression coverage.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(fsnotify): harden lifecycle and event ordering

Move mounted watches to object-local state and immutable mark snapshots so unrelated filesystem activity no longer contends on the global fallback index. Publish marks active only after accounting and index setup, and retire them through a single token-owned cleanup path.

Model link removal and rename replacement with typed outcomes across VFS, FUSE, overlayfs, ext4, FAT, ramfs, and tmpfs. Keep delete epochs ordered by canonical inode mutation coordinators and publish namespace events at the actual commit boundary.

Align open, truncate, fallocate, xattr, rename, and anonymous-object notifications with Linux ordering. Handle direct inotify reads without 64 KiB syscall re-entry, preserve EFAULT semantics, and avoid holding reader serialization across user faults.

Make FAT zero-extension allocation fallible and rollback-aware, reuse measured chain extents, and preserve allocation metadata across retryable failures. Restore correctness-critical wait-queue wakeups and fatal group-signal delivery.

Add dunitest coverage for lifecycle, ordering, read-boundary, fallocate, and concurrent FAT allocation regressions.

Validation:

- CARGO_INCREMENTAL=0 make -C kernel check ARCH=x86_64

- make kernel ARCH=x86_64

- inotify_events guest suite: 47 passed, 1 skipped, 0 failed

- fat_concurrent_allocation guest suite: 2 passed, 0 failed

Signed-off-by: longjin <longjin@dragonos.org>

* fix(fsnotify): align I/O notification boundaries

Emit IN_ACCESS once per successful read syscall instead of once per 64 KiB implementation chunk, while preserving bounded buffering and partial-read semantics.

Keep overlay copy-up data transfers from publishing chunk-level ACCESS/MODIFY events without suppressing normal backing-file notifications. Translate non-atomic FUSE O_TRUNC as an ATTR_OPEN truncate without FATTR_FH.

Add regressions for large reads and overlay copy-up notification ownership, and apply the formatting and Clippy fixes required by CI.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(vfs): align fsnotify commit boundaries

Resolve rename source and replacement objects under the same parent gates that serialize the backing mutation. Validate permissions and ancestor constraints against that authoritative snapshot, treat the locked filesystem NoOp outcome as final, and publish dentry state plus rename notifications from coherent metadata-free target seeds.

Defer ordinary readv ACCESS delivery until the syscall result is known so bounded chunks and multiple iovecs emit one event. Preserve the existing single-read socket path and accept Linux-compatible zero-segment readv calls.

Add regression coverage for large vectored reads, zero-segment ACCESS delivery, and same-inode rename no-op behavior.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(ramfs): preserve written data during fallocate

Use the locked data vector length as RamFS's authoritative file size when handling mode-0 fallocate requests. This prevents a stale cached metadata size from shrinking data previously grown by write or resize paths.

Add a mounted RamFS regression test that writes a full payload, requests a smaller allocation range, and verifies both the file size and tail contents. The test fixture owns and cleans up its fd, file, mount, and temporary directory on every exit path.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(inotify): support FIONREAD

Implement the Linux FIONREAD contract for inotify descriptors by reporting the serialized byte size of every currently readable record, including the logical overflow event.

Take the queue snapshot under its lock and release the lock before copying the result to userspace, so user faults cannot block queue producers or readers. Preserve ENOTTY for unsupported ioctl commands and EFAULT for invalid result pointers.

Add a regression test covering named and unnamed events, non-consuming queries, invalid pointers, exact-size reads, empty queues, and assertion-safe resource cleanup.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(vfs): preserve positioned I/O event boundaries

Defer ACCESS and MODIFY publication across the internal 64 KiB pread/pwrite chunks, then emit one data event when the syscall has made positive progress. Keep metadata side effects at their real commit point, preserve partial results when later chunks fail, and make bounce-buffer allocation fallible.

Replace the scheduler-dependent page-cache chunk-release selftest handshake with a deterministic probe at the same drop/yield/relock boundary used by production. Add a 200 KiB inotify regression covering parent and inode watches and unchanged positioned-I/O offsets.

Signed-off-by: longjin <longjin@dragonos.org>

* fix(inotify): preserve vector-read and interest-cache semantics

Publish IN_ACCESS once for successful preadv and preadv2 calls, including zero-byte vector completions, while preserving scalar pread behavior. Validate signed offsets before flags and user iovec access so Linux error precedence is retained.

Add an epoch-validated negative interest cache to mounted dentries. Watch transitions and namespace topology changes invalidate cached misses, avoiding repeated dentry locks and parent/name clones for unrelated I/O without adding alias scans or a global hot-path lock.

Extend dunitest coverage for zero-length and EOF vector reads, invalid offset precedence, watch transitions, rename invalidation, and retained file descriptors.

Tests: make kernel

Tests: make -C user/apps/tests/dunitest build

Tests: inotify_events_test (53/53, Ubuntu 24.04 guest)

Tests: tcp_socket_test SelfConnectSendRecv (100 rounds, Ubuntu 24.04 guest)
Signed-off-by: longjin <longjin@dragonos.org>

* fix(inotify): satisfy x86 clippy borrow check

Pass the existing parent reference directly to the mounted fsnotify state resolver. This removes the needless double borrow reported by the x86_64 format job without changing identity, lifetime, or locking semantics.

Tests: make fmt
Signed-off-by: longjin <longjin@dragonos.org>

* docs(inotify): align architecture guide with implementation

Replace the obsolete implementation plan with a user-oriented description of the current event model, routing, lifecycle, queue semantics, and performance design.

Split the English version into the locales tree and register both language pages in their filesystem indexes.

Checks: git diff --cached --check
Signed-off-by: longjin <longjin@dragonos.org>

* docs: translate newly-added Chinese comments to English

Translate Chinese code comments introduced by the inotify/fsnotify work
into English, and fix a stale function reference in inotify.rs add_watch
(try_reserve_watch -> reserve_watch / adjust_total_watches).

---------

Signed-off-by: sparkzky <sparkhhhhhhhhhh@outlook.com>
Signed-off-by: longjin <longjin@dragonos.org>
Co-authored-by: longjin <longjin@dragonos.org>
2026-08-25 14:02:38 +08:00
LoGin 1fb3b878e2 fix(waitqueue): prevent lockless empty checks from losing wakeups (#2207)
WaitQueue wake_one() and wake_all() used a lockless waiter count as a correctness-critical negative check. An unlocker could publish the condition, observe a stale zero count, and skip the wake while the waiter failed its condition recheck and went to sleep.

Always acquire the queue lock before deciding whether a wake queue is empty. This puts waiter registration and wake selection in the same linearization domain, matching the locking contract used by the regular Linux waitqueue wake path. Keep is_empty() as an explicitly advisory snapshot.

Add a DoubleEpollOneShot progress regression that exercises the AF_UNIX mutex and waitqueue path through two independent EPOLLONESHOT registrations. Use a no-progress watchdog and MSG_NOSIGNAL so failures terminate deterministically without adding periodic wakeups to the operation under test.

Fixes: #2202

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-23 22:31:48 +08:00
LoGin b990f6b283 fix(signal): preserve fatal delivery during sibling exec (#2206)
Keep a later SIGKILL on the normal pending and wakeup path when the thread group is already exiting. This matches Linux complete_signal semantics and prevents the delivery from being consumed without making the signal observable.

For the first fatal group-exit transition, snapshot the group before waking tasks and explicitly queue SIGKILL to the selected target. This keeps the selected PCB covered across a concurrent non-leader exec identity exchange while avoiding duplicate wakeups.

The change leaves group-exec ownership, wait barriers, and identity handoff unchanged.

Signed-off-by: longjin <longjin@dragonos.org>
2026-08-23 20:04:16 +08:00