Skip to content

Commit

Permalink
copy_data_from_user_space()
Browse files Browse the repository at this point in the history
  • Loading branch information
taikiy committed Dec 30, 2023
1 parent ab34302 commit ff3f410
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 7 deletions.
1 change: 0 additions & 1 deletion src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

#define HEAP_SIZE_BYTES 104857600 // 100MB heap size
#define HEAP_BLOCK_SIZE_BYTES 4096
#define HEAP_TABLE_ADDRESS 0x00007E00 // We need 25,600 bytes for our table to store 100MB heap
#define HEAP_ADDRESS 0x01000000

#define KERNEL_CODE_SELECTOR 0x08
Expand Down
1 change: 1 addition & 0 deletions src/idt/idt.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "config.h"
#include "io/io.h"
#include "memory/memory.h"
#include "memory/paging/paging.h"
#include "system/syscall.h"
#include "task/task.h"
#include "terminal/terminal.h"
Expand Down
99 changes: 94 additions & 5 deletions src/memory/paging/paging.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include "paging.h"
#include "memory/heap/kheap.h"
#include "memory/memory.h"
#include "system/sys.h"
#include "task/task.h"

extern void load_directory(uint32_t* directory);
extern void enable_paging();
Expand Down Expand Up @@ -60,7 +60,7 @@ get_aligned_address(void* address)
/// page table entry flags.
/// @return Status code ALL_OK if success, or <0 if fails.
static status_t
set_page_frame(struct paging_map* map, void* virtual_address, uint32_t table_entry)
set_table_entry(struct paging_map* map, void* virtual_address, uint32_t table_entry)
{
if (!page_is_aligned(virtual_address)) {
return ERROR(EINVARG);
Expand All @@ -81,9 +81,30 @@ set_page_frame(struct paging_map* map, void* virtual_address, uint32_t table_ent
}

static status_t
map_page_frame(struct paging_map* map, uint32_t* physical_address, uint32_t* virtual_address, uint32_t flags)
get_table_entry(struct paging_map* map, void* virtual_address, uint32_t* table_entry_out)
{
return set_page_frame(map, virtual_address, (uint32_t)physical_address | flags);
if (!map || !map->directory || !virtual_address || !table_entry_out) {
return ERROR(EINVARG);
}

uint32_t directory_index = 0;
uint32_t table_index = 0;
status_t result = get_page_indexes(virtual_address, &directory_index, &table_index);
if (result < 0) {
return ERROR(EPAGEFAULT);
}

uint32_t directory_entry = map->directory[directory_index];
uint32_t* table = (uint32_t*)(directory_entry & 0xfffff000);
uint32_t table_entry = table[table_index];

if (!(table_entry & PAGING_IS_PRESENT)) {
return ERROR(EPAGEFAULT);
}

*table_entry_out = table_entry;

return ALL_OK;
}

struct paging_map*
Expand Down Expand Up @@ -171,7 +192,8 @@ map_physical_address_to_pages(
uint32_t total_pages = ((uint32_t)physical_end_address - (uint32_t)physical_start_address) / PAGING_PAGE_SIZE_BYTES;

for (uint32_t i = 0; i < total_pages; i++) {
result = map_page_frame(map, physical_address, virtual_address, flags);
uint32_t table_entry = (uint32_t)physical_address | flags;
result = set_table_entry(map, virtual_address, table_entry);
if (result < 0) {
goto out;
}
Expand Down Expand Up @@ -205,3 +227,70 @@ switch_to_user_page()
struct task* current_task = get_current_task();
switch_page(current_task->user_page);
}

/// @brief Copies the data from the user space to the kernel space.
/// @param task The task that contains the user space paging map.
/// @param src The user space virtual address to copy from.
/// @param dest The kernel space physical address to copy to.
/// @param size The size of the data to copy.
/// @return
status_t
copy_data_from_user_space(struct task* task, void* src, void* dest, size_t size)
{
status_t result = ALL_OK;
const size_t max_page_size_to_copy = PAGING_PAGE_SIZE_BYTES;

if (!task || !task->user_page || !dest || !src) {
return ERROR(EINVARG);
}

// TODO: allow copying more than 4KB
if (size <= 0 || size > max_page_size_to_copy) {
return ERROR(EINVARG);
}

// temporary kernel space memory to copy the data from the user space
char* buf = kzalloc(size);
if (!buf) {
return ERROR(ENOMEM);
}

struct paging_map* user_page = task->user_page;

// get the original table entry at address `buf` and save it for later
uint32_t original_table_entry = 0;
result = get_table_entry(user_page, buf, &original_table_entry);
if (result != ALL_OK) {
goto out;
}

// Map the user space virtual address `buf` (which points to some unknown physical address) to point to the kernel
// space physical address `buf`. We set the flags to be writable, and accessible from everyone so the task can write
// to the kernel space memory.
result = map_physical_address_to_pages(
user_page, buf, buf, max_page_size_to_copy, PAGING_IS_PRESENT | PAGING_IS_WRITABLE | PAGING_ACCESS_FROM_ALL
);
if (result != ALL_OK) {
goto out;
}

// switch to the user space for a brief moment to be able to see the `src` address
switch_to_user_page();
memcpy(buf, src, size);
switch_to_kernel_page();

// restore the original table entry
result = set_table_entry(user_page, buf, original_table_entry);
if (result != ALL_OK) {
goto out;
}

// copy the data from the temporary space to the `dest`
memcpy(dest, buf, size);

out:
if (buf) {
kfree(buf);
}
return result;
}
2 changes: 2 additions & 0 deletions src/memory/paging/paging.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef PAGING_H
#define PAGING_H

#include "task/task.h"
#include <status.h>
#include <stdbool.h>
#include <stddef.h>
Expand All @@ -25,6 +26,7 @@ extern void set_user_segment_registers();

struct paging_map* new_paging_map(uint8_t flags);
status_t free_paging_map(struct paging_map* map);
status_t copy_data_from_user_space(struct task* task, void* src, void* dest, size_t size);
status_t map_physical_address_to_pages(
struct paging_map* map,
void* physical_address,
Expand Down
1 change: 1 addition & 0 deletions src/status.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ typedef void* status_t;
#define EFSNOTSUPPORTED 5
#define EREADONLY 6
#define ETOOMANYPROCESSES 7
#define EPAGEFAULT 8

#define ERROR(v) ((void*)(-v))

Expand Down
1 change: 1 addition & 0 deletions src/task/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "fs/file.h"
#include "memory/heap/kheap.h"
#include "memory/memory.h"
#include "memory/paging/paging.h"
#include "string/string.h"
#include "task.h"

Expand Down
1 change: 0 additions & 1 deletion src/task/task.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#define TASK_H

#include "idt/idt.h"
#include "memory/paging/paging.h"
#include "process.h"
#include <stdint.h>

Expand Down

0 comments on commit ff3f410

Please sign in to comment.