Implemented CopyStrIn/Out to fix bugginess of using CopyIn/Out wrapping passed a mapped page.

This commit is contained in:
Ali Mashtizadeh 2015-01-19 17:57:20 -08:00
parent 5ed248c8ec
commit 5808a2564d
6 changed files with 86 additions and 6 deletions

View File

@ -9,6 +9,7 @@
#define ENOMEM 0xBAD5 #define ENOMEM 0xBAD5
#define ENOENT 0xBAD6 #define ENOENT 0xBAD6
#define ENOTDIR 0xBAD7 #define ENOTDIR 0xBAD7
#define ENAMETOOLONG 0xBAD8
#endif /* __ERRNO_H__ */ #endif /* __ERRNO_H__ */

View File

@ -21,3 +21,27 @@ copy_unsafe_fault:
retq retq
FUNC_END(copy_unsafe) FUNC_END(copy_unsafe)
// copystr_unsafe(to, from, len)
FUNC_BEGIN(copystr_unsafe)
movq %rdx, %rcx
1:
decq %rcx
jz copystr_unsafe_toolong
lodsb
stosb
orb %al, %al
jnz 1b
.globl copystr_unsafe_done
copystr_unsafe_done:
xorq %rax, %rax
retq
.globl copystr_unsafe_fault
copystr_unsafe_fault:
movq $EFAULT, %rax
retq
.globl copystr_unsafe_toolong
copystr_unsafe_toolong:
movq $ENAMETOOLONG, %rax
retq
FUNC_END(copystr_unsafe)

View File

@ -115,6 +115,10 @@ extern int copy_unsafe(void *to, void *from, uintptr_t len);
extern void copy_unsafe_done(void); extern void copy_unsafe_done(void);
extern void copy_unsafe_fault(void); extern void copy_unsafe_fault(void);
extern int copystr_unsafe(void *to, void *from, uintptr_t len);
extern void copystr_unsafe_done(void);
extern void copystr_unsafe_fault(void);
void void
trap_entry(TrapFrame *tf) trap_entry(TrapFrame *tf)
{ {
@ -140,6 +144,15 @@ trap_entry(TrapFrame *tf)
return; return;
} }
// User IO
if ((tf->vector == T_PF) &&
(tf->rip >= (uint64_t)&copystr_unsafe) &&
(tf->rip <= (uint64_t)&copystr_unsafe_done)) {
kprintf("Faulted in copystr_unsafe\n");
tf->rip = (uint64_t)&copystr_unsafe_fault;
return;
}
// Halt on kernel errors // Halt on kernel errors
if (tf->vector <= T_CPU_LAST) if (tf->vector <= T_CPU_LAST)
{ {

View File

@ -107,6 +107,8 @@ Handle *Handle_Lookup(Process *proc, uint64_t fd);
// CopyIn/CopyOut Functions // CopyIn/CopyOut Functions
int CopyIn(uintptr_t fromuser, void *tokernel, uintptr_t len); int CopyIn(uintptr_t fromuser, void *tokernel, uintptr_t len);
int CopyOut(void *fromkernel, uintptr_t touser, uintptr_t len); int CopyOut(void *fromkernel, uintptr_t touser, uintptr_t len);
int CopyStrIn(uintptr_t fromuser, void *tokernel, uintptr_t len);
int CopyStrOut(void *fromkernel, uintptr_t touser, uintptr_t len);
#endif /* __SYS_THREAD_H__ */ #endif /* __SYS_THREAD_H__ */

View File

@ -11,6 +11,7 @@
#include <machine/pmap.h> #include <machine/pmap.h>
extern int copy_unsafe(void *to_addr, void *from_addr, uintptr_t len); extern int copy_unsafe(void *to_addr, void *from_addr, uintptr_t len);
extern int copystr_unsafe(void *to_addr, void *from_addr, uintptr_t len);
int int
CopyIn(uintptr_t fromuser, void *tokernel, uintptr_t len) CopyIn(uintptr_t fromuser, void *tokernel, uintptr_t len)
@ -54,3 +55,45 @@ CopyOut(void *fromkernel, uintptr_t touser, uintptr_t len)
return copy_unsafe((void *)touser, fromkernel, len); return copy_unsafe((void *)touser, fromkernel, len);
} }
int
CopyStrIn(uintptr_t fromuser, void *tokernel, uintptr_t len)
{
if (len == 0)
return 0;
// Kernel space
if (fromuser >= MEM_USERSPACE_TOP) {
kprintf("CopyStrIn: address exceeds userspace top\n");
return EFAULT;
}
// Wrap around
if (len > (MEM_USERSPACE_TOP - fromuser)) {
kprintf("CopyStrIn: length exceeds userspace top\n");
return EFAULT;
}
return copystr_unsafe(tokernel, (void *)fromuser, len);
}
int
CopyStrOut(void *fromkernel, uintptr_t touser, uintptr_t len)
{
if (len == 0)
return 0;
// Kernel space
if (touser >= MEM_USERSPACE_TOP) {
kprintf("CopyStrOut: address exceeds userspace top\n");
return EFAULT;
}
// Wrap around
if (len > (MEM_USERSPACE_TOP - touser)) {
kprintf("CopyStrOut: length exceeds userspace top\n");
return EFAULT;
}
return copystr_unsafe((void *)touser, fromkernel, len);
}

View File

@ -55,8 +55,7 @@ Syscall_Spawn(uint64_t user_path)
Process *proc; Process *proc;
Thread *thr; Thread *thr;
// XXX: Use CopyInStr status = CopyStrIn(user_path, &path, sizeof(path));
status = CopyIn(user_path, &path, sizeof(path));
if (status != 0) if (status != 0)
return status; return status;
@ -200,8 +199,7 @@ Syscall_Open(uint64_t user_path, uint64_t flags)
int status; int status;
char path[256]; char path[256];
// XXX: Use CopyInStr status = CopyStrIn(user_path, &path, sizeof(path));
status = CopyIn(user_path, &path, sizeof(path));
if (status != 0) if (status != 0)
return status; return status;
@ -241,8 +239,7 @@ Syscall_Stat(uint64_t user_path, uint64_t user_stat)
char path[256]; char path[256];
struct stat sb; struct stat sb;
// XXX: Use CopyInStr status = CopyStrIn(user_path, &path, sizeof(path));
status = CopyIn(user_path, &path, sizeof(path));
if (status != 0) { if (status != 0) {
return status; return status;
} }