* 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>
DragonOS
Languages 中文|English
DragonOS is a 64-bit operating system with a completely independent kernel, designed for lightweight cloud computing scenarios, offering Linux binary compatibility. It aims to provide lightweight, high-performance solutions for containerized workloads. Developed using Rust for enhanced reliability.
The DragonOS open-source community was established in July 2022 and is entirely commercially neutral. We warmly welcome interested developers and enthusiasts to join us!
DragonOS features excellent and comprehensive architectural design. Compared to other systems of similar scale, DragonOS supports eBPF and virtualization. Currently, we are actively advancing container support, cloud platform compatibility, RISC-V support, as well as porting compilers and application software. Our goal is to achieve large-scale production environment deployment within five years.
DragonOS is rapidly evolving under community-driven development. Currently, DragonOS has implemented approximately 1/4 of Linux interfaces. In the future, we will provide 100% Linux compatibility along with new features.
🌟 Want to quickly experience DragonOS? Visit DragonOS Playground to launch DragonOS in the cloud with zero configuration and experience the latest nightly build!
📰 Community News
- 2025-12-17: ☁️ DragonOS Playground is now live! Experience DragonOS with zero configuration on CNB platform, with daily nightly build updates! Try it now →
- 2025-11-20: 🚀 DragonOS 0.3.0 has been released! Now supports running Go programs directly!
- 2025-11-18: 📊 DragonOS CI Dashboard is now live! Check out DragonOS Linux compatibility data now!
How to Run?
🌟 Method 1: Cloud-Native Development (Recommended)
Zero configuration, one-click launch! Experience DragonOS on the CNB cloud-native development platform - the simplest and fastest way, no local dependencies required!
Method 2: Local Build
If you prefer to build and run DragonOS locally, you can refer to the following documentation:
Want to Contribute?
Read the DragonOS Community Introduction Document carefully to understand how the community operates and how you can contribute!
If you'd like to join us, check out the issues and participate in discussions or share your ideas. You can also visit the DragonOS forum to stay updated on development progress and tasks: https://bbs.dragonos.org.cn
You can also bring your creativity and ideas to discuss with the community and contribute new features to DragonOS.
Sites
- Official Website: DragonOS.org
- Documentation: docs.dragonos.org
- Community Introduction: community.dragonos.org
- QQ Group: 476358494
How to Connect with the Community?
Please read the Contributor Guide~
- You can find contact details for members of various committees in the Community Management Team section.
- You can also locate the contact information for leaders of specific community groups via the SIGs and WGs pages.
Contributor List
Contributors to DragonOS-Community/DragonOS · GitHub
Sponsorship
DragonOS is a non-profit open-source project, and its development relies on financial support. All sponsors will be publicly acknowledged. Every contribution you make will help advance DragonOS!
Where Will Sponsorship Funds Be Used?
We guarantee that all sponsorship funds and items will be used for:
- Event organization, cloud service expenses, and any other purposes beneficial to the development and growth of the DragonOS community.
🌟 Sponsor List
Special thanks to these generous financial supporters (in reverse chronological order):
- 中国雅云 雅安大数据产业园 - 🥇 Long-term supporter (since 2023)
- Tencent Cloud EdgeOne EdgeOne CDN by TencentCloud
CDN Sponsor
Individual Sponsors List
See Supporters.md
Open Source License Notice
This project is open-sourced under the GPLv2 license. You are welcome to use the code in compliance with the open-source license!
If you encounter any violations of the open-source license, we encourage you to email pmc@dragonos.org to report them. Let's work together to build a trustworthy open-source community.
👩💻 Contributors
"Open source shines because of you!" ✨
Thanks to all developers who submitted code, fixed issues, or reviewed PRs: