Users and permissions: accounts, login, enforced file permissions, setuid, su, passwd, doas

The kernel now checks owner/group/other on open, create, unlink, rename, exec
and path search; honours set-user-id and set-group-id; restricts kill, mount,
reboot and mknod; keeps supplementary groups; and implements chown. devtmpfs
nodes carry owners and modes that chmod/chown keep. Terminals run login, the
image has root and schos, X starts as the ordinary user.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EVRhxi9zpdW2uDUN4FVcao
This commit is contained in:
Nexoniarz 2026-10-26 13:16:07 +01:00
commit 020aa6113c
34 changed files with 1342 additions and 120 deletions

View file

@ -5,6 +5,7 @@
#include "arch/mmu.h"
#include "core/proc.h"
#include "core/defs.h"
#include "uapi/stat.h"
#include "arch/x86.h"
#include "core/elf.h"
#include "uapi/fcntl.h"
@ -403,6 +404,10 @@ exec_elf(char *path, struct argsrc *av, struct argsrc *ev)
begin_op();
int in_op = 1; // the error path closes the transaction only once
int ret = -1;
// What the file's mode asks for, read while it is still locked: a program
// with the set-user-id bit runs as its owner, set-group-id as its group.
int want_suid = 0, want_sgid = 0;
uint file_uid = 0, file_gid = 0;
int err;
if((ip = nameifollow(0, path, &err)) == 0){
@ -415,6 +420,20 @@ exec_elf(char *path, struct argsrc *av, struct argsrc *ev)
ilock(ip);
pgdir = 0;
// To run a file is to have execute permission on it, and it has to be a
// plain file: a directory has the bit and is not a program.
if(ip->type == T_DIR || ip->type == T_DEV || inode_permission(ip, 1, 0) < 0){
ret = -EACCES;
goto bad;
}
{
uint m = inode_mode_bits(ip);
want_suid = (m & 04000) != 0;
want_sgid = (m & 02000) != 0 && (m & 010) != 0;
file_uid = ip->uid;
file_gid = ip->gid;
}
if(readi(ip, 0, (uint64)&elf, 0, sizeof(elf)) != sizeof(elf)){
ret = -ENOEXEC; // too short to be anything we can run
goto bad;
@ -572,6 +591,15 @@ exec_elf(char *path, struct argsrc *av, struct argsrc *ev)
myproc()->sz = sz;
pgdir = 0; // newmm owns it now; not bad:'s to free
// The new image's identity. The saved ids become the effective ones, which
// is what lets a program drop its privilege and take it back (su, sudo).
if (want_suid)
myproc()->euid = file_uid;
if (want_sgid)
myproc()->egid = file_gid;
myproc()->suid = myproc()->euid;
myproc()->sgid = myproc()->egid;
// New address space: reset all per-process mmap/signal/TLS state.
// sig_handler/sig_restorer point into the *old* image — POSIX resets
// handled signals to default on exec, and keeping them would make the