feat: add eintrtarget and envprint
This commit is contained in:
1 parent
607eaff366
commit
6184cf43be
4 files changed
+179
No files matched your search
@@ -0,0 +1,61 @@
|
|||||||
|
#include "ulib.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only ever spawned by eintrtest.c. Attaches as the READ end of its own,
|
||||||
|
* self-contained pipe (userPipeCreate/userPipeAttach) that no writer will
|
||||||
|
* ever attach to -- the exact same "blocked forever" setup killtest.c's
|
||||||
|
* killvictim.c already uses for threadKill -- but the way out here is an
|
||||||
|
* ORDINARY signal (sigTerm, default disposition Terminate) going through
|
||||||
|
* the FULL sigRaise -> pending-bit -> early-wake -> deliverPendingSignals
|
||||||
|
* pipeline (signal.h/sched.c's threadWakeForSignal), not threadKill's
|
||||||
|
* direct ThreadState bypass. Before that early-wake existed, sigRaise only
|
||||||
|
* ever set a pending bit and left a Blocked thread exactly where it was --
|
||||||
|
* delivery only happens at a return-to-ring3 this process would otherwise
|
||||||
|
* never naturally reach again, so sigTerm sent here would have done
|
||||||
|
* nothing observable, ever: the read below is never naturally satisfied,
|
||||||
|
* by construction.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
print("eintrtarget: start, pid=");
|
||||||
|
printDec(userGetpid());
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
print("eintrtarget: FAIL expected one argv (ready handle)\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
long victimHandle = userPipeCreate();
|
||||||
|
if (victimHandle < 0) {
|
||||||
|
print("eintrtarget: FAIL create victim pipe\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
long victimFd = userPipeAttach(victimHandle, 0);
|
||||||
|
if (victimFd < 0) {
|
||||||
|
print("eintrtarget: FAIL attach victim pipe\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
long readyHandle = parseDec(argv[1]);
|
||||||
|
long readyFd = userPipeAttach(readyHandle, 1);
|
||||||
|
if (readyFd < 0) {
|
||||||
|
print("eintrtarget: FAIL attach ready pipe\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (userWrite((int)readyFd, "r", 1) != 1) {
|
||||||
|
print("eintrtarget: FAIL write ready byte\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
userClose((int)readyFd);
|
||||||
|
|
||||||
|
print("eintrtarget: blocking on read forever\n");
|
||||||
|
char buffer[4];
|
||||||
|
userRead((int)victimFd, buffer, sizeof(buffer));
|
||||||
|
|
||||||
|
/* Only reached if userRead somehow returned on its own -- eintrtest.c
|
||||||
|
never writes to the victim pipe, so that would itself be a bug. */
|
||||||
|
print("eintrtarget: FAIL read returned without being signaled\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
#include "ulib.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Live ring-3 proof for the real environment-variable subsystem (sched.h's
|
||||||
|
* Thread.env, syscall.c's sysGetEnv/sysSetEnv/sysUnsetEnv, shell.c's
|
||||||
|
* `export`/`env`/`unset` builtins and `$NAME` expansion) -- loaded on demand by
|
||||||
|
* the real interactive shell (kmain.c's envDriverThread types
|
||||||
|
* "export GREETING=frostbyte" then "envprint" at it, the same injected-
|
||||||
|
* keystroke mechanism every shell-driven demo above already uses), never
|
||||||
|
* boot-spawned, the same "no kmain.c spawnUser call, only /bin/NAME
|
||||||
|
* resolved by the shell's own fallback" shape jobctlfg.c/hcat.c/pipecat.c
|
||||||
|
* already established.
|
||||||
|
*
|
||||||
|
* Proves inheritance first (this process never called userSetEnv itself
|
||||||
|
* before the first check -- whatever it sees came only from
|
||||||
|
* threadCreateUser's own initialEnv copying the shell's table at spawn
|
||||||
|
* time), then proves this process's OWN later userSetEnv is visible to
|
||||||
|
* itself immediately, then proves userUnsetEnv actually removes the entry
|
||||||
|
* (a following userGetEnv on the same name fails) and that unsetting a
|
||||||
|
* name that was never set is still a no-op success, not an error. The
|
||||||
|
* other half of the isolation guarantee -- that
|
||||||
|
* this process's own mutation can never reach back into the PARENT
|
||||||
|
* shell's copy -- is proven by envDriverThread itself: it types a plain
|
||||||
|
* "env" at the shell AFTER this process has already exited and checks
|
||||||
|
* that the shell still reports the ORIGINAL "frostbyte" value, not
|
||||||
|
* "child-mutated" (mirrors cwdtest.c's own post-userWait
|
||||||
|
* parent-cwd-unaffected check, just driven through the shell instead of a
|
||||||
|
* direct userWait).
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
print("envprint: start, pid=");
|
||||||
|
printDec(userGetpid());
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
char value[32];
|
||||||
|
long len = userGetEnv("GREETING", value, sizeof(value));
|
||||||
|
if (len < 0) {
|
||||||
|
print("envprint: FAIL missing inherited GREETING\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
print("envprint: inherited-ok GREETING=");
|
||||||
|
print(value);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
if (userGetEnv("NO_SUCH_VAR", value, sizeof(value)) >= 0) {
|
||||||
|
print("envprint: FAIL unset variable returned a value\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userSetEnv("GREETING", "child-mutated") != 0) {
|
||||||
|
print("envprint: FAIL setenv\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
len = userGetEnv("GREETING", value, sizeof(value));
|
||||||
|
if (len < 0) {
|
||||||
|
print("envprint: FAIL read back own setenv\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
print("envprint: self-set-ok GREETING=");
|
||||||
|
print(value);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
if (userUnsetEnv("GREETING") != 0) {
|
||||||
|
print("envprint: FAIL unset\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (userGetEnv("GREETING", value, sizeof(value)) >= 0) {
|
||||||
|
print("envprint: FAIL unset did not remove variable\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
print("envprint: unset-ok\n");
|
||||||
|
|
||||||
|
/* Real unsetenv(3) is a no-op success on a name that was never set --
|
||||||
|
this must NOT be confused with a "not found" error. */
|
||||||
|
if (userUnsetEnv("NO_SUCH_VAR_EVER") != 0) {
|
||||||
|
print("envprint: FAIL unset-missing should be a no-op success\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
print("envprint: unset-missing-ok\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#include "ulib.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Never spawned directly by kmain.c or by proctest.c's userSpawn -- the
|
||||||
|
* only way this binary's "exectarget: running" line can ever appear in the
|
||||||
|
* boot log is if proctest.c's userExec("/bin/exectarget") call actually
|
||||||
|
* replaced proctest's own image with this one (see proctest.c). Its pid is
|
||||||
|
* therefore the SAME pid proctest was given at spawnUser time in kmain.c,
|
||||||
|
* which is what kmain.c's execReaperThread checks via threadJoin to prove
|
||||||
|
* exec() preserves process identity, not just that some program ran.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
print("exectarget: running, pid=");
|
||||||
|
printDec(userGetpid());
|
||||||
|
print("\n");
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#include "ulib.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Real POSIX false(1): does nothing, always exits 1. Exists purely so
|
||||||
|
* shell.c's new `&&`/`||` conditional chaining (execute()/executeSingle,
|
||||||
|
* shellSplitAndOr in shell.h) has a genuinely SPAWNED process (real
|
||||||
|
* fork-less spawn + real userExit, not just a builtin's own int return
|
||||||
|
* like doExport/changeDir) whose nonzero exit status drives a real `&&`
|
||||||
|
* skip followed by a real `||` fallback -- kmain.c's andOrDriverThread
|
||||||
|
* types `false && echo x || echo ao2` at the live shell to prove it.
|
||||||
|
*/
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user