Skip to content

Commit

Permalink
kernel: do not rely on struct layout when downcasting
Browse files Browse the repository at this point in the history
  • Loading branch information
mosmeh committed Oct 25, 2024
1 parent 769e4a4 commit 44d842a
Show file tree
Hide file tree
Showing 13 changed files with 96 additions and 64 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export CFLAGS := \
-nostdlib -ffreestanding \
-fno-omit-frame-pointer \
-U_FORTIFY_SOURCE \
-Wall -Wextra -pedantic \
-Wall -Wextra -pedantic -Wno-gnu-statement-expression-from-macro-expansion \
-O2 -g \
$(if $(GIT_HASH),-DYAGURA_VERSION=\"$(GIT_HASH)\") \
$(EXTRA_CFLAGS)
Expand Down
6 changes: 6 additions & 0 deletions common/extra.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
#define SIZEOF_FIELD(t, f) sizeof(((t*)0)->f)
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

#define CONTAINER_OF(ptr, type, member) \
({ \
const __typeof__(((type*)0)->member)* __mptr = (ptr); \
(type*)((char*)__mptr - offsetof(type, member)); \
})

#define ROUND_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1))
#define ROUND_DOWN(x, align) ((x) & ~((align) - 1))
#define DIV_CEIL(lhs, rhs) (((lhs) + (rhs) - 1) / (rhs))
Expand Down
16 changes: 10 additions & 6 deletions kernel/console/tty.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "private.h"
#include <common/extra.h>
#include <common/string.h>
#include <kernel/api/signal.h>
#include <kernel/api/sys/ioctl.h>
Expand All @@ -9,20 +10,23 @@
#include <kernel/safe_string.h>
#include <kernel/task.h>

static struct tty* tty_from_file(struct file* file) {
return CONTAINER_OF(file->inode, struct tty, inode);
}

static bool can_read(struct tty* tty) {
return !ring_buf_is_empty(&tty->input_buf);
}

static bool unblock_read(struct file* file) {
struct tty* tty = (struct tty*)file->inode;
return can_read(tty);
return can_read(tty_from_file(file));
}

static ssize_t tty_pread(struct file* file, void* buf, size_t count,
uint64_t offset) {
(void)offset;

struct tty* tty = (struct tty*)file->inode;
struct tty* tty = tty_from_file(file);

for (;;) {
int rc = file_block(file, unblock_read, 0);
Expand Down Expand Up @@ -81,15 +85,15 @@ static void processed_echo(struct tty* tty, const char* buf, size_t count) {
static ssize_t tty_pwrite(struct file* file, const void* buf, size_t count,
uint64_t offset) {
(void)offset;
struct tty* tty = (struct tty*)file->inode;
struct tty* tty = tty_from_file(file);
spinlock_lock(&tty->lock);
processed_echo(tty, buf, count);
spinlock_unlock(&tty->lock);
return count;
}

static int tty_ioctl(struct file* file, int request, void* user_argp) {
struct tty* tty = (struct tty*)file->inode;
struct tty* tty = tty_from_file(file);
struct termios* termios = &tty->termios;
int ret = 0;
spinlock_lock(&tty->lock);
Expand Down Expand Up @@ -157,9 +161,9 @@ static int tty_ioctl(struct file* file, int request, void* user_argp) {
}

static short tty_poll(struct file* file, short events) {
struct tty* tty = (struct tty*)file->inode;
short revents = 0;
if (events & POLLIN) {
struct tty* tty = tty_from_file(file);
spinlock_lock(&tty->lock);
if (can_read(tty))
revents |= POLLIN;
Expand Down
22 changes: 15 additions & 7 deletions kernel/fs/fifo.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,16 @@ struct fifo {
atomic_size_t num_writers;
};

static struct fifo* fifo_from_inode(struct inode* inode) {
return CONTAINER_OF(inode, struct fifo, inode);
}

static struct fifo* fifo_from_file(struct file* file) {
return fifo_from_inode(file->inode);
}

static void fifo_destroy_inode(struct inode* inode) {
struct fifo* fifo = (struct fifo*)inode;
struct fifo* fifo = fifo_from_inode(inode);
ring_buf_destroy(&fifo->buf);
kfree(fifo);
}
Expand All @@ -36,7 +44,7 @@ static bool unblock_open(struct file* file) {
static int fifo_open(struct file* file, mode_t mode) {
(void)mode;

struct fifo* fifo = (struct fifo*)file->inode;
struct fifo* fifo = fifo_from_file(file);
switch (file->flags & O_ACCMODE) {
case O_RDONLY:
++fifo->num_readers;
Expand All @@ -61,7 +69,7 @@ static int fifo_open(struct file* file, mode_t mode) {
}

static int fifo_close(struct file* file) {
struct fifo* fifo = (struct fifo*)file->inode;
struct fifo* fifo = fifo_from_file(file);
switch (file->flags & O_ACCMODE) {
case O_RDONLY:
--fifo->num_readers;
Expand All @@ -76,15 +84,15 @@ static int fifo_close(struct file* file) {
}

static bool unblock_read(struct file* file) {
const struct fifo* fifo = (const struct fifo*)file->inode;
const struct fifo* fifo = fifo_from_file(file);
return fifo->num_writers == 0 || !ring_buf_is_empty(&fifo->buf);
}

static ssize_t fifo_pread(struct file* file, void* buffer, size_t count,
uint64_t offset) {
(void)offset;

struct fifo* fifo = (struct fifo*)file->inode;
struct fifo* fifo = fifo_from_file(file);
struct ring_buf* buf = &fifo->buf;

for (;;) {
Expand Down Expand Up @@ -115,7 +123,7 @@ static ssize_t fifo_pwrite(struct file* file, const void* buffer, size_t count,
uint64_t offset) {
(void)offset;

struct fifo* fifo = (struct fifo*)file->inode;
struct fifo* fifo = fifo_from_file(file);
struct ring_buf* buf = &fifo->buf;

for (;;) {
Expand Down Expand Up @@ -190,5 +198,5 @@ struct inode* fifo_create(void) {
inode->mode = S_IFIFO;
inode->ref_count = 1;

return (struct inode*)fifo;
return inode;
}
3 changes: 2 additions & 1 deletion kernel/fs/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <kernel/panic.h>
#include <kernel/safe_string.h>
#include <kernel/sched.h>
#include <kernel/socket.h>

void inode_ref(struct inode* inode) {
ASSERT(inode);
Expand All @@ -27,7 +28,7 @@ void inode_destroy(struct inode* inode) {
ASSERT(inode->ref_count == 0 && inode->num_links == 0);
ASSERT(inode->fops->destroy_inode);
inode_unref(inode->fifo);
inode_unref((struct inode*)inode->bound_socket);
inode_unref(&inode->bound_socket->inode);
inode->fops->destroy_inode(inode);
}

Expand Down
20 changes: 12 additions & 8 deletions kernel/fs/proc/pid.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ typedef struct {
pid_t pid;
} proc_pid_item_inode;

static proc_pid_item_inode* item_from_file(struct file* file) {
return CONTAINER_OF(file->inode, proc_pid_item_inode, item_inode.inode);
}

static int populate_cmdline(struct file* file, struct vec* vec) {
proc_pid_item_inode* node = (proc_pid_item_inode*)file->inode;
proc_pid_item_inode* node = item_from_file(file);
struct task* task = task_find_by_tid(node->pid);
if (!task)
return -ENOENT;
Expand Down Expand Up @@ -57,7 +61,7 @@ static int populate_cmdline(struct file* file, struct vec* vec) {
}

static int populate_comm(struct file* file, struct vec* vec) {
proc_pid_item_inode* node = (proc_pid_item_inode*)file->inode;
proc_pid_item_inode* node = item_from_file(file);
struct task* task = task_find_by_tid(node->pid);
if (!task)
return -ENOENT;
Expand All @@ -74,7 +78,7 @@ static int populate_comm(struct file* file, struct vec* vec) {
}

static int populate_cwd(struct file* file, struct vec* vec) {
proc_pid_item_inode* node = (proc_pid_item_inode*)file->inode;
proc_pid_item_inode* node = item_from_file(file);
struct task* task = task_find_by_tid(node->pid);
if (!task)
return -ENOENT;
Expand All @@ -96,7 +100,7 @@ static int populate_cwd(struct file* file, struct vec* vec) {
}

static int populate_environ(struct file* file, struct vec* vec) {
proc_pid_item_inode* node = (proc_pid_item_inode*)file->inode;
proc_pid_item_inode* node = item_from_file(file);
struct task* task = task_find_by_tid(node->pid);
if (!task)
return -ENOENT;
Expand Down Expand Up @@ -130,7 +134,7 @@ static int populate_environ(struct file* file, struct vec* vec) {
}

static int populate_maps(struct file* file, struct vec* vec) {
proc_pid_item_inode* node = (proc_pid_item_inode*)file->inode;
proc_pid_item_inode* node = item_from_file(file);
struct task* task = task_find_by_tid(node->pid);
if (!task)
return -ENOENT;
Expand Down Expand Up @@ -159,7 +163,7 @@ static int add_item(proc_dir_inode* parent, const proc_item_def* item_def,
pid_t pid) {
proc_pid_item_inode* node = kmalloc(sizeof(proc_pid_item_inode));
if (!node) {
inode_unref((struct inode*)parent);
inode_unref(&parent->inode);
return -ENOMEM;
}
*node = (proc_pid_item_inode){0};
Expand All @@ -174,7 +178,7 @@ static int add_item(proc_dir_inode* parent, const proc_item_def* item_def,
inode->ref_count = 1;

int rc = dentry_append(&parent->children, item_def->name, inode);
inode_unref((struct inode*)parent);
inode_unref(&parent->inode);
return rc;
}

Expand Down Expand Up @@ -215,6 +219,6 @@ struct inode* proc_pid_dir_inode_create(proc_dir_inode* parent, pid_t pid) {
return ERR_PTR(rc);
}

inode_unref((struct inode*)parent);
inode_unref(&parent->inode);
return inode;
}
4 changes: 4 additions & 0 deletions kernel/fs/proc/private.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ typedef struct {
struct dentry* children;
} proc_dir_inode;

static inline proc_dir_inode* proc_dir_from_inode(struct inode* inode) {
return CONTAINER_OF(inode, proc_dir_inode, inode);
}

void proc_dir_destroy_inode(struct inode* inode);
struct inode* proc_dir_lookup_child(struct inode* inode, const char* name);
int proc_dir_getdents(struct file*, getdents_callback_fn callback, void* ctx);
Expand Down
8 changes: 4 additions & 4 deletions kernel/fs/proc/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ static int proc_item_open(struct file* file, mode_t mode) {
return -ENOMEM;
*vec = (struct vec){0};

proc_item_inode* node = (proc_item_inode*)file->inode;
proc_item_inode* node = CONTAINER_OF(file->inode, proc_item_inode, inode);
int rc = node->populate(file, vec);
if (IS_ERR(rc)) {
vec_destroy(vec);
Expand Down Expand Up @@ -45,21 +45,21 @@ const struct file_ops proc_item_fops = {
};

void proc_dir_destroy_inode(struct inode* inode) {
proc_dir_inode* node = (proc_dir_inode*)inode;
proc_dir_inode* node = proc_dir_from_inode(inode);
dentry_clear(node->children);
kfree(node);
}

struct inode* proc_dir_lookup_child(struct inode* inode, const char* name) {
proc_dir_inode* node = (proc_dir_inode*)inode;
proc_dir_inode* node = proc_dir_from_inode(inode);
struct inode* child = dentry_find(node->children, name);
inode_unref(inode);
return child;
}

int proc_dir_getdents(struct file* file, getdents_callback_fn callback,
void* ctx) {
proc_dir_inode* node = (proc_dir_inode*)file->inode;
proc_dir_inode* node = proc_dir_from_inode(file->inode);
mutex_lock(&file->offset_lock);
int rc = dentry_getdents(file, node->children, callback, ctx);
mutex_unlock(&file->offset_lock);
Expand Down
9 changes: 5 additions & 4 deletions kernel/fs/proc/root.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,15 +168,16 @@ static proc_item_def root_items[] = {
static struct inode* proc_root_lookup_child(struct inode* inode,
const char* name) {
if (str_is_uint(name)) {
proc_dir_inode* parent = proc_dir_from_inode(inode);
pid_t pid = atoi(name);
return proc_pid_dir_inode_create((proc_dir_inode*)inode, pid);
return proc_pid_dir_inode_create(parent, pid);
}
return proc_dir_lookup_child(inode, name);
}

static int proc_root_getdents(struct file* file, getdents_callback_fn callback,
void* ctx) {
proc_dir_inode* node = (proc_dir_inode*)file->inode;
proc_dir_inode* node = CONTAINER_OF(file->inode, proc_dir_inode, inode);

mutex_lock(&file->offset_lock);
if ((size_t)file->offset < NUM_ITEMS) {
Expand Down Expand Up @@ -218,7 +219,7 @@ static int proc_root_getdents(struct file* file, getdents_callback_fn callback,
static int add_item(proc_dir_inode* parent, const proc_item_def* item_def) {
proc_item_inode* node = kmalloc(sizeof(proc_item_inode));
if (!node) {
inode_unref((struct inode*)parent);
inode_unref(&parent->inode);
return -ENOMEM;
}
*node = (proc_item_inode){0};
Expand All @@ -232,7 +233,7 @@ static int add_item(proc_dir_inode* parent, const proc_item_def* item_def) {
inode->ref_count = 1;

int rc = dentry_append(&parent->children, item_def->name, inode);
inode_unref((struct inode*)parent);
inode_unref(&parent->inode);
return rc;
}

Expand Down
Loading

0 comments on commit 44d842a

Please sign in to comment.