# VFS-mutation syscalls (brintos/linux#5): mkdirat / chmod / chown / rename / fsync # / link, plus the fd forms fchmod / fchown (brintos/linux#8). # These returned ENOSYS before the wasm32 kernel wired them. GNU `mv` masks a # broken rename (copy-then-delete fallback) and no shell tool calls fsync, so the # syscalls are exercised at the C boundary by the data/vfs-probe payload, which # prints one `VFS- OK|FAIL` line each. data payloads install 0644; the wasm # exec bit is set on a private copy (chmod itself is one of the wired syscalls). # # The probe runs twice, against both filesystems the image has, because they do # not behave alike: /tmp is a tmpfs, the rootfs is the cloud virtio-fs. Only the # tmpfs pass ran until BRINTOS-52, which is why a virtio-fs rename defect reached # the image with this suite green. . "$BST_LIB" probe=${TMPDIR:-/tmp}/bst-vfs-probe.$$ cp "$BST_DATA/vfs-probe" "$probe" 2>/dev/null && chmod +x "$probe" 2>/dev/null || { bst_notok vfs/stage "cannot stage $BST_DATA/vfs-probe"; exit 0; } out=$("$probe" 2>&1) # One assertion per ticket syscall. The four wired upstream must pass; chown is a # known upstream gap (brintos/linux#5: no ownership model on the virtio-fs backend) # and reports its actual state so a future wiring flips this suite green. check_out vfs/mkdirat "VFS-mkdirat OK" printf '%s\n' "$out" check_out vfs/fsync "VFS-fsync OK" printf '%s\n' "$out" check_out vfs/chmod "VFS-chmod OK" printf '%s\n' "$out" check_out vfs/rename "VFS-rename OK" printf '%s\n' "$out" check_out vfs/chown "VFS-chown OK" printf '%s\n' "$out" # rename onto an EXISTING file — the write-.new-then-rename atomic update every # database-ish writer uses. Covered on the tmpfs first. check_out vfs/rename-over "VFS-rename-over OK" printf '%s\n' "$out" # --- link(2) — the sixth linux#5 syscall, and the one this suite never covered -- # `ln` (no -s) issues link(2) directly and has no fallback, so a refusal surfaces # as a failure here instead of being masked the way `mv`'s copy-then-delete hides # a broken rename. The identity assertion is st_ino equality — what tar and dpkg # use to recognise a hardlink — and deliberately NOT st_nlink, which the cloud # store under-reports on the link source (brintos-fs PLAN-CROSS-PLATFORM.md §10). hardlink_cases() { _dir=$1; _sfx=$2 if ! command -v ln >/dev/null 2>&1 || ! command -v stat >/dev/null 2>&1; then bst_skip "vfs/hardlink$_sfx" "ln or stat not installed on this image" bst_skip "vfs/hardlink-content$_sfx" "ln or stat not installed on this image" bst_skip "vfs/hardlink-ino$_sfx" "ln or stat not installed on this image" return fi _src="$_dir/bst-vfs-hl.$$"; _dst="$_dir/bst-vfs-hl-link.$$" rm -f "$_src" "$_dst" 2>/dev/null printf 'hardlink-payload\n' > "$_src" 2>/dev/null check "vfs/hardlink$_sfx" ln "$_src" "$_dst" check_out "vfs/hardlink-content$_sfx" "hardlink-payload" cat "$_dst" _si=$(stat -c %i "$_src" 2>/dev/null); _di=$(stat -c %i "$_dst" 2>/dev/null) if [ -n "$_si" ] && [ -n "$_di" ]; then check_eq "vfs/hardlink-ino$_sfx" "$_si" "$_di" else bst_notok "vfs/hardlink-ino$_sfx" "stat -c %i gave src='$_si' dst='$_di'" fi rm -f "$_src" "$_dst" 2>/dev/null } hardlink_cases "${TMPDIR:-/tmp}" "" # --- fchmod/fchown on an fd — brintos/linux#8 --------------------------------- # The chmod/chown cases above are the path forms, which glibc routes through # fchmodat/fchownat. [91] fchmod and [93] fchown are separate table entries and # were the pair linux#8 reported: bzip2 bails after writing a valid archive # because applySavedFileAttrToOutputFile() fchmod()s the output fd. No shell tool # calls either on an fd, so perl drives them — chmod/chown on a filehandle ARE # fchmod(2)/fchown(2), and each returns the count of files it changed, so a # refusal reads as 0. The mode is read back through fstat so an accept-and-drop # no-op cannot pass as success. fchown is issued with the file's own uid/gid and # asserts only that the call succeeds: on virtio-fs it is the sanctioned # accept-and-succeed no-op (that backend has no ownership model), so demanding a # uid change would assert something the platform legitimately does not do — and # re-setting the current owner needs no privilege, so the case does not silently # become a root-only assertion. fd_meta_cases() { _dir=$1; _sfx=$2 if ! command -v perl >/dev/null 2>&1; then bst_skip "vfs/fchmod$_sfx" "perl not installed on this image" bst_skip "vfs/fchmod-mode$_sfx" "perl not installed on this image" bst_skip "vfs/fchown$_sfx" "perl not installed on this image" return fi _f="$_dir/bst-vfs-fd.$$" rm -f "$_f" 2>/dev/null _o=$(perl -e ' my $p = shift; open(my $fh, ">", $p) or die "open: $!\n"; print $fh "x"; my $c = chmod(0640, $fh); my @s = stat($fh); my $m = $s[2] & 07777; my $o = chown($s[4], $s[5], $fh); close $fh; printf "FCHMOD=%d MODE=%o FCHOWN=%d\n", $c, $m, $o; ' "$_f" 2>&1) check_out "vfs/fchmod$_sfx" "FCHMOD=1" printf '%s\n' "$_o" check_out "vfs/fchmod-mode$_sfx" "MODE=640" printf '%s\n' "$_o" check_out "vfs/fchown$_sfx" "FCHOWN=1" printf '%s\n' "$_o" rm -f "$_f" 2>/dev/null } fd_meta_cases "${TMPDIR:-/tmp}" "" # --- the same probe against the rootfs (cloud virtio-fs) ---------------------- # The rootfs is read-only on an anonymously-booted session, which is the normal # case: skip rather than fail, since an absent capability is not a defect. An # owner-authenticated session makes it writable and the cases below run for real. vdir=/var/lib/bst-vfs if mkdir -p "$vdir" 2>/dev/null; then vout=$("$probe" /var/lib -vfs 2>&1) hardlink_cases "$vdir" "-vfs" fd_meta_cases "$vdir" "-vfs" rmdir "$vdir" 2>/dev/null check_out vfs/rename-vfs "VFS-rename-vfs OK" printf '%s\n' "$vout" check_out vfs/rename-over-vfs "VFS-rename-over-vfs OK" printf '%s\n' "$vout" else bst_skip vfs/rename-vfs "rootfs read-only (anonymous session); needs an owner-authenticated boot" bst_skip vfs/rename-over-vfs "rootfs read-only (anonymous session); needs an owner-authenticated boot" bst_skip vfs/hardlink-vfs "rootfs read-only (anonymous session); needs an owner-authenticated boot" bst_skip vfs/hardlink-content-vfs "rootfs read-only (anonymous session); needs an owner-authenticated boot" bst_skip vfs/hardlink-ino-vfs "rootfs read-only (anonymous session); needs an owner-authenticated boot" bst_skip vfs/fchmod-vfs "rootfs read-only (anonymous session); needs an owner-authenticated boot" bst_skip vfs/fchmod-mode-vfs "rootfs read-only (anonymous session); needs an owner-authenticated boot" bst_skip vfs/fchown-vfs "rootfs read-only (anonymous session); needs an owner-authenticated boot" fi rm -f "$probe"