Compare commits

...

4 Commits

Author SHA1 Message Date
66c2896652
su: Use termios ioctls to turn off echoing and read a password
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-09 11:24:34 +02:00
3e5957f9fc
libc: Add ioctl() syscall wrapper 2023-04-09 11:24:13 +02:00
fee33e7a14
kernel: Add ioctls() for termios stuff to ConsoleDevice
Only handles echoing for now.
2023-04-09 11:23:57 +02:00
76eb8cd129
kernel: Add an ioctl() system call 2023-04-09 11:22:57 +02:00
12 changed files with 186 additions and 6 deletions

View File

@ -1,16 +1,63 @@
#include <bits/termios.h>
#include <os/ArgumentParser.h> #include <os/ArgumentParser.h>
#include <pwd.h> #include <pwd.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h> #include <unistd.h>
static struct termios orig;
void restore_terminal()
{
ioctl(fileno(stdin), TCSETS, &orig);
}
char* getpass()
{
fputs("Password: ", stdout);
if (ioctl(fileno(stdin), TCGETS, &orig) < 0)
{
perror("ioctl(TCGETS)");
return nullptr;
}
atexit(restore_terminal);
struct termios tc = orig;
tc.c_lflag &= ~ECHO;
if (ioctl(fileno(stdin), TCSETS, &tc) < 0)
{
perror("ioctl(TCSETS)");
return nullptr;
}
static char buf[1024];
char* rc = fgets(buf, sizeof(buf), stdin);
restore_terminal();
putchar('\n');
if (!rc)
{
perror("fgets");
return nullptr;
}
char* newline = strrchr(rc, '\n');
if (newline) *newline = 0;
return buf;
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
StringView name; StringView name;
if (geteuid() != 0) if (geteuid() != 0)
{ {
fprintf(stderr, "su must be run as root!\n"); fprintf(stderr, "su must be setuid root!\n");
return 1; return 1;
} }
@ -25,12 +72,20 @@ int main(int argc, char** argv)
return 1; return 1;
} }
if (getuid() != geteuid()) if (getuid() != geteuid() && *entry->pw_passwd)
{ {
fprintf(stderr, "FIXME: you have to enter %s's password first!\n", name.chars()); char* pass = getpass();
if (!pass) return 1;
if (strcmp(pass, entry->pw_passwd))
{
fprintf(stderr, "Wrong password!\n");
return 1; return 1;
} }
memset(pass, 0, strlen(pass));
}
setgid(entry->pw_gid); setgid(entry->pw_gid);
setuid(entry->pw_uid); setuid(entry->pw_uid);

View File

@ -27,6 +27,11 @@ namespace VFS
class Inode class Inode
{ {
public: public:
virtual Result<u64> ioctl(int, void*)
{
return err(ENOTTY);
}
// Directory-specific methods // Directory-specific methods
virtual Result<SharedPtr<Inode>> find(const char* name) const = 0; virtual Result<SharedPtr<Inode>> find(const char* name) const = 0;

View File

@ -1,12 +1,15 @@
#include "fs/devices/ConsoleDevice.h" #include "fs/devices/ConsoleDevice.h"
#include "arch/Keyboard.h" #include "arch/Keyboard.h"
#include "memory/MemoryManager.h"
#include "video/TextConsole.h" #include "video/TextConsole.h"
#include <bits/termios.h>
#include <luna/Buffer.h> #include <luna/Buffer.h>
#include <luna/CString.h> #include <luna/CString.h>
#include <luna/Vector.h> #include <luna/Vector.h>
static Buffer g_console_input; static Buffer g_console_input;
static bool g_eof { false }; static bool g_eof { false };
static bool g_echo { true };
Result<SharedPtr<Device>> ConsoleDevice::create() Result<SharedPtr<Device>> ConsoleDevice::create()
{ {
@ -45,7 +48,10 @@ void ConsoleDevice::did_press_key(char key)
{ {
if (key == '\b') if (key == '\b')
{ {
if (g_temp_input.try_pop().has_value()) TextConsole::putwchar(L'\b'); if (g_temp_input.try_pop().has_value())
{
if (g_echo) TextConsole::putwchar(L'\b');
}
return; return;
} }
@ -65,5 +71,32 @@ void ConsoleDevice::did_press_key(char key)
g_temp_input.clear(); g_temp_input.clear();
} }
if (!g_echo) return;
TextConsole::putchar(key); TextConsole::putchar(key);
} }
Result<u64> ConsoleDevice::ioctl(int request, void* arg)
{
switch (request)
{
case TCGETS: {
struct termios tc
{
.c_lflag = 0
};
if (g_echo) tc.c_lflag |= ECHO;
return MemoryManager::copy_to_user_typed((struct termios*)arg, &tc) ? 0 : err(EFAULT);
}
case TCSETS: {
struct termios tc;
if (!MemoryManager::copy_from_user_typed((const struct termios*)arg, &tc)) return err(EFAULT);
if (tc.c_lflag & ECHO) g_echo = true;
else
g_echo = false;
return 0;
}
default: return err(EINVAL);
}
}

View File

@ -15,5 +15,7 @@ class ConsoleDevice : public Device
bool blocking() const override; bool blocking() const override;
Result<u64> ioctl(int request, void* arg) override;
virtual ~ConsoleDevice() = default; virtual ~ConsoleDevice() = default;
}; };

View File

@ -8,6 +8,11 @@ class Device
virtual Result<usize> write(const u8* buf, usize offset, usize length) = 0; virtual Result<usize> write(const u8* buf, usize offset, usize length) = 0;
virtual Result<u64> ioctl(int, void*)
{
return err(ENOTTY);
}
virtual bool blocking() const = 0; virtual bool blocking() const = 0;
virtual ~Device() = default; virtual ~Device() = default;

View File

@ -153,6 +153,11 @@ namespace TmpFS
return err(EINVAL); return err(EINVAL);
} }
Result<u64> ioctl(int request, void* arg) override
{
return m_device->ioctl(request, arg);
}
bool blocking() const override bool blocking() const override
{ {
return m_device->blocking(); return m_device->blocking();

View File

@ -135,3 +135,15 @@ Result<u64> sys_fcntl(Registers*, SyscallArgs args)
default: return err(EINVAL); default: return err(EINVAL);
} }
} }
Result<u64> sys_ioctl(Registers*, SyscallArgs args)
{
int fd = (int)args[0];
int request = (int)args[1];
void* arg = (void*)args[2];
Thread* current = Scheduler::current();
auto& descriptor = *TRY(current->resolve_fd(fd));
return descriptor.inode->ioctl(request, arg);
}

View File

@ -20,6 +20,7 @@ set(SOURCES
src/sys/stat.cpp src/sys/stat.cpp
src/sys/mman.cpp src/sys/mman.cpp
src/sys/wait.cpp src/sys/wait.cpp
src/sys/ioctl.cpp
) )
if(${LUNA_ARCH} STREQUAL "x86_64") if(${LUNA_ARCH} STREQUAL "x86_64")

View File

@ -0,0 +1,21 @@
/* bits/termios.h: Terminal control definitions. */
#ifndef _BITS_TERMIOS_H
#define _BITS_TERMIOS_H
typedef long tcflag_t;
// VERY incomplete termios structure.
struct termios
{
tcflag_t c_lflag;
};
// Values for c_lflag.
#define ECHO 1
// termios ioctl() requests.
#define TCGETS 0
#define TCSETS 1
#endif

18
libc/include/sys/ioctl.h Normal file
View File

@ -0,0 +1,18 @@
/* sys/ioctl.h: IO device control. */
#ifndef _SYS_IOCTL_H
#define _SYS_IOCTL_H
#ifdef __cplusplus
extern "C"
{
#endif
/* Perform an IO control operation on a device. */
int ioctl(int fd, int request, ...);
#ifdef __cplusplus
}
#endif
#endif

22
libc/src/sys/ioctl.cpp Normal file
View File

@ -0,0 +1,22 @@
#include <bits/errno-return.h>
#include <stdarg.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>
#include <unistd.h>
extern "C"
{
int ioctl(int fd, int request, ...)
{
va_list ap;
va_start(ap, request);
void* arg = va_arg(ap, void*);
long rc = syscall(SYS_ioctl, fd, request, arg);
va_end(ap);
__errno_return(rc, int);
}
}

View File

@ -3,7 +3,8 @@
#define enumerate_syscalls(_e) \ #define enumerate_syscalls(_e) \
_e(exit) _e(clock_gettime) _e(mmap) _e(munmap) _e(usleep) _e(open) _e(close) _e(read) _e(getpid) _e(write) \ _e(exit) _e(clock_gettime) _e(mmap) _e(munmap) _e(usleep) _e(open) _e(close) _e(read) _e(getpid) _e(write) \
_e(lseek) _e(mkdir) _e(execve) _e(mknod) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) _e(getdents) _e(getuid) \ _e(lseek) _e(mkdir) _e(execve) _e(mknod) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) _e(getdents) _e(getuid) \
_e(geteuid) _e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(chmod) _e(chown) _e(geteuid) _e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(chmod) _e(chown) \
_e(ioctl)
enum Syscalls enum Syscalls
{ {