Compare commits

...

3 Commits

Author SHA1 Message Date
3887b98a7d
kernel: Support setuid binaries
All checks were successful
continuous-integration/drone/push Build is passing
You still have to run "chmod 4755 /bin/su" as root inside Luna for now, as this is not done by the install scripts.
2023-04-08 16:32:56 +02:00
8b45766aaa
su: Use user names and read from the password file instead of using raw user IDs 2023-04-08 16:31:33 +02:00
7667f49d62
libc: Add a password file and pwd.h 2023-04-08 16:30:18 +02:00
8 changed files with 185 additions and 9 deletions

View File

@ -1,11 +1,12 @@
#include <os/ArgumentParser.h> #include <os/ArgumentParser.h>
#include <pwd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
StringView id; StringView name;
if (geteuid() != 0) if (geteuid() != 0)
{ {
@ -14,19 +15,24 @@ int main(int argc, char** argv)
} }
os::ArgumentParser parser; os::ArgumentParser parser;
parser.add_positional_argument(id, "id"_sv, true); parser.add_positional_argument(name, "name"_sv, true);
parser.parse(argc, argv); parser.parse(argc, argv);
int uid = atoi(id.chars()); struct passwd* entry = getpwnam(name.chars());
if (!entry)
if (uid == 0)
{ {
fprintf(stderr, "Already root!\n"); fprintf(stderr, "su: user %s not found!\n", name.chars());
return 1; return 1;
} }
setgid(uid); if (getuid() != geteuid())
setuid(uid); {
fprintf(stderr, "FIXME: you have to enter %s's password first!\n", name.chars());
return 1;
}
execl("/bin/sh", "sh", NULL); setgid(entry->pw_gid);
setuid(entry->pw_uid);
execl(entry->pw_shell, entry->pw_shell, NULL);
} }

2
initrd/etc/passwd Normal file
View File

@ -0,0 +1,2 @@
root:toor:0:0:Administrator:/:/bin/sh
selene:moon:1000:1000:User:/home/selene:/bin/sh

View File

@ -86,4 +86,14 @@ namespace VFS
return inode->mode() & S_IROTH; return inode->mode() & S_IROTH;
} }
bool is_setuid(SharedPtr<Inode> inode)
{
return inode->mode() & S_ISUID;
}
bool is_setgid(SharedPtr<Inode> inode)
{
return inode->mode() & S_ISGID;
}
} }

View File

@ -178,6 +178,8 @@ namespace VFS
bool can_execute(SharedPtr<Inode> inode, Credentials auth); bool can_execute(SharedPtr<Inode> inode, Credentials auth);
bool can_read(SharedPtr<Inode> inode, Credentials auth); bool can_read(SharedPtr<Inode> inode, Credentials auth);
bool can_write(SharedPtr<Inode> inode, Credentials auth); bool can_write(SharedPtr<Inode> inode, Credentials auth);
bool is_setuid(SharedPtr<Inode> inode);
bool is_setgid(SharedPtr<Inode> inode);
Inode& root_inode(); Inode& root_inode();
} }

View File

@ -76,6 +76,9 @@ Result<u64> sys_execve(Registers* regs, SyscallArgs args)
MMU::delete_userspace_page_directory(current->directory); MMU::delete_userspace_page_directory(current->directory);
if (VFS::is_setuid(inode)) current->auth.euid = current->auth.suid = inode->uid();
if (VFS::is_setgid(inode)) current->auth.egid = current->auth.sgid = inode->gid();
current->name = path.chars(); current->name = path.chars();
image->apply(current); image->apply(current);

View File

@ -16,6 +16,7 @@ set(SOURCES
src/dirent.cpp src/dirent.cpp
src/setjmp.cpp src/setjmp.cpp
src/env.cpp src/env.cpp
src/pwd.cpp
src/sys/stat.cpp src/sys/stat.cpp
src/sys/mman.cpp src/sys/mman.cpp
src/sys/wait.cpp src/sys/wait.cpp

43
libc/include/pwd.h Normal file
View File

@ -0,0 +1,43 @@
/* pwd.h: Password file parsing. */
#ifndef _PWD_H
#define _PWD_H
#include <sys/types.h>
struct passwd
{
char* pw_name;
char* pw_passwd;
uid_t pw_uid;
gid_t pw_gid;
char* pw_gecos;
char* pw_dir;
char* pw_shell;
};
#ifdef __cplusplus
extern "C"
{
#endif
/* Read the next entry from the password file. */
struct passwd* getpwent(void);
/* Find the entry with a matching username in the password file. */
struct passwd* getpwnam(const char* name);
/* Find the entry with a matching user ID in the password file. */
struct passwd* getpwuid(uid_t uid);
/* Rewind the password file. */
void setpwent(void);
/* End password file parsing. */
void endpwent(void);
#ifdef __cplusplus
}
#endif
#endif

109
libc/src/pwd.cpp Normal file
View File

@ -0,0 +1,109 @@
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static struct passwd pwd;
static FILE* f { nullptr };
static char buf[4096];
extern "C"
{
struct passwd* getpwent()
{
if (!f)
{
f = fopen("/etc/passwd", "r");
if (!f) return nullptr;
}
while (true)
{
char* rc = fgets(buf, sizeof(buf), f);
if (!rc) return nullptr;
char* name = strtok(rc, ":\n");
if (!name) continue;
char* passwd = strtok(nullptr, ":\n");
if (!passwd) continue;
char* uid = strtok(nullptr, ":\n");
if (!uid) continue;
char* gid = strtok(nullptr, ":\n");
if (!gid) continue;
char* gecos = strtok(nullptr, ":\n");
if (!gecos) continue;
char* dir = strtok(nullptr, ":\n");
if (!dir) continue;
char* shell = strtok(nullptr, ":\n");
if (!shell) continue;
pwd.pw_name = name;
pwd.pw_passwd = passwd;
pwd.pw_uid = (uid_t)strtoul(uid, NULL, 10);
pwd.pw_gid = (gid_t)strtoul(gid, NULL, 10);
pwd.pw_gecos = gecos;
pwd.pw_dir = dir;
pwd.pw_shell = shell;
return &pwd;
}
}
struct passwd* getpwnam(const char* name)
{
setpwent();
struct passwd* entry;
while ((entry = getpwent()))
{
if (!strcmp(entry->pw_name, name))
{
endpwent();
return entry;
}
}
endpwent();
return entry;
}
struct passwd* getpwuid(uid_t uid)
{
setpwent();
struct passwd* entry;
while ((entry = getpwent()))
{
if (entry->pw_uid == uid)
{
endpwent();
return entry;
}
}
endpwent();
return entry;
}
void setpwent()
{
if (f) rewind(f);
}
void endpwent()
{
if (f)
{
fclose(f);
f = nullptr;
}
}
}