Fix permission checks in EXT2.
This commit is contained in:
@@ -79,6 +79,8 @@ add_custom_target(filesystem
|
||||
COMMAND echo "---------------------------------------------"
|
||||
COMMAND echo "Creating EXT2 filesystem..."
|
||||
COMMAND echo "---------------------------------------------"
|
||||
COMMAND mkdir -p ${CMAKE_SOURCE_DIR}/files/proc
|
||||
COMMAND mkdir -p ${CMAKE_SOURCE_DIR}/files/dev
|
||||
COMMAND mke2fs -L 'rootfs' -N 0 -d ${CMAKE_SOURCE_DIR}/files -m 5 -r 1 -t ext2 -v -F ${CMAKE_BINARY_DIR}/rootfs.img 32M
|
||||
COMMAND echo "---------------------------------------------"
|
||||
COMMAND echo "Done!"
|
||||
|
||||
@@ -15,6 +15,11 @@ char *strerror(int errnum)
|
||||
case 0:
|
||||
strcpy(error, "Success");
|
||||
break;
|
||||
#ifdef EPERM
|
||||
case EPERM:
|
||||
strcpy(error, "Operation not permitted");
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENOENT
|
||||
case ENOENT:
|
||||
strcpy(error, "No such file or directory");
|
||||
|
||||
+45
-2
@@ -461,6 +461,44 @@ static const char *time_to_string(uint32_t time)
|
||||
return s;
|
||||
}
|
||||
|
||||
/// @brief Checks if the requests in flags are valid.
|
||||
/// @param flags the flags to check.
|
||||
/// @param mask the mask to check against.
|
||||
/// @param uid the uid of the owner.
|
||||
/// @param gid the gid of the owner.
|
||||
/// @return true on success, false otherwise.
|
||||
static bool_t ext2_valid_permissions(int flags, mode_t mask, uid_t uid, gid_t gid)
|
||||
{
|
||||
// Check the permissions.
|
||||
task_struct *task = scheduler_get_current_process();
|
||||
// The current task is the owner.
|
||||
if (task->uid == uid) {
|
||||
if (!bitmask_check(mask, S_IRUSR))
|
||||
return false;
|
||||
if (bitmask_check(flags, O_WRONLY) && !bitmask_check(mask, S_IWUSR))
|
||||
return false;
|
||||
if (bitmask_check(flags, O_RDWR) && (!bitmask_check(mask, S_IRUSR) || !bitmask_check(mask, S_IWUSR)))
|
||||
return false;
|
||||
}
|
||||
if (task->gid == gid) {
|
||||
if (!bitmask_check(mask, S_IRGRP))
|
||||
return false;
|
||||
if (bitmask_check(flags, O_WRONLY) && !bitmask_check(mask, S_IWGRP))
|
||||
return false;
|
||||
if (bitmask_check(flags, O_RDWR) && (!bitmask_check(mask, S_IRGRP) || !bitmask_check(mask, S_IWGRP)))
|
||||
return false;
|
||||
}
|
||||
if ((task->uid != uid) && (task->gid != gid)) {
|
||||
if (!bitmask_check(mask, S_IROTH))
|
||||
return false;
|
||||
if (bitmask_check(flags, O_WRONLY) && !bitmask_check(mask, S_IWOTH))
|
||||
return false;
|
||||
if (bitmask_check(flags, O_RDWR) && (!bitmask_check(mask, S_IROTH) || !bitmask_check(mask, S_IWOTH)))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Dumps on debugging output the superblock.
|
||||
/// @param sb the object to dump.
|
||||
static void ext2_dump_superblock(ext2_superblock_t *sb)
|
||||
@@ -2254,6 +2292,7 @@ static vfs_file_t *ext2_open(const char *path, int flags, mode_t mode)
|
||||
return ext2_creat(path, mode);
|
||||
} else {
|
||||
pr_err("The file does not exist `%s`.\n", absolute_path);
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -2265,6 +2304,12 @@ static vfs_file_t *ext2_open(const char *path, int flags, mode_t mode)
|
||||
pr_err("Failed to read the inode of `%s`.\n", direntry.name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ext2_valid_permissions(flags, inode.mode, inode.uid, inode.gid)) {
|
||||
errno = EACCES;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vfs_file_t *file = ext2_find_vfs_file_with_inode(fs, direntry.inode);
|
||||
if (file == NULL) {
|
||||
// Allocate the memory for the file.
|
||||
@@ -2280,8 +2325,6 @@ static vfs_file_t *ext2_open(const char *path, int flags, mode_t mode)
|
||||
// Add the vfs_file to the list of associated files.
|
||||
list_head_add_tail(&file->siblings, &fs->opened_files);
|
||||
}
|
||||
pr_debug("ext2_open(path: \"%s\", flags: %d, mode: %d) -> file(ino: %d, name: \"%s\")\n",
|
||||
path, flags, mode, file->ino, file->name);
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -143,7 +143,7 @@ vfs_file_t *vfs_open(const char *path, int flags, mode_t mode)
|
||||
// Retrieve the file.
|
||||
vfs_file_t *file = sb_root->fs_operations->open_f(absolute_path, flags, mode);
|
||||
if (file == NULL) {
|
||||
pr_err("vfs_open(%s): Cannot find the given file (%s)!\n", path, strerror(errno));
|
||||
pr_debug("vfs_open(%s): Filesystem open returned NULL file (errno: %d, %s)!\n", path, errno, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
// Increment file reference counter.
|
||||
|
||||
@@ -15,6 +15,11 @@ char *strerror(int errnum)
|
||||
case 0:
|
||||
strcpy(error, "Success");
|
||||
break;
|
||||
#ifdef EPERM
|
||||
case EPERM:
|
||||
strcpy(error, "Operation not permitted");
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENOENT
|
||||
case ENOENT:
|
||||
strcpy(error, "No such file or directory");
|
||||
|
||||
+39
-17
@@ -9,32 +9,54 @@
|
||||
#include <string.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <strerror.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2) {
|
||||
printf("%s: missing operand.\n", argv[0]);
|
||||
printf("Try '%s --help' for more information.\n\n", argv[0]);
|
||||
if (argc < 2) {
|
||||
printf("cat: missing operand.\n");
|
||||
printf("Try 'cat --help' for more information.\n\n");
|
||||
return 1;
|
||||
}
|
||||
if (strcmp(argv[1], "--help") == 0) {
|
||||
printf("Prints the content of the given file.\n");
|
||||
printf("Usage:\n");
|
||||
printf(" %s <file>\n\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
int fd = open(argv[1], O_RDONLY, 42);
|
||||
if (fd < 0) {
|
||||
printf("%s: %s: %s\n\n", argv[0], strerror(errno), argv[1]);
|
||||
return 1;
|
||||
// Check if `--help` is provided.
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (strcmp(argv[i], "--help") == 0) {
|
||||
printf("Prints the content of the given file.\n");
|
||||
printf("Usage:\n");
|
||||
printf(" cat <file>\n\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// Prepare the buffer for reading.
|
||||
char buffer[BUFSIZ];
|
||||
// Put on the standard output the characters.
|
||||
while (read(fd, buffer, BUFSIZ) > 0) {
|
||||
puts(buffer);
|
||||
// Iterate the arguments.
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
int fd = open(argv[i], O_RDONLY, 42);
|
||||
if (fd < 0) {
|
||||
printf("cat: %s: %s\n\n", argv[i], strerror(errno));
|
||||
continue;
|
||||
}
|
||||
stat_t statbuf;
|
||||
if (fstat(fd, &statbuf) == -1) {
|
||||
printf("cat: %s: %s\n\n", argv[i], strerror(errno));
|
||||
// Close the file descriptor.
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
printf("cat: %s: %s\n\n", argv[i], strerror(EISDIR));
|
||||
// Close the file descriptor.
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
// Put on the standard output the characters.
|
||||
while (read(fd, buffer, BUFSIZ) > 0) {
|
||||
puts(buffer);
|
||||
}
|
||||
// Close the file descriptor.
|
||||
close(fd);
|
||||
}
|
||||
putchar('\n');
|
||||
putchar('\n');
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+2
-2
@@ -145,7 +145,7 @@ int main(int argc, char *argv[])
|
||||
no_directory = false;
|
||||
int fd = open(argv[i], O_RDONLY | O_DIRECTORY, 0);
|
||||
if (fd == -1) {
|
||||
printf("%s: cannot access '%s': %s\n\n", argv[0], argv[i], strerror(errno));
|
||||
printf("ls: cannot access '%s': %s\n\n", argv[i], strerror(errno));
|
||||
} else {
|
||||
printf("%s:\n", argv[i]);
|
||||
print_ls(fd, argv[i], flags);
|
||||
@@ -157,7 +157,7 @@ int main(int argc, char *argv[])
|
||||
getcwd(cwd, PATH_MAX);
|
||||
int fd = open(cwd, O_RDONLY | O_DIRECTORY, 0);
|
||||
if (fd == -1) {
|
||||
printf("%s: cannot access '%s': %s\n\n", argv[0], cwd, strerror(errno));
|
||||
printf("ls: cannot access '%s': %s\n\n", cwd, strerror(errno));
|
||||
} else {
|
||||
print_ls(fd, cwd, flags);
|
||||
close(fd);
|
||||
|
||||
Reference in New Issue
Block a user