diff --git a/kernel-src/arch/x86-64/syscall.asm b/kernel-src/arch/x86-64/syscall.asm index 1a37ceea..36b93817 100644 --- a/kernel-src/arch/x86-64/syscall.asm +++ b/kernel-src/arch/x86-64/syscall.asm @@ -83,6 +83,10 @@ extern syscall_getresgid extern syscall_setresuid extern syscall_setresgid extern syscall_mprotect +extern syscall_setuid +extern syscall_seteuid +extern syscall_setgid +extern syscall_setegid syscalltab: dq syscall_print dq syscall_mmap @@ -168,7 +172,11 @@ dq syscall_getresgid dq syscall_setresuid dq syscall_setresgid dq syscall_mprotect -syscallcount equ 84 +dq syscall_setuid +dq syscall_seteuid +dq syscall_setgid +dq syscall_setegid +syscallcount equ 88 section .text global arch_syscall_entry ; on entry: diff --git a/kernel-src/arch/x86-64/syscalllog.c b/kernel-src/arch/x86-64/syscalllog.c index e37132ca..3ea3160d 100644 --- a/kernel-src/arch/x86-64/syscalllog.c +++ b/kernel-src/arch/x86-64/syscalllog.c @@ -5,7 +5,7 @@ #ifdef SYSCALL_LOGGING -#define SYSCALL_COUNT 84 +#define SYSCALL_COUNT 88 #define LOGSTR(x) arch_e9_puts(x) static char *name[] = { @@ -92,7 +92,11 @@ static char *name[] = { "getresgid", "setresuid", "setresgid", - "mprotect" + "mprotect", + "setuid", + "seteuid", + "setgid", + "setegid" }; static char *args[] = { @@ -179,7 +183,11 @@ static char *args[] = { "gidp %p egidp %p sgidp %p", // getresgid "uid %d euid %d suid %d", // setresuid "gid %d egid %d sgid %d", // setresgid - "addr %p len %lu prot %d" // mprotect + "addr %p len %lu prot %d", // mprotect + "uid %d", // setuid + "euid %d", // seteuid + "gid %d", // setgid + "egid %d" // setegid }; #endif diff --git a/kernel-src/include/kernel/auth.h b/kernel-src/include/kernel/auth.h index 5bc3e0f1..bd6ad4e4 100644 --- a/kernel-src/include/kernel/auth.h +++ b/kernel-src/include/kernel/auth.h @@ -4,9 +4,10 @@ #include #include -#define AUTH_SCOPE_COUNT 2 +#define AUTH_SCOPE_COUNT 3 #define AUTH_SCOPE_SYSTEM 0 #define AUTH_SCOPE_FILESYSTEM 1 +#define AUTH_SCOPE_CRED 2 #define AUTH_LISTENER_LIMIT 8 @@ -23,6 +24,13 @@ #define AUTH_ACTIONS_FILESYSTEM_SETATTR 8 #define AUTH_ACTIONS_FILESYSTEM_MOUNT 16 +#define AUTH_ACTIONS_CRED_SETRESUID 1 +#define AUTH_ACTIONS_CRED_SETRESGID 2 +#define AUTH_ACTIONS_CRED_SETUID 4 +#define AUTH_ACTIONS_CRED_SETGID 8 +#define AUTH_ACTIONS_CRED_SETEUID 16 +#define AUTH_ACTIONS_CRED_SETEGID 32 + typedef int (*authlistener_t)(cred_t *cred, int actions, void *arg0, void *arg1, void *arg2); typedef struct { @@ -40,6 +48,10 @@ static inline int auth_system_check(cred_t *cred, int actions) { return auth_check(AUTH_SCOPE_SYSTEM, cred, actions, NULL, NULL, NULL); } +static inline int auth_cred_check(cred_t *cred, int actions, int id, int eid, int sid) { + return auth_check(AUTH_SCOPE_CRED, cred, actions, &id, &eid, &sid); +} + static inline int auth_filesystem_convertaccess(int access) { int r = 0; diff --git a/kernel-src/include/kernel/cred.h b/kernel-src/include/kernel/cred.h index 7455d5b1..5871db35 100644 --- a/kernel-src/include/kernel/cred.h +++ b/kernel-src/include/kernel/cred.h @@ -15,6 +15,10 @@ typedef struct { int cred_setuids(cred_t *cred, int uid, int euid, int suid); int cred_setgids(cred_t *cred, int uid, int euid, int suid); +int cred_setuid(cred_t *cred, int uid); +int cred_seteuid(cred_t *cred, int euid); +int cred_setgid(cred_t *cred, int gid); +int cred_setegid(cred_t *cred, int egid); void cred_getuids(cred_t *cred, int *uidp, int *euidp, int *suidp); void cred_getgids(cred_t *cred, int *gidp, int *egidp, int *sgidp); void cred_doexec(cred_t *cred, int suid, int sgid); diff --git a/kernel-src/sys/cred.c b/kernel-src/sys/cred.c index 969bc419..9ad031d1 100644 --- a/kernel-src/sys/cred.c +++ b/kernel-src/sys/cred.c @@ -1,12 +1,15 @@ #include #include #include +#include int cred_setuids(cred_t *cred, int uid, int euid, int suid) { if (uid < -1 || euid < -1 || suid < -1 || (uid == -1 && euid == -1 && suid == -1)) return EINVAL; - // TODO do permission check to see if its possible + int error = auth_cred_check(cred, AUTH_ACTIONS_CRED_SETRESUID, uid, euid, suid); + if (error) + return error; cred->uid = (uid == -1) ? cred->uid : uid; cred->euid = (euid == -1) ? cred->euid : euid; @@ -19,7 +22,9 @@ int cred_setgids(cred_t *cred, int gid, int egid, int sgid) { if (gid < -1 || egid < -1 || sgid < -1 || (gid == -1 && egid == -1 && sgid == -1)) return EINVAL; - // TODO do permission check to see if its possible + int error = auth_cred_check(cred, AUTH_ACTIONS_CRED_SETRESGID, gid, egid, sgid); + if (error) + return error; cred->gid = (gid == -1) ? cred->gid : gid; cred->egid = (egid == -1) ? cred->egid : egid; @@ -28,6 +33,68 @@ int cred_setgids(cred_t *cred, int gid, int egid, int sgid) { return 0; } +int cred_setuid(cred_t *cred, int uid) { + if (uid < 0) + return EINVAL; + + int error = auth_cred_check(cred, AUTH_ACTIONS_CRED_SETUID, uid, -1, -1); + if (error) + return error; + + if (CRED_IS_ESU(cred)) { + cred->uid = uid; + cred->euid = uid; + cred->suid = uid; + } else { + cred->euid = uid; + } + + return 0; +} + +int cred_seteuid(cred_t *cred, int euid) { + if (euid < 0) + return EINVAL; + + int error = auth_cred_check(cred, AUTH_ACTIONS_CRED_SETEUID, -1, euid, -1); + if (error) + return error; + + cred->euid = euid; + return 0; +} + +int cred_setgid(cred_t *cred, int gid) { + if (gid < 0) + return EINVAL; + + int error = auth_cred_check(cred, AUTH_ACTIONS_CRED_SETGID, gid, -1, -1); + if (error) + return error; + + if (CRED_IS_ESU(cred)) { + cred->gid = gid; + cred->egid = gid; + cred->sgid = gid; + } else { + cred->egid = gid; + } + + return 0; +} + +int cred_setegid(cred_t *cred, int egid) { + if (egid < 0) + return EINVAL; + + int error = auth_cred_check(cred, AUTH_ACTIONS_CRED_SETEGID, -1, egid, -1); + if (error) + return error; + + cred->egid = egid; + return 0; +} + void cred_doexec(cred_t *cred, int suid, int sgid) { if (suid > -1) cred->euid = suid; diff --git a/kernel-src/sys/defaultauth.c b/kernel-src/sys/defaultauth.c index ac07d09e..ed314cc4 100644 --- a/kernel-src/sys/defaultauth.c +++ b/kernel-src/sys/defaultauth.c @@ -109,7 +109,96 @@ static int system(cred_t *cred, int actions, void *arg0, void *arg1, void *arg2) return weight ? AUTH_DECISION_ALLOW : AUTH_DECISION_DEFER; } +static int credlistener(cred_t *cred, int actions, void *arg0, void *arg1, void *arg2) { + int *id = arg0; + int *eid = arg1; + int *sid = arg2; + + int weight = 0; + if (actions & AUTH_ACTIONS_CRED_SETRESUID) { + if (CRED_IS_ESU(cred)) { + weight += 1; + } else { + if (*id != -1 && *id != cred->uid && *id != cred->euid && *id != cred->suid) + return AUTH_DECISION_DENY; + if (*eid != -1 && *id != cred->uid && *id != cred->euid && *id != cred->suid) + return AUTH_DECISION_DENY; + if (*sid != -1 && *sid != cred->uid && *sid != cred->euid && *sid != cred->suid) + return AUTH_DECISION_DENY; + + weight += 1; + } + + DONE_CHECK(actions); + } + + if (actions & AUTH_ACTIONS_CRED_SETRESGID) { + if (CRED_IS_ESU(cred)) { + weight += 1; + } else { + if (*id != -1 && *id != cred->gid && *id != cred->egid && *id != cred->sgid) + return AUTH_DECISION_DENY; + if (*eid != -1 && *id != cred->gid && *id != cred->egid && *id != cred->sgid) + return AUTH_DECISION_DENY; + if (*sid != -1 && *sid != cred->gid && *sid != cred->egid && *sid != cred->sgid) + return AUTH_DECISION_DENY; + + weight += 1; + } + + DONE_CHECK(actions); + } + + if (actions & AUTH_ACTIONS_CRED_SETUID) { + if (CRED_IS_ESU(cred)) { + weight += 1; + } else if (*id != cred->uid && *id != cred->suid) { + return AUTH_DECISION_DENY; + } + + weight += 1; + DONE_CHECK(actions) + } + + if (actions & AUTH_ACTIONS_CRED_SETGID) { + if (CRED_IS_ESU(cred)) { + weight += 1; + } else if (*id != cred->gid && *id != cred->sgid) { + return AUTH_DECISION_DENY; + } + + weight += 1; + DONE_CHECK(actions) + } + + if (actions & AUTH_ACTIONS_CRED_SETEUID) { + if (CRED_IS_ESU(cred)) { + weight += 1; + } else if (*eid != cred->uid && *eid != cred->suid) { + return AUTH_DECISION_DENY; + } + + weight += 1; + DONE_CHECK(actions) + } + + if (actions & AUTH_ACTIONS_CRED_SETEGID) { + if (CRED_IS_ESU(cred)) { + weight += 1; + } else if (*eid != cred->gid && *eid != cred->sgid) { + return AUTH_DECISION_DENY; + } + + weight += 1; + DONE_CHECK(actions) + } + + done: + return weight ? AUTH_DECISION_ALLOW : AUTH_DECISION_DEFER; +} + void defaultauth_init() { auth_registerlistener(AUTH_SCOPE_FILESYSTEM, filesystem); auth_registerlistener(AUTH_SCOPE_SYSTEM, system); + auth_registerlistener(AUTH_SCOPE_CRED, credlistener); } diff --git a/kernel-src/sys/syscalls/setresuid.c b/kernel-src/sys/syscalls/setresuid.c index 434b9ff1..f4047b79 100644 --- a/kernel-src/sys/syscalls/setresuid.c +++ b/kernel-src/sys/syscalls/setresuid.c @@ -10,3 +10,39 @@ syscallret_t syscall_setresuid(context_t *, uid_t uid, uid_t euid, uid_t suid) { return ret; } + +syscallret_t syscall_setuid(context_t *, uid_t uid) { + syscallret_t ret; + + ret.errno = cred_setuid(&_cpu()->thread->proc->cred, uid); + ret.ret = ret.errno ? -1 : 0; + + return ret; +} + +syscallret_t syscall_seteuid(context_t *, uid_t euid) { + syscallret_t ret; + + ret.errno = cred_seteuid(&_cpu()->thread->proc->cred, euid); + ret.ret = ret.errno ? -1 : 0; + + return ret; +} + +syscallret_t syscall_setgid(context_t *, gid_t gid) { + syscallret_t ret; + + ret.errno = cred_setgid(&_cpu()->thread->proc->cred, gid); + ret.ret = ret.errno ? -1 : 0; + + return ret; +} + +syscallret_t syscall_setegid(context_t *, uid_t egid) { + syscallret_t ret; + + ret.errno = cred_setegid(&_cpu()->thread->proc->cred, egid); + ret.ret = ret.errno ? -1 : 0; + + return ret; +} diff --git a/patches/mlibc/jinx-working-patch.patch b/patches/mlibc/jinx-working-patch.patch index bdbf7c1b..6f43980c 100644 --- a/patches/mlibc/jinx-working-patch.patch +++ b/patches/mlibc/jinx-working-patch.patch @@ -207,10 +207,10 @@ index 0000000..e5b087a + diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp new file mode 100644 -index 0000000..e58c9ac +index 0000000..5047fee --- /dev/null +++ mlibc-workdir/sysdeps/astral/generic/generic.cpp -@@ -0,0 +1,975 @@ +@@ -0,0 +1,979 @@ +#include +#include +#include @@ -285,19 +285,23 @@ index 0000000..e58c9ac + } + + int sys_setuid(uid_t id) { -+ return sys_setresuid(id, -1, -1); ++ long ret; ++ return syscall(SYSCALL_SETUID, &ret, id); + } + + int sys_setgid(gid_t id) { -+ return sys_setresgid(id, -1, -1); ++ long ret; ++ return syscall(SYSCALL_SETGID, &ret, id); + } + + int sys_seteuid(uid_t id) { -+ return sys_setresuid(-1, id, -1); ++ long ret; ++ return syscall(SYSCALL_SETEUID, &ret, id); + } + + int sys_setegid(gid_t id) { -+ return sys_setresgid(-1, id, -1); ++ long ret; ++ return syscall(SYSCALL_SETEGID, &ret, id); + } + + uid_t sys_getuid() { @@ -1205,10 +1209,10 @@ index 0000000..990eca0 +#endif diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h new file mode 100644 -index 0000000..4d30885 +index 0000000..90516f7 --- /dev/null +++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h -@@ -0,0 +1,107 @@ +@@ -0,0 +1,111 @@ +#ifndef _SYSCALL_H_INCLUDE +#define _SYSCALL_H_INCLUDE + @@ -1296,6 +1300,10 @@ index 0000000..4d30885 +#define SYSCALL_SETRESUID 81 +#define SYSCALL_SETRESGID 82 +#define SYSCALL_MPROTECT 83 ++#define SYSCALL_SETUID 84 ++#define SYSCALL_SETEUID 85 ++#define SYSCALL_SETGID 86 ++#define SYSCALL_SETEGID 87 + +#include +#include