-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
syscalls: Sanitize all pointers #606
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,12 +36,14 @@ | |
|
||
void syscalls_debug(void *ustack) | ||
{ | ||
process_t *proc = proc_current()->process; | ||
const char *s; | ||
|
||
/* FIXME: pass strlen(s) from userspace */ | ||
|
||
GETFROMSTACK(ustack, const char *, s, 0); | ||
hal_consolePrint(ATTR_USER, s); | ||
|
||
if (vm_mapStringBelongs(proc, s) == 0) { | ||
hal_consolePrint(ATTR_USER, s); | ||
} | ||
} | ||
|
||
|
||
|
@@ -173,52 +175,119 @@ int syscalls_release(void *ustack) | |
} | ||
|
||
|
||
static int syscalls_sanitizeVector(process_t *proc, char **v) | ||
{ | ||
size_t i; | ||
|
||
if (v == NULL) { | ||
return 0; | ||
} | ||
|
||
if (vm_mapBelongs(proc, v, sizeof(v)) < 0) { | ||
return -1; | ||
} | ||
|
||
for (i = 0;; ++i) { | ||
if (vm_mapBelongs(proc, &v[i], sizeof(v)) < 0) { | ||
return -1; | ||
} | ||
Comment on lines
+186
to
+193
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When |
||
|
||
if (v[i] == NULL) { | ||
break; | ||
} | ||
|
||
if (vm_mapStringBelongs(proc, v[i]) < 0) { | ||
return -1; | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
|
||
int syscalls_sys_spawn(void *ustack) | ||
{ | ||
process_t *proc = proc_current()->process; | ||
char *path; | ||
char **argv; | ||
char **envp; | ||
|
||
/* FIXME pass fields lengths from userspace */ | ||
|
||
GETFROMSTACK(ustack, char *, path, 0); | ||
GETFROMSTACK(ustack, char **, argv, 1); | ||
GETFROMSTACK(ustack, char **, envp, 2); | ||
|
||
if (vm_mapStringBelongs(proc, path) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
if (syscalls_sanitizeVector(proc, argv) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
if (syscalls_sanitizeVector(proc, envp) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
return proc_fileSpawn(path, argv, envp); | ||
} | ||
|
||
|
||
int syscalls_exec(void *ustack) | ||
{ | ||
process_t *proc = proc_current()->process; | ||
char *path; | ||
char **argv; | ||
char **envp; | ||
|
||
/* FIXME pass fields lengths from userspace */ | ||
|
||
GETFROMSTACK(ustack, char *, path, 0); | ||
GETFROMSTACK(ustack, char **, argv, 1); | ||
GETFROMSTACK(ustack, char **, envp, 2); | ||
|
||
if (vm_mapStringBelongs(proc, path) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
if (syscalls_sanitizeVector(proc, argv) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
if (syscalls_sanitizeVector(proc, envp) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
return proc_execve(path, argv, envp); | ||
} | ||
|
||
|
||
int syscalls_spawnSyspage(void *ustack) | ||
{ | ||
process_t *proc = proc_current()->process; | ||
char *imap; | ||
char *dmap; | ||
char *name; | ||
char **argv; | ||
|
||
/* FIXME pass fields lengths from userspace */ | ||
|
||
GETFROMSTACK(ustack, char *, imap, 0); | ||
GETFROMSTACK(ustack, char *, dmap, 1); | ||
GETFROMSTACK(ustack, char *, name, 2); | ||
GETFROMSTACK(ustack, char **, argv, 3); | ||
|
||
if (vm_mapStringBelongs(proc, imap) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
if (vm_mapStringBelongs(proc, dmap) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
if (vm_mapStringBelongs(proc, name) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
if (syscalls_sanitizeVector(proc, argv) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
return proc_syspageSpawnName(imap, dmap, name, argv); | ||
} | ||
|
||
|
@@ -729,7 +798,9 @@ u32 syscalls_portRegister(void *ustack) | |
GETFROMSTACK(ustack, char *, name, 1); | ||
GETFROMSTACK(ustack, oid_t *, oid, 2); | ||
|
||
/* FIXME: Pass strlen(name) from userspace */ | ||
if (vm_mapStringBelongs(proc, name) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
if (vm_mapBelongs(proc, oid, sizeof(*oid)) < 0) { | ||
return -EFAULT; | ||
|
@@ -828,7 +899,9 @@ int syscalls_lookup(void *ustack) | |
GETFROMSTACK(ustack, oid_t *, file, 1); | ||
GETFROMSTACK(ustack, oid_t *, dev, 2); | ||
|
||
/* FIXME: Pass strlen(name) from userspace */ | ||
if (vm_mapStringBelongs(proc, name) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
if ((file != NULL) && (vm_mapBelongs(proc, file, sizeof(*file)) < 0)) { | ||
return -EFAULT; | ||
|
@@ -1066,14 +1139,17 @@ void syscalls_sigreturn(void *ustack) | |
|
||
int syscalls_sys_open(char *ustack) | ||
{ | ||
process_t *proc = proc_current()->process; | ||
const char *filename; | ||
int oflag; | ||
|
||
/* FIXME: pass strlen(filename) from userspace */ | ||
|
||
GETFROMSTACK(ustack, const char *, filename, 0); | ||
GETFROMSTACK(ustack, int, oflag, 1); | ||
|
||
if (vm_mapStringBelongs(proc, filename) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
return posix_open(filename, oflag, ustack); | ||
} | ||
|
||
|
@@ -1158,26 +1234,36 @@ int syscalls_sys_dup2(char *ustack) | |
|
||
int syscalls_sys_link(char *ustack) | ||
{ | ||
process_t *proc = proc_current()->process; | ||
const char *path1; | ||
const char *path2; | ||
|
||
/* FIXME pass strlen(path1) and strlen(path2) from userspace */ | ||
|
||
GETFROMSTACK(ustack, const char *, path1, 0); | ||
GETFROMSTACK(ustack, const char *, path2, 1); | ||
|
||
if (vm_mapStringBelongs(proc, path1) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
if (vm_mapStringBelongs(proc, path2) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
return posix_link(path1, path2); | ||
} | ||
|
||
|
||
int syscalls_sys_unlink(char *ustack) | ||
{ | ||
process_t *proc = proc_current()->process; | ||
const char *pathname; | ||
|
||
/* FIXME: pass strlen(pathname) from userspace */ | ||
|
||
GETFROMSTACK(ustack, const char *, pathname, 0); | ||
|
||
if (vm_mapStringBelongs(proc, pathname) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
return posix_unlink(pathname); | ||
} | ||
|
||
|
@@ -1242,14 +1328,17 @@ int syscalls_sys_pipe(char *ustack) | |
|
||
int syscalls_sys_mkfifo(char *ustack) | ||
{ | ||
process_t *proc = proc_current()->process; | ||
const char *path; | ||
mode_t mode; | ||
|
||
/* FIXME: pass strlen(path) from userspace */ | ||
|
||
GETFROMSTACK(ustack, const char *, path, 0); | ||
GETFROMSTACK(ustack, mode_t, mode, 1); | ||
|
||
if (vm_mapStringBelongs(proc, path) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
return posix_mkfifo(path, mode); | ||
} | ||
|
||
|
@@ -1283,14 +1372,17 @@ int syscalls_sys_fsync(char *ustack) | |
|
||
int syscalls_sys_chmod(char *ustack) | ||
{ | ||
process_t *proc = proc_current()->process; | ||
const char *path; | ||
mode_t mode; | ||
|
||
/* FIXME: pass strlen(path) from userspace */ | ||
|
||
GETFROMSTACK(ustack, const char *, path, 0); | ||
GETFROMSTACK(ustack, mode_t, mode, 1); | ||
|
||
if (vm_mapStringBelongs(proc, path) < 0) { | ||
return -EFAULT; | ||
} | ||
|
||
return posix_chmod(path, mode); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1105,7 +1105,9 @@ static int _vm_mapBelongs(const struct _process_t *proc, const void *ptr, size_t | |
return 0; | ||
} | ||
|
||
|
||
/* FIXME checked pages should be marked somehow. | ||
* Right now they might be unmapped by some other | ||
* thread in the user process */ | ||
int vm_mapBelongs(const struct _process_t *proc, const void *ptr, size_t size) | ||
{ | ||
int ret; | ||
|
@@ -1120,6 +1122,32 @@ int vm_mapBelongs(const struct _process_t *proc, const void *ptr, size_t size) | |
} | ||
|
||
|
||
int vm_mapStringBelongs(const struct _process_t *proc, const char *str) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This check has one more vulnerability than There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't there be a fast return for |
||
{ | ||
const char *page = (const char *)((ptr_t)str & (SIZE_PAGE - 1)); | ||
size_t offs = str - page; | ||
|
||
proc_lockSet(&proc->mapp->lock); | ||
|
||
while (_vm_mapBelongs(proc, page, SIZE_PAGE) == 0) { | ||
while (offs < SIZE_PAGE) { | ||
if (page[offs] == '\0') { | ||
proc_lockClear(&proc->mapp->lock); | ||
return 0; | ||
} | ||
|
||
++offs; | ||
} | ||
|
||
page += SIZE_PAGE; | ||
offs = 0; | ||
} | ||
proc_lockClear(&proc->mapp->lock); | ||
|
||
return -1; | ||
} | ||
|
||
|
||
void vm_mapinfo(meminfo_t *info) | ||
{ | ||
rbnode_t *n; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On top of vulnerabilities of
vm_mapStringBelongs
andvm_mapStringBelongs
, this function is also vulnerable to user changing the elements of vector. Unfortunatelly, I think that there's no way around copying the vector, but a FIXME note should be sufficient for now.