Skip to content

fix(net): align Unix socket statfs and permission semantics - #2584

Merged
fslongjin merged 3 commits into
DragonOS-Community:masterfrom
fslongjin:codex/fix-unix-socket-statfs-permissions
Nov 5, 2026
Merged

fslongjin merged 3 commits into
DragonOS-Community:masterfrom
fslongjin:codex/fix-unix-socket-statfs-permissions

Conversation

@fslongjin

Copy link
Copy Markdown
Member

Summary

Make socket inodes participate in the normal VFS metadata and statfs contracts, so Unix sockets no longer need syscall-specific branches.

  • Give every socket a singleton sockfs identity and per-socket mutable inode metadata.
  • Return SOCKFS_MAGIC, PAGE_SIZE, NAME_MAX and frsize == bsize from fstatfs(2).
  • Initialize sockets with S_IFSOCK | 0777 and the creator's fsuid/fsgid, matching Linux sock_alloc().
  • Reuse do_fchmod() through masked metadata updates, preserving owner/CAP_FSETID/immutable/SGID/ctime semantics.
  • Derive Unix path bind permissions from the socket mode and current umask, matching unix_bind_bsd().
  • Keep AF_PACKET's TPACKET mmap filesystem and only share the sockfs statfs view.
  • Remove the three revalidated gVisor cases from the socket blocklist and add dunitest coverage.

Verification

  • make kernel: passed.
  • gVisor SocketTest.UnixSocketStat, SocketTest.UnixSocketStatFS, SocketTest.Permission: 3/3 passed in QEMU (KVM, snapshot disk).
  • normal/unix_socket_stat: 5/5 passed in QEMU.
  • AfPacketRing.FstatfsUsesSockfsBeforeAndAfterRingSetup: passed in QEMU.

No smoltcp change was required: this fix is confined to socket inode identity/metadata and path bind semantics.

Give every socket inode a sockfs identity and per-socket mutable metadata so the generic VFS paths can implement fstatfs(2), fchmod(2), and fstat(2) without socket-specific syscall branches.

- Reuse a singleton SockFs for SOCKFS_MAGIC, PAGE_SIZE, NAME_MAX and frsize.
- Initialize sockets with S_IFSOCK | 0777 and creator fsuid/fsgid.
- Implement masked metadata updates so do_fchmod keeps owner, CAP_FSETID, immutable, SGID and ctime semantics in one place.
- Derive Unix path bind permissions from the socket mode and current umask, matching Linux unix_bind_bsd().
- Keep AF_PACKET's mmap filesystem while sharing the sockfs statfs view.
- Cover the behavior with dunitest and unblock the three gVisor cases.

Signed-off-by: longjin <longjin@dragonos.org>
@github-actions github-actions Bot added Bug fix A bug is fixed in this pull request test Unitest/User space test labels Nov 4, 2026
@fslongjin

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-05T03:49:49.258916Z d03d25f Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 66a5dfe51a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Linux allocates the accepted socket's sockfs inode in the accepting task
(`sock_alloc()` from `do_accept()`), so `i_uid`/`i_gid` come from the
acceptor's fsuid/fsgid. DragonOS materializes some passive peers before
accept: Unix stream children are created by the connecting task in
`connect()`, and vsock children may be created by a transport worker.
They therefore inherited the wrong credentials, so `fstat(2)` reported
the peer's owner and an unprivileged acceptor could fail `fchmod(2)`
with EPERM.

Refresh the accepted socket's metadata owner in the shared accept path
before publishing the descriptor. The reset is protocol-agnostic, so it
covers Unix stream and vsock children without touching their handoff
paths.

Add a dunitest that connects as one euid, accepts from root, and checks
the accepted inode ownership, and remove an explicit auto-deref flagged
by clippy.

Verification:
- make kernel
- make fmt FMT_CHECK=--check
- QEMU dunitest normal/unix_socket_stat: 6/6 passed

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

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: cea894fb53

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown
Member Author

CI status on cea894fb5:

  • Format check (x86_64/riscv64/loongarch64), all builds, kernel static tests, and Dunitest pass.
  • Integration Test still reports 4 failures, all ENOENT in exec tests: ExecTest.InterpreterScript, ExecTest.SymlinkLimitRefreshedForInterpreter, ExecveatTest.SymlinkNoFollowIgnoreSymlinkAncestor, and ExecveatTest.SymlinkNoFollowWithNormalFile.
  • These are pre-existing on the base commit 6fa9f70ba: https://github.com/DragonOS-Community/DragonOS/actions/runs/41877946619/job/126742506875 fails with the identical 4 cases. They were unblocked by the preceding blocklist prune (test(gvisor): prune revalidated syscall blocklists #2583) and are unrelated to the socket changes here.
  • The three gVisor cases unblocked by this PR pass in the same Integration run: SocketTest.UnixSocketStat, SocketTest.UnixSocketStatFS, and SocketTest.Permission.

So the only red check is the pre-existing exec failure on master; this PR's socket behavior is covered by Dunitest and the target gVisor cases.

The gVisor exec tests resolve /bin/echo and /bin/bash directly. The
default CI rootfs is FAT32 built from BusyBox, which only installs
/bin/busybox and /bin/sh because FAT cannot represent applet symlinks.
The four unblocked tests therefore failed with ENOENT even though the
exec and namei semantics were correct.

Enable the BusyBox bash applet in both the DADK and Nix rootfs builds,
and materialize the two interpreter entry points at test start only when
they are missing. An existing executable, such as a base image's real
bash, is never replaced. Fixture setup now fails fast with a precise
diagnostic instead of letting the tests degrade into ENOENT.

Verified on a clean default FAT32 image: the fixture installs both entry
points, the four previously failing exec tests pass, and the socket
statfs/permission cases remain green.

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

Copy link
Copy Markdown
Member Author

The Integration Test failure was not only pre-existing: the four exec tests fail because the default CI rootfs is a FAT32 image built from BusyBox, which installs only /bin/busybox and /bin/sh. FAT cannot represent the BusyBox applet symlinks, so /bin/echo and /bin/bash are absent. ExecTest.InterpreterScript uses exit_script with #!/bin/bash, SymlinkLimitRefreshedForInterpreter uses /bin/echo, and both ExecveatTest.SymlinkNoFollow* cases exec /bin/echo; the kernel correctly returned ENOENT for a genuinely missing interpreter.

Fixed in d03d25f80:

  • Enable the BusyBox bash applet in both the DADK (user/apps/busybox/Makefile) and Nix (user/apps/default.nix) rootfs builds.
  • Prepare missing /bin/echo and /bin/bash entry points at gVisor test start (run_tests.sh). Existing executables, such as an Ubuntu base image's real bash, are never replaced.
  • Fixture preparation now fails fast with a precise diagnostic if BusyBox lacks the required applet or the entry point cannot be materialized, instead of degrading into hard-to-diagnose ENOENT.

Verified on a freshly rebuilt ROOTFS_MANIFEST=default FAT32 image with no pre-existing /bin/echo or /bin/bash:

  • Fixture installed both entry points from BusyBox.
  • exec_test: 47/47 unblocked cases pass, including all four previously failing cases; the only failure is ExecTest.ExecNameScript, which remains in the blocklist.
  • socket_test: 7/7 pass, including SocketTest.UnixSocketStat, SocketTest.UnixSocketStatFS, and SocketTest.Permission.

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep them coming!

Reviewed commit: d03d25f809

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown
Member Author

CI on d03d25f80 is green: Build Check, Test x86_64 (Integration Test), Dunitest x86_64, RISC-V Boot Smoke, and docs all pass. The Integration Test now completes with no exec failures.

@fslongjin
fslongjin merged commit f64a853 into DragonOS-Community:master Nov 5, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug fix A bug is fixed in this pull request test Unitest/User space test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant