Skip to content

Report startstack in procfs stat#227

Merged
jserv merged 1 commit into
sysprog21:mainfrom
open-sources-port:proc-self-stat
Jul 19, 2026
Merged

Report startstack in procfs stat#227
jserv merged 1 commit into
sysprog21:mainfrom
open-sources-port:proc-self-stat

Conversation

@doanbaotrung

@doanbaotrung doanbaotrung commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator

Record the initial guest user stack pointer and expose it as field 28 in /proc/self/stat and /proc/self/task//stat.

Carry the value across fork IPC and bump the private protocol magic so mixed parent/child builds reject the incompatible header layout.

Add procfs regression coverage to ensure startstack points inside the reported [stack] VMA.

Fix #226


Summary by cubic

Expose the initial user stack pointer as startstack (field 28) in /proc/self/stat and /proc/self/task//stat. Persist it across exec and fork, and add tests to confirm it’s the recorded SP and inside the [stack] VMA. Fixes #226.

  • New Features

    • Record start_stack during bootstrap and exec; emit it as field 28 in /proc/self/stat and /proc/self/task/<tid>/stat (with a safe fallback if unavailable).
    • Preserve start_stack through fork IPC; bump FORK_IPC_PROTOCOL_MAGIC to ELFN to reject mixed builds.
    • Add procfs tests for self and task stats to verify it lies within [stack], uses the recorded SP (not the fallback), and is preserved across fork.
  • Migration

    • Parent and child must run matching builds due to the protocol bump. Rebuild both together.

Written for commit 3534161. Summary will update on new commits.

Review in cubic

cubic-dev-ai[bot]

This comment was marked as resolved.

@doanbaotrung
doanbaotrung requested review from Max042004 and jserv July 18, 2026 18:47

@jserv jserv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The core change is correct (field 28 lands in the right column in both emitters, fallback keeps 16-byte SP alignment, fork-IPC struct insertion is 8-byte aligned, all four stack-establishing paths set start_stack, and the ELFM->ELFN magic bump rejects mixed builds).

Comment thread tests/test-procfs.c
}
}

TEST("procfs: stat startstack is in [stack]");

@jserv jserv Jul 19, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This test (and the task-stat one below) can pass vacuously. It only asserts startstack lies inside [stack], but proc_start_stack() falls back to stack_top - 16 when g->start_stack == 0, and that fallback is also inside [stack]. So if start_stack propagation ever breaks (left 0 on some path), the membership check still passes and the regression goes undetected. The test does catch a mis-placed stat field (that would read a neighboring literal 0), but not a lost value. Consider asserting the reported value differs from the stack_top-16 fallback, or comparing against an independently derived SP.

Comment thread src/runtime/forkipc.c
@@ -1678,6 +1679,7 @@ int64_t sys_clone(hv_vcpu_t vcpu,
.brk_current = g->brk_current,

@jserv jserv Jul 19, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This new wire-format field is the riskiest part of the PR, but nothing tests that it survives the fork IPC round-trip. test-fork-ipc-protocol-host.c only static-asserts the magic bumped to ELFN; no test forks a child and reads the child's /proc/self/stat field 28 to confirm start_stack packs/unpacks at the right offset. A fork→child field-28 check would close this.

Comment thread src/runtime/procemu.c
}

if (!strcmp(endp, "/stat")) {
uint64_t start_stack = proc_start_stack(g);

@jserv jserv Jul 19, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

/proc/self/task/<tid>/stat reports the process-wide g->start_stack for every tid, whereas real Linux reports each thread's own stack start. Harmless today (single guest_t, no per-thread stack tracking, the test only exercises the main tid), but a latent gap for CLONE_VM threads reading a non-main tid's field 28.

Comment thread tests/test-procfs.c Outdated
Comment thread tests/test-procfs.c
p++;
while (*p != '\0' && field <= target) {
char *endp;
if (field == 3) {

@jserv jserv Jul 19, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

parse_proc_stat_field_u64 special-cases field 3 (endp = p+1, no field == target check), so it can't return field 3 and assumes state is exactly one character. Not exercised here (target is always 28), so no live impact — flagging only as a latent constraint if this helper gets reused.

Record the initial guest user stack pointer and expose it as field 28
in /proc/self/stat and /proc/self/task/<tid>/stat.

Carry the value across fork IPC and bump the private protocol magic so
mixed parent/child builds reject the incompatible header layout.

Add procfs regression coverage for direct and fork-restored startstack
values, including checks that the fallback value is not used.

Fix sysprog21#226
@doanbaotrung

Copy link
Copy Markdown
Collaborator Author

Fixed base on comments. What changed:

  • The startstack tests no longer pass vacuously on the stack_top - 16 fallback.
  • Added a fork test that confirms the child sees the same field 28 value after fork IPC restore.
  • Increased /proc/self/maps buffer from 4 KiB to 64 KiB.
  • Tightened parse_proc_stat_field_u64() so it explicitly rejects unsupported fields < 4 instead of pretending it can parse field 3.

@jserv
jserv merged commit 7fa6388 into sysprog21:main Jul 19, 2026
10 checks passed
@jserv

jserv commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Thank @doanbaotrung for contributing!

@doanbaotrung
doanbaotrung deleted the proc-self-stat branch July 19, 2026 14:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

/proc/self/stat reports startstack as 0 that breaking stack discovery

2 participants