test: add more cases for coreTest

This commit is contained in:
dualfroz committed 2026-09-10 11:07:59 +02:00
1 parent 5f60d0e517
commit 1c389a47f6
1 file changed
+158
+158
View File
@@ -314,3 +314,161 @@ KTEST(coreVfsResolveOpenRequiresFileReadPermission)
KT_GE(t, wfd2, 0); /* write-only still works -- the two bits are independent */
vfsClose(wfd2);
KT_EQ(t, vfsChmod("/tmp/readf", fsModeDefaultFile), 0);
int rfd2 = vfsOpen("/tmp/readf", oReadOnly);
KT_GE(t, rfd2, 0);
vfsClose(rfd2);
vfsUnlink("/tmp/readf");
}
/* chmod on a missing path, or on the never-writable ustar-loaded /bin
content, is rejected exactly like every other tmpfs mutation already
gates on node->writable (vfsUnlink, vfsWrite's write path) -- chmod is a
metadata mutation too, so it obeys the same rule. Also proves every
ustar-loaded binary really does get the owner-exec bit by default
(vfs.c's ustarAdd), the fact loadImageByPath/jobctlSpawn's own exec-
permission check depends on for every existing spawnUser/userSpawn call
in this kernel to keep working at all. */
KTEST(coreVfsChmodRejectsMissingAndReadonlyBin)
{
KT_EQ(t, vfsChmod("/tmp/doesNotExist", 0644), -1);
KT_EQ(t, vfsChmod("/bin/false", 0777), -1);
FbStat st;
KT_EQ(t, vfsStat("/bin/false", &st), 0);
KT_EQ(t, st.mode, fsModeDefaultExec);
}
/* Same round trip on the persistent SFS mount, PLUS the "survives
unmount+remount" proof every other SFS-persisted field (mtime/ctime,
FALA 39) already has -- mode genuinely lives on disk, not just in the
in-memory inode cache. */
KTEST(coreVfsChmodSfsPersistsAcrossRemount)
{
KT_EQ(t, vfsMkdir("/mnt/chmodd"), 0);
int fd = vfsOpen("/mnt/chmodd/f", oReadWrite | oCreate);
KT_GE(t, fd, 0);
vfsClose(fd);
FbStat st;
KT_EQ(t, vfsStat("/mnt/chmodd/f", &st), 0);
KT_EQ(t, st.mode, fsModeDefaultFile);
KT_EQ(t, vfsChmod("/mnt/chmodd/f", 0400), 0);
KT_EQ(t, vfsOpen("/mnt/chmodd/f", oWriteOnly), -1);
sfsUnmount();
KT_TRUE(t, sfsMount());
KT_EQ(t, vfsStat("/mnt/chmodd/f", &st), 0);
KT_EQ(t, st.mode, 0400u);
KT_EQ(t, vfsOpen("/mnt/chmodd/f", oWriteOnly), -1);
KT_EQ(t, vfsChmod("/mnt/chmodd/f", fsModeDefaultFile), 0);
int wfd = vfsOpen("/mnt/chmodd/f", oWriteOnly);
KT_GE(t, wfd, 0);
vfsClose(wfd);
vfsUnlink("/mnt/chmodd/f");
vfsRmdir("/mnt/chmodd");
}
/* Real Unix owner/group/other permission algorithm (vfs.c's vfsPermitted)
-- pure-logic coverage of the whole decision matrix, since the function
takes every credential as an explicit argument instead of reading a live
thread (see its own doc comment). Deliberately includes uid 0 on BOTH
sides of the owner/other split (coreVfsPermittedUidZeroIsNotASuperuser
below) -- uid 0 gets no special treatment at all, the one property that
distinguishes this from real Unix's root and the exact regression this
test guards: an earlier version of vfsPermitted let uid 0 bypass every
bit unconditionally, which silently broke every OTHER permission test in
this file (coreVfsChmodTmpfsWritePermission,
coreVfsChmodSfsPersistsAcrossRemount both run as ktestRunAll's own idle
thread, uid 0) the moment chmod took away the write bit on a file that
same uid-0 caller had just created. Every "hits the other branch" case
below deliberately gives a MISMATCHED gid too (not just a mismatched
uid) -- otherwise an incidental gid match would silently redirect the
check into the new group branch instead of exercising other at all. */
KTEST(coreVfsPermittedOwnerMatchChecksOwnerBitOnly)
{
/* Owner-uid match short-circuits before gid is ever consulted, so gid
values here are deliberately irrelevant -- 0 on both sides. */
/* Owner bit set, other bit clear: an owning caller passes. */
KT_TRUE(t, vfsPermitted(0600, 1000, 0, 1000, 0, fsModeOwnerWrite));
/* Owner bit clear, other bit set: an owning caller still fails --
owning the file never grants what the OTHER bits happen to allow. */
KT_FALSE(t, vfsPermitted(0004, 1000, 0, 1000, 0, fsModeOwnerWrite));
}
KTEST(coreVfsPermittedNonOwnerChecksOtherBitOnly)
{
/* Other-write set, owner-write clear, DIFFERENT uid AND gid: passes on
the other bit even though the owner bit alone would refuse. */
KT_TRUE(t, vfsPermitted(0002, 1000, 10, 2000, 20, fsModeOwnerWrite));
/* Neither bit helps a stranger if the other bit is the one clear. */
KT_FALSE(t, vfsPermitted(0600, 1000, 10, 2000, 20, fsModeOwnerWrite));
KT_FALSE(t, vfsPermitted(0000, 1000, 10, 2000, 20, fsModeOwnerExec));
}
KTEST(coreVfsPermittedUidZeroIsNotASuperuser)
{
/* uid 0 as OWNER: governed by the owner bit exactly like any other
uid, matching every existing chmod test's own assumption (every
boot-time process, including ktestRunAll itself, starts at uid 0). */
KT_TRUE(t, vfsPermitted(0600, 0, 0, 0, 0, fsModeOwnerWrite));
KT_FALSE(t, vfsPermitted(0000, 0, 0, 0, 0, fsModeOwnerWrite));
/* uid 0 as a NON-owner (and non-group-member): governed by the other
bit, no bypass at all -- a mode of 0 denies even uid 0 against
someone else's file. */
KT_FALSE(t, vfsPermitted(0700, 1000, 10, 0, 20, fsModeOwnerWrite));
KT_TRUE(t, vfsPermitted(0702, 1000, 10, 0, 20, fsModeOwnerWrite));
/* And symmetrically: owning a file as a non-zero uid is not somehow
MORE privileged than uid 0 owning one -- same algorithm either way. */
KT_FALSE(t, vfsPermitted(0600, 42, 10, 0, 20, fsModeOwnerWrite));
}
/* Every fsModeOwner/fsModeOther pair used by a real choke point
(resolveOpen's write check, loadImageByPath/jobctlSpawn's exec check)
round-trips through the exact bit-shift vfsPermitted derives one from
the other with -- not just fsModeOwnerWrite from the test above. */
KTEST(coreVfsPermittedExecBitFollowsSameOwnerOtherSplit)
{
KT_TRUE(t, vfsPermitted(fsModeOtherExec, 1, 10, 2, 20, fsModeOwnerExec));
KT_FALSE(t, vfsPermitted(fsModeOwnerExec, 1, 10, 2, 20, fsModeOwnerExec));
KT_TRUE(t, vfsPermitted(fsModeOwnerExec, 1, 10, 1, 10, fsModeOwnerExec));
}
/* The new middle branch: a caller whose UID does not match the owner but
whose GID matches the node's group is governed by the fsModeGroup* bit
(wantOwnerBit >> 3), never falling all the way through to other -- and a
group bit set does NOT imply the other bit is, proving this is a
genuinely separate check, not just "not owner" collapsing to one
fallback like the pre-group-model version of this function used to. */
KTEST(coreVfsPermittedGroupMatchChecksGroupBitOnly)
{
/* Group-write set, owner/other-write clear: different uid, same gid. */
KT_TRUE(t, vfsPermitted(0020, 1000, 10, 2000, 10, fsModeOwnerWrite));
/* Group bit clear: a gid match alone grants nothing by itself. */
KT_FALSE(t, vfsPermitted(0602, 1000, 10, 2000, 10, fsModeOwnerWrite));
/* Every fsModeOwner/fsModeGroup pair round-trips through the >>3 shift,
not just write above. */
KT_TRUE(t, vfsPermitted(fsModeGroupExec, 1, 10, 2, 10, fsModeOwnerExec));
/* Owner-uid match takes priority over a coincidental gid match: the
caller here is BOTH the owner AND shares the owner's own gid, but the
decision must still come from the owner bit, not group. */
KT_TRUE(t, vfsPermitted(0100, 1, 10, 1, 10, fsModeOwnerExec));
KT_FALSE(t, vfsPermitted(0010, 1, 10, 1, 10, fsModeOwnerExec));
}
/* Real owner identity (fs.h's FbStat.uid, vfs.c's vfsUid): a fresh tmpfs
node is stamped with whoever created it -- ktestRunAll always runs as
the permanent idle thread (id 0, uid 0, "root"), the same context
schedTest.c's own pgid-default tests already document relying on, so
every node created here is root-owned by construction. */
KTEST(coreVfsTmpfsNodeStampsCreatorAsOwner)
{
int fd = vfsOpen("/tmp/uidf", oReadWrite | oCreate);
KT_GE(t, fd, 0);
vfsClose(fd);