From 62e14e75801074b7db2e05667a89ba11038632bb Mon Sep 17 00:00:00 2001 From: apio Date: Fri, 26 May 2023 20:27:47 +0200 Subject: [PATCH] kernel+libos+apps: Support block devices and disallow seeking character devices or pipes --- apps/stat.cpp | 7 ++++++- kernel/src/fs/VFS.cpp | 5 +++++ kernel/src/fs/VFS.h | 7 +++++-- kernel/src/fs/devices/Device.h | 5 +++++ kernel/src/fs/tmpfs/FileSystem.h | 5 +++++ kernel/src/sys/file.cpp | 11 ++++++++--- kernel/src/sys/stat.cpp | 3 ++- libc/include/bits/modes.h | 2 ++ libos/src/Mode.cpp | 1 + 9 files changed, 39 insertions(+), 7 deletions(-) diff --git a/apps/stat.cpp b/apps/stat.cpp index 721c49c5..fdc70ebf 100644 --- a/apps/stat.cpp +++ b/apps/stat.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -10,6 +11,7 @@ static const char* file_type(mode_t mode) case S_IFREG: return "regular file"; case S_IFDIR: return "directory"; case S_IFCHR: return "character special device"; + case S_IFBLK: return "block special device"; case S_IFLNK: return "symbolic link"; case S_IFIFO: return "pipe"; default: return "unknown file type"; @@ -31,10 +33,13 @@ Result luna_main(int argc, char** argv) struct stat st; TRY(os::FileSystem::stat(path, st, follow_symlinks)); + char buf[11]; + os::format_mode(st.st_mode, buf); + printf(" File: %s\n", path.chars()); printf(" Size: %zu (%s)\n", st.st_size, file_type(st.st_mode)); printf("Inode: %lu Links: %lu\n", st.st_ino, st.st_nlink); - printf(" Mode: %#o UID: %u GID: %u\n", st.st_mode & ~S_IFMT, st.st_uid, st.st_gid); + printf(" Mode: (%#o/%s) UID: %u GID: %u\n", st.st_mode & ~S_IFMT, buf, st.st_uid, st.st_gid); return 0; } diff --git a/kernel/src/fs/VFS.cpp b/kernel/src/fs/VFS.cpp index 2ee8225f..6c0aacb9 100644 --- a/kernel/src/fs/VFS.cpp +++ b/kernel/src/fs/VFS.cpp @@ -168,6 +168,11 @@ namespace VFS return inode->mode() & S_ISGID; } + bool is_seekable(SharedPtr inode) + { + return inode->type() != InodeType::FIFO && inode->type() != InodeType::CharacterDevice; + } + Result mount_root(SharedPtr fs) { root_fs = fs; diff --git a/kernel/src/fs/VFS.h b/kernel/src/fs/VFS.h index b6b1851e..6ab313cb 100644 --- a/kernel/src/fs/VFS.h +++ b/kernel/src/fs/VFS.h @@ -13,7 +13,8 @@ namespace VFS { RegularFile, Directory, - Device, + CharacterDevice, + BlockDevice, Symlink, FIFO, }; @@ -261,7 +262,7 @@ namespace VFS InodeType type() const override { - return InodeType::Device; + return InodeType::CharacterDevice; } virtual ~DeviceInode() = default; @@ -285,6 +286,8 @@ namespace VFS bool is_setuid(SharedPtr inode); bool is_setgid(SharedPtr inode); + bool is_seekable(VFS::InodeType type); + Inode& root_inode(); Result mount_root(SharedPtr fs); diff --git a/kernel/src/fs/devices/Device.h b/kernel/src/fs/devices/Device.h index a958e19a..e2bb95db 100644 --- a/kernel/src/fs/devices/Device.h +++ b/kernel/src/fs/devices/Device.h @@ -18,6 +18,11 @@ class Device return 0; } + virtual bool is_block_device() const + { + return false; + } + virtual bool blocking() const = 0; virtual ~Device() = default; diff --git a/kernel/src/fs/tmpfs/FileSystem.h b/kernel/src/fs/tmpfs/FileSystem.h index 579dc282..d082d436 100644 --- a/kernel/src/fs/tmpfs/FileSystem.h +++ b/kernel/src/fs/tmpfs/FileSystem.h @@ -243,6 +243,11 @@ namespace TmpFS public: DeviceInode() = default; + VFS::InodeType type() const override + { + return m_device->is_block_device() ? VFS::InodeType::BlockDevice : VFS::InodeType::CharacterDevice; + } + void set_fs(FileSystem& fs, Badge) { m_fs = &fs; diff --git a/kernel/src/sys/file.cpp b/kernel/src/sys/file.cpp index 20749ead..aa36a940 100644 --- a/kernel/src/sys/file.cpp +++ b/kernel/src/sys/file.cpp @@ -33,7 +33,7 @@ Result sys_read(Registers*, SyscallArgs args) usize nread = TRY(descriptor.inode->read(buf, descriptor.offset, size)); - descriptor.offset += nread; + if (VFS::is_seekable(descriptor.inode->type())) descriptor.offset += nread; return nread; } @@ -52,11 +52,12 @@ Result sys_write(Registers*, SyscallArgs args) if (!descriptor.is_writable()) return err(EBADF); - if (descriptor.should_append()) descriptor.offset = descriptor.inode->size(); + if (descriptor.should_append() && VFS::is_seekable(descriptor.inode->type())) + descriptor.offset = descriptor.inode->size(); usize nwritten = TRY(descriptor.inode->write(buf, descriptor.offset, size)); - descriptor.offset += nwritten; + if (VFS::is_seekable(descriptor.inode->type())) descriptor.offset += nwritten; return nwritten; } @@ -71,6 +72,10 @@ Result sys_lseek(Registers*, SyscallArgs args) auto& descriptor = *TRY(current->resolve_fd(fd)); + if (descriptor.inode->type() == VFS::InodeType::FIFO) return err(ESPIPE); + + if (!VFS::is_seekable(descriptor.inode->type())) return descriptor.offset; + off_t new_offset; switch (whence) diff --git a/kernel/src/sys/stat.cpp b/kernel/src/sys/stat.cpp index f2146828..055a83a2 100644 --- a/kernel/src/sys/stat.cpp +++ b/kernel/src/sys/stat.cpp @@ -13,7 +13,8 @@ static mode_t make_mode(mode_t mode, VFS::InodeType type) { case VFS::InodeType::RegularFile: result |= S_IFREG; break; case VFS::InodeType::Directory: result |= S_IFDIR; break; - case VFS::InodeType::Device: result |= S_IFCHR; break; + case VFS::InodeType::CharacterDevice: result |= S_IFCHR; break; + case VFS::InodeType::BlockDevice: result |= S_IFBLK; break; case VFS::InodeType::Symlink: result |= S_IFLNK; break; case VFS::InodeType::FIFO: result |= S_IFIFO; break; default: break; diff --git a/libc/include/bits/modes.h b/libc/include/bits/modes.h index 8929750d..6f567339 100644 --- a/libc/include/bits/modes.h +++ b/libc/include/bits/modes.h @@ -7,6 +7,7 @@ #define S_IFREG 000000 #define S_IFLNK 010000 #define S_IFIFO 020000 +#define S_IFBLK 030000 #define S_IFDIR 040000 #define S_IFCHR 050000 @@ -15,6 +16,7 @@ #define S_ISREG(mode) __CHECK_TYPE(mode, S_IFREG) #define S_ISDIR(mode) __CHECK_TYPE(mode, S_IFDIR) #define S_ISCHR(mode) __CHECK_TYPE(mode, S_IFCHR) +#define S_ISBLK(mode) __CHECK_TYPE(mode, S_IFBLK) #define S_ISLNK(mode) __CHECK_TYPE(mode, S_IFLNK) #define S_ISFIFO(mode) __CHECK_TYPE(mode, S_IFIFO) diff --git a/libos/src/Mode.cpp b/libos/src/Mode.cpp index 7fc87d06..69e64a4b 100644 --- a/libos/src/Mode.cpp +++ b/libos/src/Mode.cpp @@ -9,6 +9,7 @@ namespace os if (S_ISDIR(mode)) return 'd'; if (S_ISCHR(mode)) return 'c'; + if (S_ISBLK(mode)) return 'b'; if (S_ISLNK(mode)) return 'l'; if (S_ISFIFO(mode)) return 'p';