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:
parent
b3f72cd95e
commit
020aa6113c
34 changed files with 1342 additions and 120 deletions
|
|
@ -59,18 +59,27 @@ sys_kill(void)
|
|||
// pid == 0 -> every process in the caller's own group
|
||||
// pid == -1 -> every process we may signal (approximated as our group)
|
||||
// pid < -1 -> the process group with id -pid
|
||||
if (pid == 0 || pid == -1)
|
||||
return sigsend_pgrp(myproc()->pgid, sig) < 0 ? -ESRCH : 0;
|
||||
if (pid < -1)
|
||||
return sigsend_pgrp(-pid, sig) < 0 ? -ESRCH : 0;
|
||||
|
||||
{
|
||||
int r = 0;
|
||||
if (pid == 0 || pid == -1)
|
||||
r = sigsend_pgrp_user(myproc()->pgid, sig);
|
||||
else if (pid < -1)
|
||||
r = sigsend_pgrp_user(-pid, sig);
|
||||
else
|
||||
goto single;
|
||||
return r == -2 ? -EPERM : r < 0 ? -ESRCH : 0;
|
||||
}
|
||||
single:
|
||||
// sig == 0: existence check only
|
||||
if (sig == 0)
|
||||
return proc_exists(pid) ? 0 : -ESRCH;
|
||||
|
||||
// Raise the signal for real: pending bit + wakeup, handler delivery on
|
||||
// the target's next syscall boundary, default action if unhandled.
|
||||
return sigsend(pid, sig) < 0 ? -ESRCH : 0;
|
||||
{
|
||||
int r = sigsend_user(pid, sig);
|
||||
return r == -2 ? -EPERM : r < 0 ? -ESRCH : 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Defined with getrusage() further down; wait4() needs it too.
|
||||
|
|
@ -208,6 +217,8 @@ sys_uptime(void)
|
|||
|
||||
addr_t sys_reboot(void)
|
||||
{
|
||||
if (!capable())
|
||||
return -EPERM;
|
||||
cprintf("System is rebooting...\n");
|
||||
// A stick left mounted should come back readable, and marked clean.
|
||||
schfs_ksync_all();
|
||||
|
|
@ -223,6 +234,8 @@ addr_t sys_reboot(void)
|
|||
|
||||
addr_t sys_shutdown(void)
|
||||
{
|
||||
if (!capable())
|
||||
return -EPERM;
|
||||
cprintf("System is shutting down...\n");
|
||||
// S5, through the firmware's own PM1 registers and its _PTS. The port
|
||||
// writes after it are QEMU's, Bochs' and VirtualBox's fixed addresses,
|
||||
|
|
@ -335,12 +348,19 @@ addr_t
|
|||
sys_setreuid(void)
|
||||
{
|
||||
int ruid, euid;
|
||||
struct proc *p = myproc();
|
||||
argint(0, &ruid); argint(1, &euid);
|
||||
if (myproc()->euid != 0)
|
||||
return -EPERM;
|
||||
if (ruid >= 0) myproc()->uid = (uint)ruid;
|
||||
if (euid >= 0) myproc()->euid = (uint)euid;
|
||||
myproc()->suid = myproc()->euid;
|
||||
if (p->euid != 0) {
|
||||
if (ruid >= 0 && (uint)ruid != p->uid && (uint)ruid != p->euid)
|
||||
return -EPERM;
|
||||
if (euid >= 0 && (uint)euid != p->uid && (uint)euid != p->euid &&
|
||||
(uint)euid != p->suid)
|
||||
return -EPERM;
|
||||
}
|
||||
if (ruid >= 0 || (euid >= 0 && (uint)euid != p->uid))
|
||||
p->suid = euid >= 0 ? (uint)euid : p->euid;
|
||||
if (ruid >= 0) p->uid = (uint)ruid;
|
||||
if (euid >= 0) p->euid = (uint)euid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -348,12 +368,19 @@ addr_t
|
|||
sys_setregid(void)
|
||||
{
|
||||
int rgid, egid;
|
||||
struct proc *p = myproc();
|
||||
argint(0, &rgid); argint(1, &egid);
|
||||
if (myproc()->euid != 0)
|
||||
return -EPERM;
|
||||
if (rgid >= 0) myproc()->gid = (uint)rgid;
|
||||
if (egid >= 0) myproc()->egid = (uint)egid;
|
||||
myproc()->sgid = myproc()->egid;
|
||||
if (p->euid != 0) {
|
||||
if (rgid >= 0 && (uint)rgid != p->gid && (uint)rgid != p->egid)
|
||||
return -EPERM;
|
||||
if (egid >= 0 && (uint)egid != p->gid && (uint)egid != p->egid &&
|
||||
(uint)egid != p->sgid)
|
||||
return -EPERM;
|
||||
}
|
||||
if (rgid >= 0 || (egid >= 0 && (uint)egid != p->gid))
|
||||
p->sgid = egid >= 0 ? (uint)egid : p->egid;
|
||||
if (rgid >= 0) p->gid = (uint)rgid;
|
||||
if (egid >= 0) p->egid = (uint)egid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -361,12 +388,19 @@ addr_t
|
|||
sys_setresuid(void)
|
||||
{
|
||||
int r, e, sv;
|
||||
struct proc *p = myproc();
|
||||
argint(0, &r); argint(1, &e); argint(2, &sv);
|
||||
if (myproc()->euid != 0)
|
||||
return -EPERM;
|
||||
if (r >= 0) myproc()->uid = (uint)r;
|
||||
if (e >= 0) myproc()->euid = (uint)e;
|
||||
if (sv >= 0) myproc()->suid = (uint)sv;
|
||||
// Unprivileged, each id may be set only to one the process already has.
|
||||
if (p->euid != 0) {
|
||||
int ids[3] = { r, e, sv };
|
||||
for (int i = 0; i < 3; i++)
|
||||
if (ids[i] >= 0 && (uint)ids[i] != p->uid &&
|
||||
(uint)ids[i] != p->euid && (uint)ids[i] != p->suid)
|
||||
return -EPERM;
|
||||
}
|
||||
if (r >= 0) p->uid = (uint)r;
|
||||
if (e >= 0) p->euid = (uint)e;
|
||||
if (sv >= 0) p->suid = (uint)sv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -374,12 +408,18 @@ addr_t
|
|||
sys_setresgid(void)
|
||||
{
|
||||
int r, e, sv;
|
||||
struct proc *p = myproc();
|
||||
argint(0, &r); argint(1, &e); argint(2, &sv);
|
||||
if (myproc()->euid != 0)
|
||||
return -EPERM;
|
||||
if (r >= 0) myproc()->gid = (uint)r;
|
||||
if (e >= 0) myproc()->egid = (uint)e;
|
||||
if (sv >= 0) myproc()->sgid = (uint)sv;
|
||||
if (p->euid != 0) {
|
||||
int ids[3] = { r, e, sv };
|
||||
for (int i = 0; i < 3; i++)
|
||||
if (ids[i] >= 0 && (uint)ids[i] != p->gid &&
|
||||
(uint)ids[i] != p->egid && (uint)ids[i] != p->sgid)
|
||||
return -EPERM;
|
||||
}
|
||||
if (r >= 0) p->gid = (uint)r;
|
||||
if (e >= 0) p->egid = (uint)e;
|
||||
if (sv >= 0) p->sgid = (uint)sv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -412,10 +452,39 @@ sys_getresgid(void)
|
|||
addr_t sys_getgroups(void)
|
||||
{
|
||||
int size;
|
||||
addr_t list;
|
||||
struct proc *p = myproc();
|
||||
argint(0, &size);
|
||||
return 0; // no supplementary groups
|
||||
argaddr(1, &list);
|
||||
if (size < 0)
|
||||
return -EINVAL;
|
||||
if (size == 0)
|
||||
return p->ngroups; // how many there are
|
||||
if (size < p->ngroups)
|
||||
return -EINVAL;
|
||||
if (p->ngroups && copy_to_user(list, p->groups, p->ngroups * sizeof(uint)) < 0)
|
||||
return -EFAULT;
|
||||
return p->ngroups;
|
||||
}
|
||||
|
||||
addr_t sys_setgroups(void)
|
||||
{
|
||||
int size;
|
||||
addr_t list;
|
||||
uint tmp[NGROUPS_MAX];
|
||||
struct proc *p = myproc();
|
||||
argint(0, &size);
|
||||
argaddr(1, &list);
|
||||
if (p->euid != 0)
|
||||
return -EPERM;
|
||||
if (size < 0 || size > NGROUPS_MAX)
|
||||
return -EINVAL;
|
||||
if (size && copy_from_user(tmp, list, size * sizeof(uint)) < 0)
|
||||
return -EFAULT;
|
||||
p->ngroups = size;
|
||||
memmove(p->groups, tmp, size * sizeof(uint));
|
||||
return 0;
|
||||
}
|
||||
addr_t sys_setgroups(void) { return 0; }
|
||||
|
||||
// --- Process/scheduling extensions ---
|
||||
|
||||
|
|
@ -478,7 +547,10 @@ addr_t sys_tgkill(void)
|
|||
// the calling thread.
|
||||
if (tid <= 0) return -EINVAL;
|
||||
if (sig == 0) return proc_exists(tid) ? 0 : -ESRCH;
|
||||
return sigsend(tid, sig) < 0 ? -ESRCH : 0;
|
||||
{
|
||||
int r = sigsend_user(tid, sig);
|
||||
return r == -2 ? -EPERM : r < 0 ? -ESRCH : 0;
|
||||
}
|
||||
}
|
||||
|
||||
addr_t sys_tkill(void)
|
||||
|
|
@ -487,7 +559,10 @@ addr_t sys_tkill(void)
|
|||
argint(0, &tid); argint(1, &sig);
|
||||
if (tid <= 0) return 0;
|
||||
if (sig == 0) return proc_exists(tid) ? 0 : -ESRCH;
|
||||
return sigsend(tid, sig) < 0 ? -ESRCH : 0;
|
||||
{
|
||||
int r = sigsend_user(tid, sig);
|
||||
return r == -2 ? -EPERM : r < 0 ? -ESRCH : 0;
|
||||
}
|
||||
}
|
||||
|
||||
addr_t sys_pause(void)
|
||||
|
|
|
|||
Loading…
Reference in a new issue