feat: expand syscall
This commit is contained in:
1 parent
643fa45f6a
commit
aad9d4ece8
1 file changed
+173
+173
@@ -444,6 +444,179 @@ uint64 syscallDispatch(Registers* regs)
|
|||||||
regs->rax = (uint64)(int64)vfsUnlink(path);
|
regs->rax = (uint64)(int64)vfsUnlink(path);
|
||||||
return (uint64)regs;
|
return (uint64)regs;
|
||||||
}
|
}
|
||||||
|
case sysRmdir: {
|
||||||
|
char path[256];
|
||||||
|
if (!copyUserPath(regs->rdi, path, sizeof(path)))
|
||||||
|
regs->rax = (uint64)-1;
|
||||||
|
else
|
||||||
|
regs->rax = (uint64)(int64)vfsRmdir(path);
|
||||||
|
return (uint64)regs;
|
||||||
|
}
|
||||||
|
case sysChmod: {
|
||||||
|
char path[256];
|
||||||
|
if (!copyUserPath(regs->rdi, path, sizeof(path)))
|
||||||
|
regs->rax = (uint64)-1;
|
||||||
|
else
|
||||||
|
regs->rax = (uint64)(int64)vfsChmod(path, (uint32)regs->rsi);
|
||||||
|
return (uint64)regs;
|
||||||
|
}
|
||||||
|
case sysChown: {
|
||||||
|
char path[256];
|
||||||
|
if (!copyUserPath(regs->rdi, path, sizeof(path)))
|
||||||
|
regs->rax = (uint64)-1;
|
||||||
|
else
|
||||||
|
regs->rax = (uint64)(int64)vfsChown(path, (uint32)regs->rsi);
|
||||||
|
return (uint64)regs;
|
||||||
|
}
|
||||||
|
case sysGetuid:
|
||||||
|
/* Real getuid(2): no arguments, always succeeds, straight through
|
||||||
|
to the calling thread's own credential. */
|
||||||
|
regs->rax = (uint64)currentThreadUid();
|
||||||
|
return (uint64)regs;
|
||||||
|
case sysSetuid:
|
||||||
|
/* Real setuid(2): currentThreadSetUid (sched.h) itself enforces the
|
||||||
|
actual privilege rule (uid 0 may become anyone; anyone else may
|
||||||
|
only pass their own current uid back in) -- this dispatch case
|
||||||
|
does no additional validation of its own, matching sysChdir's own
|
||||||
|
"the underlying function already checks everything" split. */
|
||||||
|
regs->rax = currentThreadSetUid((uint32)regs->rdi) ? 0 : (uint64)-1;
|
||||||
|
return (uint64)regs;
|
||||||
|
case sysGetgid:
|
||||||
|
/* Real getgid(2): same shape as sysGetuid above. */
|
||||||
|
regs->rax = (uint64)currentThreadGid();
|
||||||
|
return (uint64)regs;
|
||||||
|
case sysSetgid:
|
||||||
|
/* Real setgid(2): currentThreadSetGid (sched.h) itself enforces the
|
||||||
|
actual privilege rule (gated by this thread's own UID, not GID --
|
||||||
|
see that function's own doc comment). */
|
||||||
|
regs->rax = currentThreadSetGid((uint32)regs->rdi) ? 0 : (uint64)-1;
|
||||||
|
return (uint64)regs;
|
||||||
|
case sysChgrp: {
|
||||||
|
char path[256];
|
||||||
|
if (!copyUserPath(regs->rdi, path, sizeof(path)))
|
||||||
|
regs->rax = (uint64)-1;
|
||||||
|
else
|
||||||
|
regs->rax = (uint64)(int64)vfsChgrp(path, (uint32)regs->rsi);
|
||||||
|
return (uint64)regs;
|
||||||
|
}
|
||||||
|
case sysPidfdOpen:
|
||||||
|
/* vfsPidfdOpen (vfs.c) already does every validity check pidfd.h's
|
||||||
|
own pidfdOpen needs (id 0/out-of-range/already-unused target) and
|
||||||
|
the fd-table installation vfsPipe/vfsPipeAttach's own dispatch
|
||||||
|
cases above delegate the same way -- nothing left for this
|
||||||
|
handler to add. */
|
||||||
|
regs->rax = (uint64)vfsPidfdOpen((uint32)regs->rdi);
|
||||||
|
return (uint64)regs;
|
||||||
|
case sysPidfdSend: {
|
||||||
|
/* vfsPidfdTarget folds "is this fd even a live pidfd" and "has the
|
||||||
|
original target since been reaped/recycled" (pidfd.h's own
|
||||||
|
generation check) into one call -- a stale handle is rejected
|
||||||
|
right here, before sigRaiseInfo ever sees a pid, which is
|
||||||
|
exactly the ABA-safety pidfd.h exists to provide over a raw
|
||||||
|
userSigSend(pid, signum) on a cached pid (see pidfd.h's own file
|
||||||
|
comment). Otherwise identical to sysSigSend's own single-target
|
||||||
|
path just above (same siCodeUser/senderPid convention, same
|
||||||
|
sigKill/sigStop bypasses already living inside sigRaiseInfo). */
|
||||||
|
uint32 target = vfsPidfdTarget((int)regs->rdi);
|
||||||
|
if (target == threadInvalidId) {
|
||||||
|
regs->rax = (uint64)-1;
|
||||||
|
return (uint64)regs;
|
||||||
|
}
|
||||||
|
int signum = (int)regs->rsi;
|
||||||
|
bool ok = sigRaiseInfo(target, signum, siCodeUser, (int)currentThreadId(), 0);
|
||||||
|
regs->rax = ok ? 0 : (uint64)-1;
|
||||||
|
return (uint64)regs;
|
||||||
|
}
|
||||||
|
case sysPidfdWait: {
|
||||||
|
/* Same retry-the-syscall park pattern as sysWait's own specific-pid
|
||||||
|
path below, just resolving the target through a pidfd instead of
|
||||||
|
a raw pid -- re-resolved on EVERY retry (not just the first
|
||||||
|
check), so a target that gets reaped by someone else while this
|
||||||
|
thread is blocked is caught the instant this thread wakes back
|
||||||
|
up, rather than only at the moment sysPidfdWait was first called.
|
||||||
|
threadJoin(target) below only ever reaps a thread this exact
|
||||||
|
check just proved is threadDead AND still the same incarnation
|
||||||
|
this handle was opened on, so there is no risk of it silently
|
||||||
|
reaping (or reporting the exit code of) an unrelated thread that
|
||||||
|
happens to have landed on the same numeric slot since. */
|
||||||
|
uint32 target = vfsPidfdTarget((int)regs->rdi);
|
||||||
|
if (target == threadInvalidId) {
|
||||||
|
regs->rax = (uint64)-1;
|
||||||
|
return (uint64)regs;
|
||||||
|
}
|
||||||
|
Thread* targetThread = threadAt(target);
|
||||||
|
if (targetThread->state != threadDead) {
|
||||||
|
currentThread()->sigInRetryableSyscall = true;
|
||||||
|
schedBlockCurrent(targetThread);
|
||||||
|
regs->rip -= 2;
|
||||||
|
return schedule((uint64)regs);
|
||||||
|
}
|
||||||
|
regs->rax = (uint64)threadJoin(target);
|
||||||
|
return (uint64)regs;
|
||||||
|
}
|
||||||
|
case sysSymlink: {
|
||||||
|
char target[256];
|
||||||
|
char path[256];
|
||||||
|
if (!copyUserPath(regs->rdi, target, sizeof(target)) ||
|
||||||
|
!copyUserPath(regs->rsi, path, sizeof(path)))
|
||||||
|
regs->rax = (uint64)-1;
|
||||||
|
else
|
||||||
|
regs->rax = (uint64)(int64)vfsSymlink(path, target);
|
||||||
|
return (uint64)regs;
|
||||||
|
}
|
||||||
|
case sysReadlink: {
|
||||||
|
char path[256];
|
||||||
|
if (!copyUserPath(regs->rdi, path, sizeof(path)) || !userRangeOk(regs->rsi, regs->rdx))
|
||||||
|
regs->rax = (uint64)-1;
|
||||||
|
else
|
||||||
|
regs->rax = (uint64)vfsReadlink(path, (char*)regs->rsi, regs->rdx);
|
||||||
|
return (uint64)regs;
|
||||||
|
}
|
||||||
|
case sysLink: {
|
||||||
|
char oldPath[256];
|
||||||
|
char newPath[256];
|
||||||
|
if (!copyUserPath(regs->rdi, oldPath, sizeof(oldPath)) ||
|
||||||
|
!copyUserPath(regs->rsi, newPath, sizeof(newPath)))
|
||||||
|
regs->rax = (uint64)-1;
|
||||||
|
else
|
||||||
|
regs->rax = (uint64)(int64)vfsLink(oldPath, newPath);
|
||||||
|
return (uint64)regs;
|
||||||
|
}
|
||||||
|
case sysPipe: {
|
||||||
|
if (!userRangeOk(regs->rdi, 2 * sizeof(int))) {
|
||||||
|
regs->rax = (uint64)-1;
|
||||||
|
return (uint64)regs;
|
||||||
|
}
|
||||||
|
int* userFds = (int*)regs->rdi;
|
||||||
|
int readFd, writeFd;
|
||||||
|
if (vfsPipe(&readFd, &writeFd) < 0) {
|
||||||
|
regs->rax = (uint64)-1;
|
||||||
|
} else {
|
||||||
|
userFds[0] = readFd;
|
||||||
|
userFds[1] = writeFd;
|
||||||
|
regs->rax = 0;
|
||||||
|
}
|
||||||
|
return (uint64)regs;
|
||||||
|
}
|
||||||
|
case sysPipeCreate:
|
||||||
|
regs->rax = (uint64)vfsPipeCreateHandle();
|
||||||
|
return (uint64)regs;
|
||||||
|
case sysPipeAttach:
|
||||||
|
regs->rax = (uint64)vfsPipeAttach((int)regs->rdi, regs->rsi != 0);
|
||||||
|
return (uint64)regs;
|
||||||
|
case sysKill: {
|
||||||
|
/* Real kill(2)'s own pid<0/pid==0 convention (userKill's `pid` is
|
||||||
|
already a signed `long`, see ulib.h -- only this kernel-side
|
||||||
|
interpretation of the raw bit pattern was missing): pid>0 is the
|
||||||
|
single-target path this always had; pid==0 targets the caller's
|
||||||
|
OWN process group (threadKillGroup, sched.c -- naturally kills
|
||||||
|
no one else if this is the group's only OTHER member, since
|
||||||
|
threadKill itself already excludes the caller's own Running
|
||||||
|
thread); pid<0 targets group -pid, exactly like real
|
||||||
|
kill(-pgid, SIGKILL). */
|
||||||
|
int64 rawPid = (int64)regs->rdi;
|
||||||
|
bool ok;
|
||||||
|
if (rawPid > 0)
|
||||||
default:
|
default:
|
||||||
regs->rax = (uint64)-1;
|
regs->rax = (uint64)-1;
|
||||||
return (uint64)regs;
|
return (uint64)regs;
|
||||||
|
|||||||
Reference in new issue
Block a user