[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Lost] [Patch] kernel: RPC-Parameter prüfen
Dieser Patch implementiert die Funktion is_userspace(), die bisher mehr
oder weniger ein Stub war, verschiebt sie in die Speicherverwaltung und
wendet sie schließlich zur Prüfung der Syscall-Parameter bei RPCs an. Um
Codeduplikation zu vermeiden, mußte ich resolve_vaddr() ändern, ich
hoffe, ich habe dabei nichts kaputtgemacht.
Index: src/kernel/include/paging.h
===================================================================
--- src/kernel/include/paging.h (Revision 699)
+++ src/kernel/include/paging.h (Arbeitskopie)
@@ -11,6 +11,8 @@
bool map_page(page_directory_t page_directory, vaddr_t vaddr, paddr_t paddr, int flags);
bool unmap_page(page_directory_t page_directory, vaddr_t vaddr);
paddr_t resolve_vaddr(page_directory_t page_directory, vaddr_t vaddr);
+bool is_userspace(vaddr_t start, dword len);
+
vaddr_t find_contiguous_pages(page_directory_t page_directory, int num, dword lower_limit, dword upper_limit);
void increase_user_stack_size(struct task * task_ptr, int pages);
Index: src/kernel/src/syscall.c
===================================================================
--- src/kernel/src/syscall.c (Revision 699)
+++ src/kernel/src/syscall.c (Arbeitskopie)
@@ -67,22 +67,6 @@
dword debug_last_syscall_data[DEBUG_LAST_SYSCALL_DATA_SIZE] = { 0 };
#endif
-/**
- * Prueft, ob ein Speicherbereich komplett gemappt ist und PTE_U gesetzt
- * hat.
- *
- * FIXME Tut sie in dieser Form natuerlich nicht
- */
-bool is_userspace(vaddr_t start, dword len)
-{
- if (start + len < start) {
- return FALSE;
- }
-
- return ((uintptr_t) start >= USER_MEM_START)
- && ((uintptr_t) start + len <= USER_MEM_END);
-}
-
void syscall(struct int_stack_frame ** esp)
{
struct int_stack_frame * isf = *esp;
@@ -677,13 +661,26 @@
{
struct task* callee = get_task(*((dword*) isf->esp));
+ dword metadata_size = *((dword*) (isf->esp + 4));
+ void* metadata = *((void**) (isf->esp + 8));
+ dword data_size = *((dword*) (isf->esp + 12));
+ void* data = *((void**) (isf->esp + 16));
+
+ if (!is_userspace(metadata, metadata_size)) {
+ abort_task("SYSCALL_FASTRPC: Ungueltige Metadaten (%08x)",
+ (dword) metadata);
+ }
+
+ if (!is_userspace(data, data_size)) {
+ abort_task("SYSCALL_FASTRPC: Ungueltige Daten (%08x)",
+ (dword) metadata);
+ }
+
isf->eax = 0;
if (fastrpc(
callee,
- *((dword*) (isf->esp + 4)),
- *((void**) (isf->esp + 8)),
- *((dword*) (isf->esp + 12)),
- *((void**) (isf->esp + 16))
+ metadata_size, metadata,
+ data_size, data
)) {
schedule_to_task(callee, (dword*) esp);
} else {
Index: src/kernel/src/mm/paging.c
===================================================================
--- src/kernel/src/mm/paging.c (Revision 699)
+++ src/kernel/src/mm/paging.c (Arbeitskopie)
@@ -285,18 +285,24 @@
return map_page(page_directory, vaddr, NULL, 0);
}
-
/**
- * Loest eine virtuelle Adresse bezueglich eines Page Directory
- * in eine physische Adresse auf.
+ * Gibt den Pagetable-Eintrag zu einer gegebenen virtuellen Speicheradresse
+ * zurueck.
*
- * @return Physische Adresse oder NULL, wenn die Page nicht vorhanden ist
+ * @param page_directory Page Directory, auf das sich die Adresse bezieht
+ * @param vaddr Aufzuloesende virtuelle Adresse
+ *
+ * @return Pagetable-Eintrag der 4K-Seite, zu der die gegebene virtuelle
+ * Adresse gehoert. 0, wenn die Adresse nicht in einer Seite liegt, die
+ * present ist. Bei 4M-Pages werden die Bits 12 bis 21 mit der passenden
+ * physischen Adresse gefuellt.
*/
-paddr_t resolve_vaddr(page_directory_t page_directory, vaddr_t vaddr)
+static dword get_pagetable_entry
+ (page_directory_t page_directory, vaddr_t vaddr)
{
page_table_t page_table;
paddr_t phys_page_table;
- paddr_t result;
+ dword result;
dword vpage = (dword) vaddr / PAGE_SIZE;
//kprintf("[Resolv: %x in PD %x]", vaddr, page_directory);
@@ -304,30 +310,26 @@
// Passende Page Table suchen
// Bei einer 4M-Page sind wir eigentlich schon am Ziel
if ((page_directory[vpage / PAGE_TABLE_LENGTH] & PTE_P) == 0) {
- return NULL;
+ return 0;
} else if (page_directory[vpage / PAGE_TABLE_LENGTH] & PTE_PS) {
- return (paddr_t) (
- (page_directory[vpage / PAGE_TABLE_LENGTH] & ~0x3FFFFF)
- | ((dword) vaddr & 0x3FFFFF));
+ return (page_directory[vpage / PAGE_TABLE_LENGTH] & ~0x3FF000)
+ | ((dword) vaddr & 0x3FF000);
} else {
- phys_page_table = (page_table_t) (page_directory[vpage / PAGE_TABLE_LENGTH] & ~0xFFF);
+ phys_page_table = (page_table_t)
+ (page_directory[vpage / PAGE_TABLE_LENGTH] & ~0xFFF);
}
- // Die Page-Table-Adresse ist eine physische Adresse. Am sichersten ist es, die
- // Adresse einfach noch einmal zu mappen.
+ // Die Page-Table-Adresse ist eine physische Adresse. Am sichersten ist es,
+ // die Adresse einfach noch einmal zu mappen.
page_table = map_phys_addr(phys_page_table, PAGE_SIZE);
// Adresse zusammenbasteln und fertig
if (page_table[vpage % PAGE_TABLE_LENGTH] & PTE_P) {
-
- result = (paddr_t) (
- (page_table[vpage % PAGE_TABLE_LENGTH] & ~0xFFF)
- | ((dword) vaddr & 0xFFF));
-
+ result = page_table[vpage % PAGE_TABLE_LENGTH];
} else {
- result = NULL;
+ result = 0;
}
// Falls wir die Page Table extra in den Kerneladressraum gemappt haben,
@@ -337,8 +339,48 @@
return result;
}
+/**
+ * Loest eine virtuelle Adresse bezueglich eines Page Directory
+ * in eine physische Adresse auf.
+ *
+ * @return Physische Adresse oder NULL, wenn die Page nicht vorhanden ist
+ */
+paddr_t resolve_vaddr(page_directory_t page_directory, vaddr_t vaddr)
+{
+ dword pte = get_pagetable_entry(page_directory, vaddr);
+ paddr_t result = (paddr_t) ((pte & ~0xFFF) | ((dword) vaddr & 0xFFF));
+ return result;
+}
+
/**
+ * Prueft, ob ein Speicherbereich im Page Directory des aktuellen Tasks
+ * komplett gemappt ist und PTE_U (Zugriffsrecht fuer Usermode) gesetzt hat.
+ */
+bool is_userspace(vaddr_t start, dword len)
+{
+ vaddr_t cur;
+
+ if (start + len < start) {
+ return FALSE;
+ }
+
+ for (cur = start;
+ (cur < start + len) && (cur > (void*) 0xFFF);
+ cur += PAGE_SIZE)
+ {
+ dword pte = get_pagetable_entry(current_task->cr3, cur);
+ if ((pte == 0) || (!pte & PTE_U)) {
+ kprintf("!is_userspace(%08x): %08x", cur, pte);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/**
* Findet einen freien Bereich mit num freien Seiten
*
* @return Die Anfangsadresse der ersten Seite dieses Bereiches