Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

New milestone: fopen/fgets/fclose works

The following code can be runned in the sandbox:

int main(int argc, char *argv[]) {
        char buf[512];
        FILE *f = fopen("/etc/passwd", "r");

        if (!f)
                exit(1);

        printf("==========> file opened!\n");
        while (fgets(buf, sizeof buf, f) != NULL) {
                printf("> %s", buf);
        }
        fclose(f);

        exit(0);
}
  • Loading branch information...
commit dcdd914ed7e937a4722bf20aae561917575d28b8 1 parent f83e741
@nbareil authored
View
6 helper.c
@@ -4,6 +4,7 @@
#include "helper.h"
#include "common.h"
+#include "mm.h"
struct memory_op_msg {
__u32 addr;
@@ -65,6 +66,11 @@ int wait_for_orders(const int fd) {
_exit(ret);
break;
+ case MEMORY_POOL:
+ DEBUGP("big_memory_pool = %#p\n", big_memory_pool);
+ write(fd, &big_memory_pool, sizeof big_memory_pool);
+ break;
+
default:
ERROR("Unknown message type %x\n", msgtype);
break;
View
2  helper.h
@@ -5,7 +5,7 @@ enum {
POKE_MEMORY,
RETVAL,
NATIVE_EXIT,
- GET_MEM_POOL,
+ MEMORY_POOL,
};
static int controlfd = -1;
View
6 jail.c
@@ -149,14 +149,14 @@ void link_sockets(const char *dir, int last, unsigned int n) {
ok = 0;
if (connect(s, (struct sockaddr *) &uaddr, sizeof(uaddr))) {
- if (errno == ENOENT || errno == ECONNREFUSED)
+ if (errno == ENOENT || errno == ECONNREFUSED) {
+ sleep(0.1);
continue;
- else
+ } else
PERROR("connect()");
}
ok = 1;
- sleep(0.1);
} while (!ok);
}
}
View
17 mm.c
@@ -1,19 +1,36 @@
+#include <sys/mman.h>
+
#include "mm.h"
+#include "common.h"
+#include "helper.h"
mspace mm = NULL;
+void *big_memory_pool;
void init_memory(size_t mem)
{
+
+
mm = create_mspace(mem, 0);
+ big_memory_pool = mmap(NULL,
+ 0xf000,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
+ -1, 0);
+
+ if (!big_memory_pool)
+ _exit(1);
}
static void * my_malloc_hook(size_t size, const void *caller)
{
+ DEBUGP("malloc(%d)", size);
return mspace_malloc(mm, size);
}
static void * my_free_hook(void *ptr, const void *caller)
{
+ DEBUGP("free()");
mspace_free(mm, ptr);
return NULL;
}
View
9 mm.h
@@ -1,5 +1,4 @@
#ifndef __MM_H
-
#define __MM_H
#define MSPACES 1
@@ -9,6 +8,11 @@
#include "dlmalloc.h"
+#include <sys/mman.h>
+#ifndef MAP_HUGETLB
+# define MAP_HUGETLB 0 /* it's only available since 2.6.32 */
+#endif
+
extern void (*__after_morecore_hook)(void);
extern void (*__malloc_initialize_hook) (void);
extern void (*__free_hook)(void *, const void *);
@@ -27,4 +31,7 @@ static void my_malloc_init(void);
#define XCHANGE_VALUE(a, b) do { typeof(a) c = a; a = b; b = c; } while (0);
+extern mspace mm;
+extern void *big_memory_pool;
+
#endif
View
119 trusted.py
@@ -3,11 +3,11 @@
import struct, os
import logging
-import vfs
+import vfs, vm
mainlog = logging.getLogger("trusted")
console_handler = logging.StreamHandler()
-console_handler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
+console_handler.setFormatter(logging.Formatter("%(name)15.15s %(levelname)5s: %(message)s"))
mainlog.addHandler(console_handler)
sandboxlog = logging.getLogger("sandbox.action")
tubelog = logging.getLogger("sandbox.tube")
@@ -41,23 +41,30 @@ def __repr__(self):
POKE_MEMORY = 4
RETVAL = 5
NATIVE_EXIT = 6
+GET_MEMORY_POOL = 7
class SandboxedProcess:
def __init__(self, fd=-1):
- self.fd = os.fdopen(fd, 'w+')
+ self.fd = os.fdopen(fd, 'w+')
self.vfs = vfs.VfsManager(root='/', nextfd=fd+1)
+ self.vm = vm.VirtualMemory(0x1000)
def syscall_request(self):
- tubelog.debug('syscall request ringing...')
+ sandboxlog.info('syscall request ringing...')
msg = self.fd.read(7*4)
- tubelog.debug('>>> msg received: %s' % msg.encode('hex'))
mm = Memory.parse(msg)
- tubelog.debug('>>> %s' % mm)
+ sandboxlog.debug('>>> %s' % mm)
if mm.eax == 5:
self.open(mm)
+ elif mm.eax == 6:
+ self.close(mm.ebx)
+ elif mm.eax == 0x5b:
+ self.munmap(mm.ebx, mm.ecx)
elif mm.eax == 0xc5:
self.fstat(mm.ebx, mm.ecx)
+ elif mm.eax == 0xc0:
+ self.mmap(mm.ebx, mm.ecx, mm.edx, mm.esi, mm.edi, mm.ebp)
elif mm.eax == 0xfc:
self.exit(mm.ebx)
@@ -66,33 +73,31 @@ def open(self, reg):
u_perms = reg.ecx
u_mode = reg.edx
filename = self.peek_asciiz(u_ptr)
- sandboxlog.debug('open("%s", %x, %x)' % (filename, u_perms, u_mode))
+ sandboxlog.debug('+++ open("%s", %x, %x)' % (filename, u_perms, u_mode))
(fd, errno) = self.vfs.open(filename, u_perms, u_mode)
if isinstance(fd, file):
ret = fd.fileno()
else:
ret = fd
- sandboxlog.debug('*** fd=%s errno=%x' % (fd, errno))
self.op_retval(ret, errno)
def op_retval(self, ret, errno=0):
- tubelog.debug('<<< op_retval(%d, %d)' % (ret,errno))
- self.write(struct.pack('IiI', RETVAL, ret, errno))
+ tubelog.debug('<<< op_retval(%#x, %d)' % (ret,errno))
+ self.write(struct.pack('III', RETVAL, ret, errno))
def peek_asciiz(self, ptr):
tubelog.debug('<<< peek_asciiz(%#x)' % ptr)
self.write(struct.pack('II', PEEK_ASCIIZ, ptr))
buf = self.fd.read(4)
nbytes = struct.unpack('I', buf)[0]
- tubelog.debug('*** Waiting for %d bytes' % nbytes)
+ tubelog.debug(' Waiting for %d bytes' % nbytes)
buf = self.fd.read(nbytes)
tubelog.debug('>>> ' + buf)
return buf
-
def poke_memory(self, addr, buf):
length = len(buf)
- tubelog.debug('<<< poke_memory(%#x, "%s") len=%d' % (addr, buf.encode('hex'), length))
+ tubelog.debug('<<< poke_memory(%#x, "...") len=%d' % (addr, length))
self.write(struct.pack('III', POKE_MEMORY, addr, length))
self.write(buf)
@@ -110,49 +115,9 @@ def read(self, nbytes):
return self.fd.read(nbytes)
def fstat(self, fd, addr):
+ sandboxlog.info('+++ fstat(%d, %#8x)' % (fd, addr))
## XXX: Check if fd is open
(ret, st, errno) = self.vfs.fstat(fd)
-
- # $ pahole a.out
- # struct stat {
- # __dev_t st_dev; /* 0 8 */
- # short unsigned int __pad1; /* 8 2 */
- #
- # /* XXX 2 bytes hole, try to pack */
- #
- # __ino_t st_ino; /* 12 4 */
- # __mode_t st_mode; /* 16 4 */
- # __nlink_t st_nlink; /* 20 4 */
- # __uid_t st_uid; /* 24 4 */
- # __gid_t st_gid; /* 28 4 */
- # __dev_t st_rdev; /* 32 8 */
- # short unsigned int __pad2; /* 40 2 */
- #
- # /* XXX 2 bytes hole, try to pack */
- #
- # __off_t st_size; /* 44 4 */
- # __blksize_t st_blksize; /* 48 4 */
- # __blkcnt_t st_blocks; /* 52 4 */
- # struct timespec st_atim; /* 56 8 */
- # /* --- cacheline 1 boundary (64 bytes) --- */
- # struct timespec st_mtim; /* 64 8 */
- # struct timespec st_ctim; /* 72 8 */
- # long unsigned int __unused4; /* 80 4 */
- # long unsigned int __unused5; /* 84 4 */
- #
- # /* size: 88, cachelines: 2 */
- # /* sum members: 84, holes: 2, sum holes: 4 */
- # /* last cacheline: 24 bytes */
- # }; /* definitions: 1 */
- #
- # struct timespec {
- # __time_t tv_sec; /* 0 4 */
- # long int tv_nsec; /* 4 4 */
- #
- # /* size: 8, cachelines: 1 */
- # /* last cacheline: 8 bytes */
- # }; /* definitions: 1 */
-
st_buf = struct.pack('Q xxxx IIIIIQ xxxx III QQQ xxxxxxxx',
st.st_dev, st.st_ino, st.st_mode, st.st_nlink, st.st_uid,
st.st_gid, st.st_rdev, st.st_size, st.st_blksize, st.st_blocks,
@@ -161,7 +126,43 @@ def fstat(self, fd, addr):
tubelog.debug('<<< stat buffer')
self.poke_memory(addr, st_buf)
self.op_retval(ret, errno)
-
+
+ def mmap(self, addr, length, prot, flags, fd, offset):
+ fd = ~((fd + 1) & 0xffffffff)
+ sandboxlog.info('+++ mmap(%#x, %#x, %#x, %#x, %#d, %d)' %
+ (addr, length, prot, flags, fd, offset))
+
+ # if not self.security.mmap(addr, length, prot, flags, fd, offset):
+ # raise SecurityViolation("mmap denied")
+
+ ## XXX: Check if fd is owned by the sandbox
+ ## XXX: Offset must be page aligned
+
+ if not self.vm.pool:
+ self.vm.set_pool_addr(self.get_memory_pool())
+ addr = self.vm.new_mapping(addr, length, prot, flags)
+ if fd >= 0:
+ os.lseek(fd, offset, os.SEEK_SET)
+ self.poke_memory(addr, os.read(fd, length))
+ self.op_retval(int(addr & 0xffffffff), 0)
+
+ def munmap(self, addr, length):
+ sandboxlog.info('+++ munmap(%#x, %d)' % (addr, length))
+ self.vm.release_mapping(addr, length)
+ self.op_retval(0, 0)
+
+ def get_memory_pool(self):
+ tubelog.debug('<<< memory_pool_addr')
+ self.write(struct.pack('I', GET_MEMORY_POOL))
+ addr = struct.unpack('I', self.read(4))[0]
+ tubelog.info('>>> memory pool is at %x' % addr)
+ return addr
+
+ def close(self, fd):
+ sandboxlog.info('+++ close(%d)' % fd)
+ (ret, errno) = self.vfs.close(fd)
+ return self.op_retval(ret, errno)
+
class TrustedProcess:
def __init__(self):
self.sandbox = SandboxedProcess(fd=3)
@@ -169,15 +170,15 @@ def __init__(self):
def dispatcher(self, rawtype):
msgtype = struct.unpack('I', rawtype)[0]
- tubelog.debug('dispatching msgtype=%x' % msgtype)
-
if msgtype == DO_SYSCALL:
self.sandbox.syscall_request()
+ elif msgtype == MEMORY_POOL:
+ self.sandbox.set_memory_pool()
+ else:
+ tubelog.error('Unknown message type: %#x' % msgtype)
def run(self):
- tubelog.debug('running')
while True:
- mainlog.debug('select_loop')
if not self.sandbox.vfs.select_loop(self.untrustedfd):
raise Exception('Select_loop failed!')
buf = os.read(self.untrustedfd, 4)
View
3  vfs.py
@@ -97,6 +97,9 @@ def fstat(self, fd):
errno = e.errno
return (ret, st, errno)
+ def close(self, fd):
+ return (0, 0,)
+
if __name__ == "__main__":
import doctest
doctest.testmod()
View
14 vm.py
@@ -0,0 +1,14 @@
+#! /usr/bin/env python
+
+class VirtualMemory:
+ def __init__(self, size):
+ self.pool = None
+
+ def new_mapping(self, addr, length, prot, flags):
+ return self.pool
+
+ def release_mapping(self, addr, length):
+ pass
+
+ def set_pool_addr(self, addr):
+ self.pool = addr
Please sign in to comment.
Something went wrong with that request. Please try again.