brintos

brintos / linux public Read only

0
0

wasm32: sys_capget/sys_capset SYSCALL_DEFINE alias not materialized -> dangling relocation; wire via __se_sys_* #10

Open sasha opened this issue · 1 comment
S sasha commented

Summary

Wiring capget/capset into the wasm32 syscall table by referencing the plain sys_capget/sys_capset produces a dangling relocation (symbol index 0xFFFFFFFF) that crashes llvm-objcopy/wasm-ld (see the brintos/llvm-project parseRelocSection OOB issue). Root cause: sys_capget/sys_capset are asmlinkage SYSCALL_DEFINE aliases to __se_sys_capget/__se_sys_capset, and in the wasm object the plain alias is never materialized as a symbol (nothing else in the kernel references it). Kernel c1a1999b2.

Evidence

wasm32 vmlinux.o with capget wired via sys_capget:

  • reloc.CODE has 4 entries with symbol index 0xFFFFFFFF (2x R_WASM_FUNCTION_INDEX_LEB, 2x R_WASM_TABLE_INDEX_SLEB) at the sys_capget/sys_capset call sites.
  • symbol table has __se_sys_capget (idx 1277), __se_sys_capset (1278), __do_sys_capget/__do_sys_capset — but sys_capget/sys_capset are absent.
  • A/B: wiring the same slots to sys_ni_syscall (a materialized symbol) builds clean; pure-data padding of equal/greater size builds clean. So it is the alias reference specifically, not object size.

Fix

Wire the slots to the real entry the alias points to:

extern long __se_sys_capget(long a0, long a1);
extern long __se_sys_capset(long a0, long a1);
static long w_sys_capget(long a0,long a1,long a2,long a3,long a4,long a5)
{ IGNORE_TAIL_4; return __se_sys_capget(a0, a1); }
static long w_sys_capset(long a0,long a1,long a2,long a3,long a4,long a5)
{ IGNORE_TAIL_4; return __se_sys_capset(a0, a1); }
//  [125] = w_sys_capget,   [126] = w_sys_capset,

This resolves the relocation and the kernel links clean (vmlinux.o parses 20/20).

Runtime note (separate follow-up)

With capget so wired, capget still errors at runtime for libcap-ng pscap/captest: the main-thread gettid() (35) != getpid() (34), and libcap-ng addresses self by gettid(), so capget(hdr.pid=gettid) doesn't resolve. Until the wasm32-hwjs task/pid model is fixed, userspace reads caps from /proc/<pid>/status instead. So wiring the syscall is necessary but not sufficient for working process-capability tools.