forked from Bananymous/banan-os
Kernel: Add syscalls for set{,e,re}{uid,gid}
This commit is contained in:
parent
99f8133b91
commit
ef4ebaa969
|
@ -21,6 +21,16 @@ namespace Kernel
|
|||
gid_t egid() const { return m_egid; }
|
||||
gid_t sgid() const { return m_sgid; }
|
||||
|
||||
void set_ruid(uid_t uid) { m_ruid = uid; }
|
||||
void set_euid(uid_t uid) { m_euid = uid; }
|
||||
void set_suid(uid_t uid) { m_suid = uid; }
|
||||
|
||||
void set_rgid(gid_t gid) { m_rgid = gid; }
|
||||
void set_egid(gid_t gid) { m_egid = gid; }
|
||||
void set_sgid(gid_t gid) { m_sgid = gid; }
|
||||
|
||||
bool is_superuser() const { return m_euid == 0; }
|
||||
|
||||
private:
|
||||
uid_t m_ruid, m_euid, m_suid;
|
||||
gid_t m_rgid, m_egid, m_sgid;
|
||||
|
|
|
@ -58,6 +58,13 @@ namespace Kernel
|
|||
|
||||
BAN::ErrorOr<void> setenvp(char** envp);
|
||||
|
||||
BAN::ErrorOr<void> set_uid(uid_t);
|
||||
BAN::ErrorOr<void> set_gid(gid_t);
|
||||
BAN::ErrorOr<void> set_euid(uid_t);
|
||||
BAN::ErrorOr<void> set_egid(gid_t);
|
||||
BAN::ErrorOr<void> set_reuid(uid_t, uid_t);
|
||||
BAN::ErrorOr<void> set_regid(gid_t, gid_t);
|
||||
|
||||
BAN::ErrorOr<int> open(BAN::StringView, int);
|
||||
BAN::ErrorOr<int> openat(int, BAN::StringView, int);
|
||||
BAN::ErrorOr<void> close(int fd);
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace Kernel
|
|||
|
||||
bool Inode::can_access(const Credentials& credentials, int flags)
|
||||
{
|
||||
if (credentials.euid() == 0)
|
||||
if (credentials.is_superuser())
|
||||
return true;
|
||||
|
||||
// We treat O_SEARCH as O_RDONLY
|
||||
|
|
|
@ -785,6 +785,187 @@ namespace Kernel
|
|||
strcpy(buffer + 5, m_tty->name().data());
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::set_uid(uid_t uid)
|
||||
{
|
||||
if (uid < 0 || uid >= 1'000'000'000)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
LockGuard _(m_lock);
|
||||
|
||||
// If the process has appropriate privileges, setuid() shall set the real user ID, effective user ID, and the saved
|
||||
// set-user-ID of the calling process to uid.
|
||||
if (m_credentials.is_superuser())
|
||||
{
|
||||
m_credentials.set_euid(uid);
|
||||
m_credentials.set_ruid(uid);
|
||||
m_credentials.set_suid(uid);
|
||||
return {};
|
||||
}
|
||||
|
||||
// If the process does not have appropriate privileges, but uid is equal to the real user ID or the saved set-user-ID,
|
||||
// setuid() shall set the effective user ID to uid; the real user ID and saved set-user-ID shall remain unchanged.
|
||||
if (uid == m_credentials.ruid() || uid == m_credentials.suid())
|
||||
{
|
||||
m_credentials.set_euid(uid);
|
||||
return {};
|
||||
}
|
||||
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::set_gid(gid_t gid)
|
||||
{
|
||||
if (gid < 0 || gid >= 1'000'000'000)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
LockGuard _(m_lock);
|
||||
|
||||
// If the process has appropriate privileges, setgid() shall set the real group ID, effective group ID, and the saved
|
||||
// set-group-ID of the calling process to gid.
|
||||
if (m_credentials.is_superuser())
|
||||
{
|
||||
m_credentials.set_egid(gid);
|
||||
m_credentials.set_rgid(gid);
|
||||
m_credentials.set_sgid(gid);
|
||||
return {};
|
||||
}
|
||||
|
||||
// If the process does not have appropriate privileges, but gid is equal to the real group ID or the saved set-group-ID,
|
||||
// setgid() shall set the effective group ID to gid; the real group ID and saved set-group-ID shall remain unchanged.
|
||||
if (gid == m_credentials.rgid() || gid == m_credentials.sgid())
|
||||
{
|
||||
m_credentials.set_egid(gid);
|
||||
return {};
|
||||
}
|
||||
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::set_euid(uid_t uid)
|
||||
{
|
||||
if (uid < 0 || uid >= 1'000'000'000)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
LockGuard _(m_lock);
|
||||
|
||||
// If uid is equal to the real user ID or the saved set-user-ID, or if the process has appropriate privileges, seteuid()
|
||||
// shall set the effective user ID of the calling process to uid; the real user ID and saved set-user-ID shall remain unchanged.
|
||||
if (uid == m_credentials.ruid() || uid == m_credentials.suid() || m_credentials.is_superuser())
|
||||
{
|
||||
m_credentials.set_euid(uid);
|
||||
return {};
|
||||
}
|
||||
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::set_egid(gid_t gid)
|
||||
{
|
||||
if (gid < 0 || gid >= 1'000'000'000)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
LockGuard _(m_lock);
|
||||
|
||||
// If gid is equal to the real group ID or the saved set-group-ID, or if the process has appropriate privileges, setegid()
|
||||
// shall set the effective group ID of the calling process to gid; the real group ID, saved set-group-ID, and any
|
||||
// supplementary group IDs shall remain unchanged.
|
||||
if (gid == m_credentials.rgid() || gid == m_credentials.sgid() || m_credentials.is_superuser())
|
||||
{
|
||||
m_credentials.set_egid(gid);
|
||||
return {};
|
||||
}
|
||||
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::set_reuid(uid_t ruid, uid_t euid)
|
||||
{
|
||||
if (ruid == -1 && euid == -1)
|
||||
return {};
|
||||
|
||||
if (ruid < -1 || ruid >= 1'000'000'000)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
if (euid < -1 || euid >= 1'000'000'000)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
// The setreuid() function shall set the real and effective user IDs of the current process to the values specified
|
||||
// by the ruid and euid arguments. If ruid or euid is -1, the corresponding effective or real user ID of the current
|
||||
// process shall be left unchanged.
|
||||
|
||||
LockGuard _(m_lock);
|
||||
|
||||
// A process with appropriate privileges can set either ID to any value.
|
||||
if (!m_credentials.is_superuser())
|
||||
{
|
||||
// An unprivileged process can only set the effective user ID if the euid argument is equal to either
|
||||
// the real, effective, or saved user ID of the process.
|
||||
if (euid != -1 && euid != m_credentials.ruid() && euid != m_credentials.euid() && euid == m_credentials.suid())
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
|
||||
// It is unspecified whether a process without appropriate privileges is permitted to change the real user ID to match the
|
||||
// current effective user ID or saved set-user-ID of the process.
|
||||
// NOTE: we will allow this
|
||||
if (ruid != -1 && ruid != m_credentials.ruid() && ruid != m_credentials.euid() && ruid == m_credentials.suid())
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
}
|
||||
|
||||
// If the real user ID is being set (ruid is not -1), or the effective user ID is being set to a value not equal to the
|
||||
// real user ID, then the saved set-user-ID of the current process shall be set equal to the new effective user ID.
|
||||
if (ruid != -1 || euid != m_credentials.ruid())
|
||||
m_credentials.set_suid(euid);
|
||||
|
||||
if (ruid != -1)
|
||||
m_credentials.set_ruid(ruid);
|
||||
if (euid != -1)
|
||||
m_credentials.set_euid(euid);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<void> Process::set_regid(gid_t rgid, gid_t egid)
|
||||
{
|
||||
if (rgid == -1 && egid == -1)
|
||||
return {};
|
||||
|
||||
if (rgid < -1 || rgid >= 1'000'000'000)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
if (egid < -1 || egid >= 1'000'000'000)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
// The setregid() function shall set the real and effective group IDs of the calling process.
|
||||
|
||||
// If rgid is -1, the real group ID shall not be changed; if egid is -1, the effective group ID shall not be changed.
|
||||
|
||||
// The real and effective group IDs may be set to different values in the same call.
|
||||
|
||||
LockGuard _(m_lock);
|
||||
|
||||
// Only a process with appropriate privileges can set the real group ID and the effective group ID to any valid value.
|
||||
if (!m_credentials.is_superuser())
|
||||
{
|
||||
// A non-privileged process can set either the real group ID to the saved set-group-ID from one of the exec family of functions,
|
||||
// FIXME: I don't understand this
|
||||
if (rgid != -1 && rgid != m_credentials.sgid())
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
|
||||
// or the effective group ID to the saved set-group-ID or the real group ID.
|
||||
if (egid != -1 && egid != m_credentials.sgid() && egid != m_credentials.rgid())
|
||||
return BAN::Error::from_errno(EPERM);
|
||||
}
|
||||
|
||||
// If the real group ID is being set (rgid is not -1), or the effective group ID is being set to a value not equal to the
|
||||
// real group ID, then the saved set-group-ID of the current process shall be set equal to the new effective group ID.
|
||||
if (rgid != -1 || egid != m_credentials.rgid())
|
||||
m_credentials.set_sgid(egid);
|
||||
|
||||
if (rgid != -1)
|
||||
m_credentials.set_rgid(rgid);
|
||||
if (egid != -1)
|
||||
m_credentials.set_egid(egid);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
BAN::ErrorOr<BAN::String> Process::absolute_path_of(BAN::StringView path) const
|
||||
{
|
||||
if (path.empty())
|
||||
|
|
|
@ -160,6 +160,54 @@ namespace Kernel
|
|||
return 0;
|
||||
}
|
||||
|
||||
long sys_set_uid(uid_t uid)
|
||||
{
|
||||
auto ret = Process::current().set_uid(uid);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_set_gid(gid_t gid)
|
||||
{
|
||||
auto ret = Process::current().set_gid(gid);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_set_euid(uid_t uid)
|
||||
{
|
||||
auto ret = Process::current().set_euid(uid);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_set_egid(gid_t gid)
|
||||
{
|
||||
auto ret = Process::current().set_egid(gid);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_set_reuid(uid_t ruid, uid_t euid)
|
||||
{
|
||||
auto ret = Process::current().set_reuid(ruid, euid);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
long sys_set_regid(gid_t rgid, gid_t egid)
|
||||
{
|
||||
auto ret = Process::current().set_regid(rgid, egid);
|
||||
if (ret.is_error())
|
||||
return -ret.error().get_error_code();
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" long sys_fork_trampoline();
|
||||
|
||||
extern "C" long cpp_syscall_handler(int syscall, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5)
|
||||
|
@ -237,6 +285,24 @@ namespace Kernel
|
|||
case SYS_READ_DIR_ENTRIES:
|
||||
ret = sys_read_dir_entries((int)arg1, (API::DirectoryEntryList*)arg2, (size_t)arg3);
|
||||
break;
|
||||
case SYS_SET_UID:
|
||||
ret = sys_set_uid((uid_t)arg1);
|
||||
break;
|
||||
case SYS_SET_GID:
|
||||
ret = sys_set_gid((gid_t)arg1);
|
||||
break;
|
||||
case SYS_SET_EUID:
|
||||
ret = sys_set_euid((uid_t)arg1);
|
||||
break;
|
||||
case SYS_SET_EGID:
|
||||
ret = sys_set_egid((gid_t)arg1);
|
||||
break;
|
||||
case SYS_SET_REUID:
|
||||
ret = sys_set_reuid((uid_t)arg1, (uid_t)arg2);
|
||||
break;
|
||||
case SYS_SET_REGID:
|
||||
ret = sys_set_regid((gid_t)arg1, (gid_t)arg2);
|
||||
break;
|
||||
default:
|
||||
dwarnln("Unknown syscall {}", syscall);
|
||||
ret = -ENOSYS;
|
||||
|
|
|
@ -26,6 +26,12 @@ __BEGIN_DECLS
|
|||
#define SYS_FSTAT 19
|
||||
#define SYS_SETENVP 20
|
||||
#define SYS_READ_DIR_ENTRIES 21
|
||||
#define SYS_SET_UID 22
|
||||
#define SYS_SET_GID 23
|
||||
#define SYS_SET_EUID 24
|
||||
#define SYS_SET_EGID 25
|
||||
#define SYS_SET_REUID 26
|
||||
#define SYS_SET_REGID 27
|
||||
|
||||
__END_DECLS
|
||||
|
||||
|
|
|
@ -175,6 +175,44 @@ long syscall(long syscall, ...)
|
|||
ret = Kernel::syscall(SYS_READ_DIR_ENTRIES, fd, (uintptr_t)buffer, buffer_size);
|
||||
break;
|
||||
}
|
||||
case SYS_SET_UID:
|
||||
{
|
||||
uid_t uid = va_arg(args, uid_t);
|
||||
ret = Kernel::syscall(SYS_SET_UID, uid);
|
||||
break;
|
||||
}
|
||||
case SYS_SET_GID:
|
||||
{
|
||||
gid_t gid = va_arg(args, gid_t);
|
||||
ret = Kernel::syscall(SYS_SET_GID, gid);
|
||||
break;
|
||||
}
|
||||
case SYS_SET_EUID:
|
||||
{
|
||||
uid_t uid = va_arg(args, uid_t);
|
||||
ret = Kernel::syscall(SYS_SET_EUID, uid);
|
||||
break;
|
||||
}
|
||||
case SYS_SET_EGID:
|
||||
{
|
||||
gid_t gid = va_arg(args, gid_t);
|
||||
ret = Kernel::syscall(SYS_SET_EGID, gid);
|
||||
break;
|
||||
}
|
||||
case SYS_SET_REUID:
|
||||
{
|
||||
uid_t ruid = va_arg(args, uid_t);
|
||||
uid_t euid = va_arg(args, uid_t);
|
||||
ret = Kernel::syscall(SYS_SET_REUID, ruid, euid);
|
||||
break;
|
||||
}
|
||||
case SYS_SET_REGID:
|
||||
{
|
||||
gid_t rgid = va_arg(args, gid_t);
|
||||
gid_t egid = va_arg(args, gid_t);
|
||||
ret = Kernel::syscall(SYS_SET_REGID, rgid, egid);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
puts("LibC: Unhandeled syscall");
|
||||
ret = -ENOSYS;
|
||||
|
@ -283,3 +321,33 @@ unsigned int sleep(unsigned int seconds)
|
|||
{
|
||||
return syscall(SYS_SLEEP, seconds);
|
||||
}
|
||||
|
||||
int seteuid(uid_t uid)
|
||||
{
|
||||
return syscall(SYS_SET_EUID, uid);
|
||||
}
|
||||
|
||||
int setegid(gid_t gid)
|
||||
{
|
||||
return syscall(SYS_SET_EGID, gid);
|
||||
}
|
||||
|
||||
int setuid(uid_t uid)
|
||||
{
|
||||
return syscall(SYS_SET_UID, uid);
|
||||
}
|
||||
|
||||
int setgid(gid_t gid)
|
||||
{
|
||||
return syscall(SYS_SET_GID, gid);
|
||||
}
|
||||
|
||||
int setreuid(uid_t ruid, uid_t euid)
|
||||
{
|
||||
return syscall(SYS_SET_REUID, ruid, euid);
|
||||
}
|
||||
|
||||
int setregid(gid_t rgid, gid_t egid)
|
||||
{
|
||||
return syscall(SYS_SET_REGID, rgid, egid);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue