aboutsummaryrefslogtreecommitdiff
path: root/kernel/features
diff options
context:
space:
mode:
authorMarvin Borner2021-04-09 13:10:03 +0200
committerMarvin Borner2021-04-09 13:10:03 +0200
commiteeb88df1d501ccec4737c18dddb7ca0a1176304f (patch)
treed36b563a27a4a7bdeae662eb5aa44ca082b57e0b /kernel/features
parentf8d841fe268ebba43686729af535e035702438f7 (diff)
Added readable/writable checks
Diffstat (limited to 'kernel/features')
-rw-r--r--kernel/features/fs.c28
-rw-r--r--kernel/features/load.c6
-rw-r--r--kernel/features/mm.c62
3 files changed, 58 insertions, 38 deletions
diff --git a/kernel/features/fs.c b/kernel/features/fs.c
index ded4bf1..76c230e 100644
--- a/kernel/features/fs.c
+++ b/kernel/features/fs.c
@@ -119,10 +119,10 @@ static void vfs_list_mounts()
res vfs_mount(struct device *dev, const char *path)
{
- if (!memory_valid(path))
+ if (!memory_readable(path))
return -EFAULT;
- if (!memory_valid(dev) || !dev->id)
+ if (!memory_readable(dev) || !dev->id)
return -EFAULT;
if (vfs_mounted(dev, path))
@@ -140,10 +140,10 @@ res vfs_mount(struct device *dev, const char *path)
res vfs_read(const char *path, void *buf, u32 offset, u32 count)
{
- if (!memory_valid(path))
+ if (!memory_readable(path))
return -EFAULT;
- if (!memory_valid(buf))
+ if (!memory_writable(buf))
return -EFAULT;
struct mount_info *m = vfs_find_mount_info(path);
@@ -168,10 +168,10 @@ res vfs_read(const char *path, void *buf, u32 offset, u32 count)
res vfs_write(const char *path, void *buf, u32 offset, u32 count)
{
- if (!memory_valid(path))
+ if (!memory_readable(path))
return -EFAULT;
- if (!memory_valid(buf))
+ if (!memory_writable(buf))
return -EFAULT;
struct mount_info *m = vfs_find_mount_info(path);
@@ -196,7 +196,7 @@ res vfs_write(const char *path, void *buf, u32 offset, u32 count)
res vfs_ioctl(const char *path, u32 request, void *arg1, void *arg2, void *arg3)
{
- if (!memory_valid(path))
+ if (!memory_readable(path))
return -EFAULT;
struct mount_info *m = vfs_find_mount_info(path);
@@ -218,10 +218,10 @@ res vfs_ioctl(const char *path, u32 request, void *arg1, void *arg2, void *arg3)
res vfs_stat(const char *path, struct stat *buf)
{
- if (!memory_valid(path))
+ if (!memory_readable(path))
return -EFAULT;
- if (!memory_valid(buf))
+ if (!memory_writable(buf))
return -EFAULT;
struct mount_info *m = vfs_find_mount_info(path);
@@ -243,7 +243,7 @@ res vfs_stat(const char *path, struct stat *buf)
res vfs_block(const char *path, u32 func_ptr)
{
- if (!func_ptr || !memory_valid(path))
+ if (!func_ptr || !memory_readable(path))
return -EFAULT;
struct mount_info *m = vfs_find_mount_info(path);
@@ -267,11 +267,11 @@ res vfs_block(const char *path, u32 func_ptr)
// TODO: Fix page fault when called too often/fast
res vfs_poll(const char **files)
{
- if (!memory_valid(files))
+ if (!memory_readable(files))
return -EFAULT;
stac();
- for (const char **p = files; *p && memory_valid(*p) && **p; p++) {
+ for (const char **p = files; *p && memory_readable(*p) && **p; p++) {
res ready = vfs_ready(*p);
clac();
if (ready == 1)
@@ -281,7 +281,7 @@ res vfs_poll(const char **files)
stac();
}
- for (const char **p = files; *p && memory_valid(*p) && **p; p++) {
+ for (const char **p = files; *p && memory_readable(*p) && **p; p++) {
vfs_block(*p, (u32)vfs_poll);
stac();
}
@@ -292,7 +292,7 @@ res vfs_poll(const char **files)
res vfs_ready(const char *path)
{
- if (!memory_valid(path))
+ if (!memory_readable(path))
return -EFAULT;
struct mount_info *m = vfs_find_mount_info(path);
diff --git a/kernel/features/load.c b/kernel/features/load.c
index 91954b1..df01e04 100644
--- a/kernel/features/load.c
+++ b/kernel/features/load.c
@@ -11,7 +11,7 @@
res elf_load(const char *name, struct proc *proc)
{
- if (!memory_valid(name))
+ if (!memory_readable(name))
return -EFAULT;
stac();
@@ -52,7 +52,7 @@ res elf_load(const char *name, struct proc *proc)
header.version != 1 || header.machine != ELF_MACHINE_386)
return -ENOEXEC;
- if (!memory_valid((void *)header.entry))
+ if (!memory_is_user((void *)header.entry))
return -ENOEXEC;
// ASLR
@@ -77,7 +77,7 @@ res elf_load(const char *name, struct proc *proc)
if (program.vaddr == 0 || program.type != ELF_PROGRAM_TYPE_LOAD)
continue;
- if (!memory_is_user(program.vaddr))
+ if (!memory_is_user((void *)program.vaddr))
return -ENOEXEC;
struct page_dir *prev;
diff --git a/kernel/features/mm.c b/kernel/features/mm.c
index 7baa4ea..466e448 100644
--- a/kernel/features/mm.c
+++ b/kernel/features/mm.c
@@ -199,7 +199,7 @@ void physical_free(struct memory_range range)
#define PDI(vaddr) ((vaddr) >> 22)
#define PTI(vaddr) (((vaddr) >> 12) & 0x03ff)
-u8 virtual_present(struct page_dir *dir, u32 vaddr)
+union page_table_entry *virtual_entry(struct page_dir *dir, u32 vaddr)
{
u32 pdi = PDI(vaddr);
union page_dir_entry *dir_entry = &dir->entries[pdi];
@@ -210,24 +210,35 @@ u8 virtual_present(struct page_dir *dir, u32 vaddr)
u32 pti = PTI(vaddr);
union page_table_entry *table_entry = &table->entries[pti];
+ if (!table_entry->bits.present)
+ return 0;
- return table_entry->bits.present;
+ return table_entry;
}
-u32 virtual_to_physical(struct page_dir *dir, u32 vaddr)
+u8 virtual_present(struct page_dir *dir, u32 vaddr)
{
- u32 pdi = PDI(vaddr);
- union page_dir_entry *dir_entry = &dir->entries[pdi];
- if (!dir_entry->bits.present)
- return 0;
+ union page_table_entry *table_entry = virtual_entry(dir, vaddr);
+ return !!table_entry;
+}
- struct page_table *table = (struct page_table *)(dir_entry->bits.address * PAGE_SIZE);
+u8 virtual_user_readable(struct page_dir *dir, u32 vaddr)
+{
+ union page_table_entry *table_entry = virtual_entry(dir, vaddr);
+ return table_entry && table_entry->bits.user;
+}
- u32 pti = PTI(vaddr);
- union page_table_entry *table_entry = &table->entries[pti];
- if (!table_entry->bits.present)
- return 0;
+u8 virtual_user_writable(struct page_dir *dir, u32 vaddr)
+{
+ union page_table_entry *table_entry = virtual_entry(dir, vaddr);
+ return table_entry && table_entry->bits.user && table_entry->bits.writable;
+}
+u32 virtual_to_physical(struct page_dir *dir, u32 vaddr)
+{
+ union page_table_entry *table_entry = virtual_entry(dir, vaddr);
+ if (!table_entry)
+ return 0;
return (table_entry->bits.address * PAGE_SIZE) + (vaddr & (PAGE_SIZE - 1));
}
@@ -457,7 +468,7 @@ void memory_map_identity(struct page_dir *dir, struct memory_range prange, u32 f
static struct list *memory_objects = NULL;
res memory_sys_alloc(struct page_dir *dir, u32 size, u32 *addr, u32 *id, u8 shared)
{
- if (!memory_valid(addr) || !memory_valid(id))
+ if (!memory_writable(addr) || !memory_writable(id))
return -EFAULT;
size = PAGE_ALIGN_UP(size);
@@ -488,7 +499,7 @@ res memory_sys_alloc(struct page_dir *dir, u32 size, u32 *addr, u32 *id, u8 shar
res memory_sys_free(struct page_dir *dir, u32 addr)
{
- if (!addr || !memory_valid((void *)addr))
+ if (!addr || !memory_readable((void *)addr))
return -EFAULT;
struct list *links = proc_current()->memory;
@@ -516,7 +527,7 @@ res memory_sys_free(struct page_dir *dir, u32 addr)
res memory_sys_shaccess(struct page_dir *dir, u32 id, u32 *addr, u32 *size)
{
- if (!memory_valid(addr) || !memory_valid(size))
+ if (!memory_writable(addr) || !memory_writable(size))
return -EFAULT;
struct node *iterator = memory_objects->head;
@@ -576,16 +587,25 @@ void memory_bypass_disable(void)
memory_bypass_validity = 0;
}
-u8 memory_is_user(u32 addr)
+u8 memory_is_user(const void *addr)
{
- return PDI(addr) >= PAGE_KERNEL_COUNT;
+ return PDI((u32)addr) >= PAGE_KERNEL_COUNT;
}
-// TODO: Limit by proc stack and data range
-u8 memory_valid(const void *addr)
+u8 memory_readable(const void *addr)
{
- if (proc_current() && !memory_bypass_validity)
- return memory_is_user((u32)addr);
+ struct proc *proc = proc_current();
+ if (proc && !memory_bypass_validity)
+ return memory_is_user(addr) && virtual_user_readable(proc->page_dir, (u32)addr);
+ else
+ return 1;
+}
+
+u8 memory_writable(const void *addr)
+{
+ struct proc *proc = proc_current();
+ if (proc && !memory_bypass_validity)
+ return memory_is_user(addr) && virtual_user_writable(proc->page_dir, (u32)addr);
else
return 1;
}