diff --git a/apps/glogin.c b/apps/glogin.c index e58c28c9..04c2cbaf 100644 --- a/apps/glogin.c +++ b/apps/glogin.c @@ -119,6 +119,7 @@ int main (int argc, char ** argv) { pid_t _session_pid = fork(); if (!_session_pid) { + setgid(uid); setuid(uid); toaru_auth_set_vars(); char * args[] = {"/bin/session", NULL}; diff --git a/apps/live-session.c b/apps/live-session.c index ed801167..0fbeed45 100644 --- a/apps/live-session.c +++ b/apps/live-session.c @@ -27,6 +27,7 @@ int main(int argc, char * argv[]) { int _session_pid = fork(); if (!_session_pid) { + setgid(1000); setuid(1000); toaru_auth_set_vars(); diff --git a/apps/sudo.c b/apps/sudo.c index 90af3ee8..09c6db2b 100644 --- a/apps/sudo.c +++ b/apps/sudo.c @@ -128,6 +128,7 @@ static int sudo_loop(int (*prompt_callback)(char * username, char * password, in putenv("USER=root"); /* Actually become root, so real user id = 0 */ + setgid(0); setuid(0); if (!strcmp(argv[1], "-s")) { diff --git a/base/usr/include/kernel/process.h b/base/usr/include/kernel/process.h index dee74066..56c34f90 100644 --- a/base/usr/include/kernel/process.h +++ b/base/usr/include/kernel/process.h @@ -79,6 +79,10 @@ typedef struct process { uid_t user; uid_t real_user; + + gid_t user_group; + gid_t real_user_group; + unsigned int mask; char * name; diff --git a/base/usr/include/syscall.h b/base/usr/include/syscall.h index 413585e5..b63fc642 100644 --- a/base/usr/include/syscall.h +++ b/base/usr/include/syscall.h @@ -124,6 +124,9 @@ DECL_SYSCALL0(setsid); DECL_SYSCALL2(setpgid,int,int); DECL_SYSCALL1(getpgid,int); DECL_SYSCALL4(fswait3, int, int*, int, int*); +DECL_SYSCALL0(getgid); +DECL_SYSCALL0(getegid); +DECL_SYSCALL1(setgid, unsigned int); _End_C_Header diff --git a/base/usr/include/syscall_nums.h b/base/usr/include/syscall_nums.h index 5532a54c..65cc5b37 100644 --- a/base/usr/include/syscall_nums.h +++ b/base/usr/include/syscall_nums.h @@ -65,3 +65,6 @@ #define SYS_SETPGID 63 #define SYS_GETPGID 64 #define SYS_FSWAIT3 65 +#define SYS_GETGID 66 +#define SYS_GETEGID 67 +#define SYS_SETGID 68 diff --git a/base/usr/include/unistd.h b/base/usr/include/unistd.h index 97bef392..3b080f0a 100644 --- a/base/usr/include/unistd.h +++ b/base/usr/include/unistd.h @@ -28,6 +28,7 @@ extern int execve(const char *name, char * const argv[], char * const envp[]); extern void _exit(int status); extern int setuid(uid_t uid); +extern int setgid(gid_t gid); extern uid_t getuid(void); extern uid_t geteuid(void); diff --git a/kernel/sys/process.c b/kernel/sys/process.c index 1ebab616..bf3008f6 100644 --- a/kernel/sys/process.c +++ b/kernel/sys/process.c @@ -367,6 +367,8 @@ process_t * spawn_init(void) { init->cmdline = NULL; init->user = USER_ROOT_UID; init->real_user = USER_ROOT_UID; + init->user_group = USER_ROOT_UID; + init->real_user_group = USER_ROOT_UID; init->mask = 022; init->status = 0; @@ -427,6 +429,8 @@ process_t * spawn_process(volatile process_t * parent, int flags) { proc->user = parent->user; proc->real_user = parent->real_user; + proc->user_group = parent->user_group; + proc->real_user_group = parent->real_user_group; proc->mask = parent->mask; proc->job = parent->job; proc->session = parent->session; @@ -1259,6 +1263,8 @@ process_t * spawn_worker_thread(void (*entrypoint)(void * argp), const char * na /* Are these necessary for tasklets? Should probably all be zero. */ proc->user = 0; proc->real_user = 0; + proc->user_group = 0; + proc->real_user_group = 0; proc->mask = 0; proc->job = proc->id; proc->session = proc->id; diff --git a/kernel/sys/syscall.c b/kernel/sys/syscall.c index 25fc9cad..b3e4e277 100644 --- a/kernel/sys/syscall.c +++ b/kernel/sys/syscall.c @@ -482,6 +482,23 @@ static long sys_setuid(uid_t new_uid) { return -EPERM; } +static long sys_getgid(void) { + return (long)this_core->current_process->real_user_group; +} + +static long sys_getegid(void) { + return (long)this_core->current_process->user_group; +} + +static long sys_setgid(gid_t new_gid) { + if (this_core->current_process->user == USER_ROOT_UID) { + this_core->current_process->user_group = new_gid; + this_core->current_process->real_user_group = new_gid; + return 0; + } + return -EPERM; +} + static long sys_getpid(void) { /* The user actually wants the pid of the originating thread (which can be us). */ return this_core->current_process->group ? (long)this_core->current_process->group : (long)this_core->current_process->id; @@ -959,6 +976,9 @@ static long (*syscalls[])() = { [SYS_SIGNAL] = sys_signal, [SYS_KILL] = sys_kill, [SYS_REBOOT] = sys_reboot, + [SYS_GETGID] = sys_getgid, + [SYS_GETEGID] = sys_getegid, + [SYS_SETGID] = sys_setgid, [SYS_SOCKET] = net_socket, [SYS_SETSOCKOPT] = net_setsockopt, diff --git a/kernel/vfs/tmpfs.c b/kernel/vfs/tmpfs.c index e0a14cc7..39eed5be 100644 --- a/kernel/vfs/tmpfs.c +++ b/kernel/vfs/tmpfs.c @@ -451,7 +451,7 @@ static int create_tmpfs(fs_node_t *parent, char *name, mode_t permission) { struct tmpfs_file * t = tmpfs_file_new(name); t->mask = permission; t->uid = this_core->current_process->user; - t->gid = this_core->current_process->user; + t->gid = this_core->current_process->user_group; spin_lock(tmpfs_lock); list_insert(d->files, t); diff --git a/kernel/vfs/tty.c b/kernel/vfs/tty.c index d37ce0cc..46a1bcd3 100644 --- a/kernel/vfs/tty.c +++ b/kernel/vfs/tty.c @@ -445,7 +445,7 @@ fs_node_t * pty_master_create(pty_t * pty) { fnode->name[0] = '\0'; snprintf(fnode->name, 100, "pty master"); fnode->uid = this_core->current_process->user; - fnode->gid = 0; + fnode->gid = this_core->current_process->user_group; fnode->mask = 0666; fnode->flags = FS_PIPE; fnode->read = read_pty_master; @@ -474,7 +474,7 @@ fs_node_t * pty_slave_create(pty_t * pty) { fnode->name[0] = '\0'; snprintf(fnode->name, 100, "pty slave"); fnode->uid = this_core->current_process->user; - fnode->gid = 0; + fnode->gid = this_core->current_process->user_group; fnode->mask = 0620; fnode->flags = FS_CHARDEVICE; fnode->read = read_pty_slave; diff --git a/kernel/vfs/vfs.c b/kernel/vfs/vfs.c index 3d4b7acd..c63f91d2 100644 --- a/kernel/vfs/vfs.c +++ b/kernel/vfs/vfs.c @@ -68,17 +68,16 @@ int has_permission(fs_node_t * node, int permission_bit) { uint64_t permissions = node->mask; + uint8_t my_permissions = (permissions) & 07; uint8_t user_perm = (permissions >> 6) & 07; - //uint8_t group_perm = (permissions >> 3) & 07; - uint8_t other_perm = (permissions) & 07; + uint8_t group_perm = (permissions >> 3) & 07; - if (this_core->current_process->user == node->uid) { - return (permission_bit & user_perm); - /* TODO group permissions? */ - } else { - return (permission_bit & other_perm); - } + if (this_core->current_process->user == node->uid) my_permissions |= user_perm; + if (this_core->current_process->user_group == node->uid) my_permissions |= group_perm; + /* TODO: Supplementary group IDs */ + + return (permission_bit & my_permissions); } static struct dirent * readdir_mapper(fs_node_t *node, unsigned long index) { diff --git a/libc/unistd/getegid.c b/libc/unistd/getegid.c index 8d9ff7a3..e863498b 100644 --- a/libc/unistd/getegid.c +++ b/libc/unistd/getegid.c @@ -1,6 +1,10 @@ #include +#include +#include -int getegid() { - return getgid(); +DEFN_SYSCALL0(getegid, SYS_GETEGID); + +gid_t getegid(void) { + return syscall_getegid(); } diff --git a/libc/unistd/getgid.c b/libc/unistd/getgid.c index a29ae23e..6fdad07b 100644 --- a/libc/unistd/getgid.c +++ b/libc/unistd/getgid.c @@ -1,5 +1,10 @@ #include +#include +#include -int getgid() { - return getuid(); +DEFN_SYSCALL0(getgid, SYS_GETGID); + +gid_t getgid(void) { + return syscall_getgid(); } + diff --git a/libc/unistd/setgid.c b/libc/unistd/setgid.c new file mode 100644 index 00000000..34ead22b --- /dev/null +++ b/libc/unistd/setgid.c @@ -0,0 +1,11 @@ +#include +#include +#include +#include + +DEFN_SYSCALL1(setgid, SYS_SETGID, unsigned int); + +int setgid(gid_t uid) { + __sets_errno(syscall_setgid(uid)); +} + diff --git a/libc/unistd/setuid.c b/libc/unistd/setuid.c index b33a3721..b3e30ca6 100644 --- a/libc/unistd/setuid.c +++ b/libc/unistd/setuid.c @@ -1,9 +1,10 @@ #include #include #include +#include DEFN_SYSCALL1(setuid, SYS_SETUID, unsigned int); int setuid(uid_t uid) { - return syscall_setuid(uid); + __sets_errno(syscall_setuid(uid)); }