Compare commits

..

2 Commits

Author SHA1 Message Date
0d54d0ece1
libc: Check for a compatible mode in fdopen()
All checks were successful
continuous-integration/drone/push Build is passing
2023-03-28 20:56:00 +02:00
6239ed83c7
kernel+libc: Add F_GETFD, F_SETFD, F_GETFL and F_SETFL to fcntl 2023-03-28 20:55:38 +02:00
4 changed files with 44 additions and 3 deletions

View File

@ -113,6 +113,25 @@ Result<u64> sys_fcntl(Registers*, SyscallArgs args)
return (u64)new_fd;
}
case F_GETFD: return (u64) !!(descriptor.flags & O_CLOEXEC);
case F_SETFD: {
int arg = (int)args[2];
if (arg == FD_CLOEXEC) descriptor.flags |= O_CLOEXEC;
else
descriptor.flags &= ~O_CLOEXEC;
return 0;
}
case F_GETFL: return (u64)(descriptor.flags & ~O_CLOEXEC);
case F_SETFL: {
int arg = (int)args[2];
descriptor.flags &= ~(O_APPEND | O_NONBLOCK);
arg &= (O_APPEND | O_NONBLOCK);
descriptor.flags |= arg;
return 0;
}
default: return err(EINVAL);
}
}

View File

@ -5,5 +5,11 @@
#define F_DUPFD 0
#define F_DUPFD_CLOEXEC 1
#define F_GETFD 2
#define F_SETFD 3
#define F_SETFL 4
#define F_GETFL 5
#define FD_CLOEXEC 1
#endif

View File

@ -13,4 +13,6 @@
#define O_NONBLOCK 64
#define O_CLOEXEC 128
#define O_ACCMODE O_RDWR
#endif

View File

@ -29,6 +29,22 @@ static int fopen_parse_mode(const char* mode)
return result;
}
static int fdopen_check_compatible_mode(int fd, int new_flags)
{
int old_flags = fcntl(fd, F_GETFL);
if (old_flags < 0) return -1;
int old_mode = old_flags & O_ACCMODE;
int new_mode = new_flags & O_ACCMODE;
if ((old_mode & new_mode) != new_mode)
{
errno = EINVAL;
return -1;
}
return 0;
}
extern "C"
{
FILE* fopen(const char* path, const char* mode)
@ -59,9 +75,7 @@ extern "C"
if ((flags = fopen_parse_mode(mode)) < 0) return nullptr;
// FIXME: We do verify that fd is valid, but not that the mode is compatible.
long rc = lseek(fd, 0, SEEK_CUR);
if (rc < 0) return nullptr;
if (fdopen_check_compatible_mode(fd, flags) < 0) return nullptr;
FILE* f = (FILE*)malloc(sizeof(FILE));
if (!f) { return nullptr; }