Skip to content
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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 113 additions & 21 deletions syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}


Expand Down Expand Up @@ -173,52 +175,119 @@ int syscalls_release(void *ustack)
}


static int syscalls_sanitizeVector(process_t *proc, char **v)
Copy link
Contributor

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 and vm_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.

{
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wheni = 0 &v[i] == v


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);
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand Down
30 changes: 29 additions & 1 deletion vm/map.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check has one more vulnerability than vm_mapBelongs has. User can also alter the string post NUL byte check. We either have to copy the string or pass the string with length found by this function.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't there be a fast return for str == NULL or at least handle that per-syscall? To avoid arithmetic on NULLs and unnecessary locks.

{
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;
Expand Down
3 changes: 3 additions & 0 deletions vm/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ extern vm_map_t *vm_getSharedMap(int map);
extern int vm_mapBelongs(const struct _process_t *proc, const void *ptr, size_t size);


extern int vm_mapStringBelongs(const struct _process_t *proc, const char *str);


extern int _map_init(vm_map_t *kmap, struct _vm_object_t *kernel, void **start, void **end);


Expand Down
Loading