Browse Source

Bugfixes, upgrade to Linux 3.14

Chia-Che Tsai 9 years ago
parent
commit
7974db7720
40 changed files with 2313 additions and 150 deletions
  1. 14 3
      LibOS/shim/include/shim_internal.h
  2. 1 2
      LibOS/shim/include/shim_types.h
  3. 1 7
      LibOS/shim/src/Makefile
  4. 1 1
      LibOS/shim/src/bookkeep/shim_thread.c
  5. 12 12
      LibOS/shim/src/fs/shim_dcache.c
  6. 36 43
      LibOS/shim/src/fs/shim_namei.c
  7. 4 1
      LibOS/shim/src/sys/shim_clone.c
  8. 6 0
      LibOS/shim/src/sys/shim_stat.c
  9. 2 2
      LibOS/shim/test/apps/Makefile
  10. 1 0
      LibOS/shim/test/apps/python/.gitignore
  11. 16 0
      LibOS/shim/test/apps/python/Makefile
  12. 116 0
      LibOS/shim/test/apps/python/benchrun.py
  13. 54 0
      LibOS/shim/test/apps/python/fibonacci.py
  14. 3 0
      LibOS/shim/test/apps/python/helloworld.py
  15. 28 0
      LibOS/shim/test/apps/python/python.manifest.template
  16. 70 0
      LibOS/shim/test/apps/python/sympybench.py
  17. 11 2
      Pal/Makefile
  18. 23 10
      Pal/ipc/linux/graphene-ipc.c
  19. 1 2
      Pal/lib/Makefile
  20. 0 0
      Pal/linux-3.14.patch
  21. 17 0
      Pal/linux-3.14/graphene/Kconfig
  22. 2 0
      Pal/linux-3.14/graphene/Makefile
  23. 1 0
      Pal/linux-3.14/graphene/graphene-ipc.c
  24. 1 0
      Pal/linux-3.14/graphene/graphene-ipc.h
  25. 1653 0
      Pal/linux-3.14/graphene/graphene.c
  26. 180 0
      Pal/linux-3.14/graphene/graphene.h
  27. 1 0
      Pal/linux-3.14/graphene/my_mmap.h
  28. 1 0
      Pal/linux-3.14/graphene/my_tlb.h
  29. 2 8
      Pal/src/Makefile
  30. 0 2
      Pal/src/db_rtld.c
  31. 2 7
      Pal/src/host/Linux/Makefile
  32. 5 0
      Pal/src/host/Linux/db_main.c
  33. 2 1
      Pal/src/host/Linux/db_process.c
  34. 5 7
      Pal/src/host/Linux/pal-gdb.py
  35. 36 0
      Pal/src/host/Linux/pal.gdb
  36. 1 1
      Pal/src/host/Linux/pal_linux.h
  37. 1 6
      Pal/src/host/Skeleton/Makefile
  38. 0 17
      Pal/src/pal.gdb
  39. 0 13
      Pal/src/pal_debug.h
  40. 3 3
      README

+ 14 - 3
LibOS/shim/include/shim_internal.h

@@ -473,8 +473,7 @@ static inline void enable_preempt (shim_tcb_t * tcb)
 
 #define lock_created(l)  ((l).lock != NULL)
 
-//#define clear_lock(l)  do { (l).lock = NULL; (l).owner = 0; (l).reowned = 0; } while (0)
-#define clear_lock(l)  do { (l).lock = NULL; } while (0)
+#define clear_lock(l)  do { (l).lock = NULL; (l).owner = 0; } while (0)
 
 #define create_lock(l)                          \
     do {                                        \
@@ -511,7 +510,7 @@ static inline void __lock (LOCKTYPE * l)
 #endif
 
     while (!DkObjectsWaitAny(1, &l->lock, NO_TIMEOUT));
-
+    l->owner = tcb->tid;
 #if DEBUG_LOCK == 1
     debug("lock(%s=%p) by %s:%d\n", name, l, file, line);
 #endif
@@ -535,10 +534,22 @@ static inline void __unlock (LOCKTYPE * l)
     debug("unlock(%s=%p) %s:%d\n", name, l, file, line);
 #endif
 
+    l->owner = 0;
     DkSemaphoreRelease(l->lock, 1);
     enable_preempt(tcb);
 }
 
+static inline bool __locked (LOCKTYPE * l)
+{
+    if (!lock_enabled || !l->lock)
+        return false;
+
+    shim_tcb_t * tcb = SHIM_GET_TLS();
+    return tcb->tid == l->owner;
+}
+
+#define locked(l) __locked(&(l))
+
 #define DEBUG_MASTER_LOCK       0
 
 extern LOCKTYPE __master_lock;

+ 1 - 2
LibOS/shim/include/shim_types.h

@@ -288,8 +288,7 @@ typedef struct shim_atomic REFTYPE;
 
 typedef struct shim_lock {
     PAL_HANDLE lock;
-    //IDTYPE owner;
-    //unsigned int reowned;
+    IDTYPE owner;
 } LOCKTYPE;
 
 typedef struct shim_aevent {

+ 1 - 7
LibOS/shim/src/Makefile

@@ -61,7 +61,6 @@ $(graphene_lib):
 libsysdb.so: $(addsuffix .o,$(objs)) $(filter %.map %.lds,$(LDFLAGS)) \
 	     $(graphene_lib) $(pal_lib)
 	@echo [ $@ ]
-	@mv -f $@ $@.backup || true
 	$(LD) $(LDFLAGS) -o $@ $(filter-out %.map %.lds,$^) -soname $@ \
 		-e shim_start
 
@@ -69,7 +68,6 @@ libsysdb_debug.so: $(addsuffix .o,$(objs)) \
 		   $(filter %.map %.lds,$($LDFLAGS-debug)) \
 		   $(graphene_lib) $(pal_lib)
 	@echo [ $@ ]
-	@mv -f $@ $@.backup || true
 	$(LD) $(LDFLAGS-debug) -o $@ $(filter-out %.map %.lds,$^) -soname $@ \
 		-e shim_start
 
@@ -103,8 +101,4 @@ $(addsuffix .o,$(addprefix ipc/shim_ipc_,$(ipcns))): ipc/*.h
 	@$(AS) $(ASFLAGS) $(defs) -E $< -o $@
 
 clean:
-	rm -f $(addsuffix .o,$(objs))
-	for f in $(shim_target); \
-	do \
-		mv -f $$f $$f.backup || true; \
-	done
+	rm -f $(addsuffix .o,$(objs)) $(shim_target)

+ 1 - 1
LibOS/shim/src/bookkeep/shim_thread.c

@@ -754,7 +754,7 @@ MIGRATE_FUNC_BODY(running_thread)
     ADD_FUNC_ENTRY(new_thread);
 
     __libc_tcb_t * tcb = thread->tcb;
-    if (lookup_supervma(tcb, sizeof(__libc_tcb_t), NULL) < 0) {
+    if (tcb && lookup_supervma(tcb, sizeof(__libc_tcb_t), NULL) < 0) {
         ADD_OFFSET(sizeof(__libc_tcb_t));
         ADD_ENTRY(ADDR, base + *offset);
         if (!dry) {

+ 12 - 12
LibOS/shim/src/fs/shim_dcache.c

@@ -156,7 +156,7 @@ void __del_dcache (struct shim_dentry * dent)
 #endif
 }
 
-static int __put_dentry (struct shim_dentry * dent, bool dput);
+static int __internal_put_dentry (struct shim_dentry * dent);
 
 void del_dcache (struct shim_dentry * dent)
 {
@@ -199,13 +199,13 @@ kill:   {
             dent->parent = NULL;
             dent = parent;
 
-            if (__put_dentry(dent, false))
+            if (__internal_put_dentry(dent))
                 break;
         }
     }
 }
 
-static int __put_dentry (struct shim_dentry * dent, bool dput)
+static int __internal_put_dentry (struct shim_dentry * dent)
 {
     int count = REF_DEC(dent->ref_count);
 
@@ -216,11 +216,7 @@ static int __put_dentry (struct shim_dentry * dent, bool dput)
           qstrgetstr(&dent->rel_path), count);
 #endif
 
-    if (count || !dput)
-        return count;
-
-    __dput_dentry(dent);
-    return 0;
+    return count;
 }
 
 void get_dentry (struct shim_dentry * dent)
@@ -239,12 +235,16 @@ void get_dentry (struct shim_dentry * dent)
 
 void put_dentry (struct shim_dentry * dent)
 {
-    if (__put_dentry(dent, false))
+    if (__internal_put_dentry(dent))
         return;
 
-    lock(dcache_lock);
-    __dput_dentry(dent);
-    unlock(dcache_lock);
+    if (locked(dcache_lock)) {
+        __dput_dentry(dent);
+    } else {
+        lock(dcache_lock);
+        __dput_dentry(dent);
+        unlock(dcache_lock);
+    }
 }
 
 struct shim_dentry * get_new_dentry (struct shim_dentry * parent,

+ 36 - 43
LibOS/shim/src/fs/shim_namei.c

@@ -40,7 +40,7 @@
 
 /* check permission of a dentry. If force is not set, permission
    is consider granted on invalid dentries */
-/* have dcache_lock acquired (write) */
+/* have dcache_lock acquired */
 int permission (struct shim_dentry * dent, int mask, bool force)
 {
     mode_t mode = 0;
@@ -107,7 +107,7 @@ static inline int __do_lookup_dentry (struct shim_dentry * dent, bool force)
 }
 
 /* looking up single dentry based on its parent and name */
-/* have dcache_lock acquired (write) */
+/* have dcache_lock acquired */
 int lookup_dentry (struct shim_dentry * parent, const char * name, int namelen,
                    bool force, struct shim_dentry ** new)
 {
@@ -149,7 +149,7 @@ out:
 static void path_reacquire (struct lookup * look, struct shim_dentry * dent);
 
 /* looking up single dentry, but use struct lookup */
-/* have dcache_lock acquired (write) */
+/* have dcache_lock acquired */
 static int do_lookup (struct lookup * look, const char * name, int namelen,
                       bool force)
 {
@@ -170,6 +170,7 @@ fail:
 
 static int link_path_walk (const char * name, struct lookup * look);
 
+/* have dcache_lock acquired */
 void path_acquire (struct lookup * look)
 {
     if (look->dentry)
@@ -179,6 +180,7 @@ void path_acquire (struct lookup * look)
         get_mount(look->mount);
 }
 
+/* have dcache_lock acquired */
 void path_release (struct lookup * look)
 {
     if (look->dentry)
@@ -188,6 +190,7 @@ void path_release (struct lookup * look)
         put_mount(look->mount);
 }
 
+/* have dcache_lock acquired */
 static void path_reacquire (struct lookup * look, struct shim_dentry * dent)
 {
     struct shim_dentry * old_dent = look->dentry;
@@ -209,7 +212,7 @@ static void path_reacquire (struct lookup * look, struct shim_dentry * dent)
 }
 
 /* try follow a link where the dentry points to */
-/* have dcache_lock acquired (write) */
+/* have dcache_lock acquired */
 static inline int __do_follow_link (struct lookup * look)
 {
     int err = 0;
@@ -245,7 +248,7 @@ out:
 }
 
 /* follow links on a dentry until the last target */
-/* have dcache_lock acquired (write) */
+/* have dcache_lock acquired */
 static int follow_link (struct lookup * look)
 {
     int err = 0;
@@ -269,7 +272,7 @@ static int follow_link (struct lookup * look)
 }
 
 /* follow a single dot-dot to the parent */
-/* have dcache_lock acquired (write) */
+/* have dcache_lock acquired */
 static int follow_dotdot (struct lookup * look)
 {
     struct shim_dentry * dent = look->dentry;
@@ -299,7 +302,7 @@ static int follow_dotdot (struct lookup * look)
 
 /* walk through a absolute path based on current lookup structure,
    across mount point, dot dot and symlinks */
-/* have dcache_lock acquired (write) */
+/* have dcache_lock acquired */
 static int link_path_walk (const char * name, struct lookup * look)
 {
     struct shim_dentry * dent = NULL;
@@ -503,7 +506,7 @@ static int path_lookup_dcache (struct shim_dentry * start, const char * path,
     return 0;
 }
 
-/* have dcache_lock acquired (write) */
+/* have dcache_lock acquired */
 static int path_lookup_walk (struct shim_dentry * start,
                              const char * name, int flags,
                              struct lookup * look,
@@ -578,6 +581,7 @@ out_if:
         else
             put_dentry(found);
     }
+
     return 0;
 }
 
@@ -591,44 +595,42 @@ int path_lookupat (struct shim_dentry * start, const char * path, int flags,
     struct lookup look;
 
     lock(dcache_lock);
+
     ret = path_lookup_dcache(start, path, flags, &found, cur_thread);
-    unlock(dcache_lock);
 
-    if (ret < 0)
+    if (ret < 0) {
+        unlock(dcache_lock);
         return ret;
+    }
 
     if (!found) {
-        lock(dcache_lock);
-
         if ((ret = path_lookup_walk(start, path, flags, &look,
                                     cur_thread)) < 0)
-            goto out_if;
+            goto out;
 
         get_dentry(look.dentry);
         found = look.dentry;
 
         if (flags & LOOKUP_SYNC) {
             if ((ret = __do_lookup_dentry(found, true)) < 0)
-                goto out_dentry;
+                goto out_release;
         }
 
         if (found->state & DENTRY_NEGATIVE &&
             !(flags & LOOKUP_CREATE)) {
             ret = -ENOENT;
-            goto out_dentry;
+            goto out_release;
         }
 
         if (!(found->state & DENTRY_NEGATIVE) &&
             !(found->state & DENTRY_ISDIRECTORY) &&
             flags & LOOKUP_DIRECTORY) {
             ret = -ENOTDIR;
-            goto out_dentry;
+            goto out_release;
         }
 
-out_dentry:
+out_release:
         path_release(&look);
-out_if:
-        unlock(dcache_lock);
     }
 
     if (found) {
@@ -637,6 +639,9 @@ out_if:
         else
             put_dentry(found);
     }
+
+out:
+    unlock(dcache_lock);
     return ret;
 }
 
@@ -726,7 +731,6 @@ int open_namei (struct shim_handle * hdl, struct shim_dentry * start,
 #endif
 
     BEGIN_PROFILE_INTERVAL();
-
     lock(dcache_lock);
 
     err = path_lookup_dcache(start, path, lookup_flags|LOOKUP_OPEN,
@@ -738,10 +742,10 @@ int open_namei (struct shim_handle * hdl, struct shim_dentry * start,
             get_mount(look.mount);
     }
 
-    unlock(dcache_lock);
     SAVE_PROFILE_INTERVAL(path_lookup_dcache_for_open_namei);
 
     if (err < 0) {
+        unlock(dcache_lock);
         SAVE_PROFILE_INTERVAL(end_open_namei);
         return err;
     }
@@ -763,31 +767,25 @@ int open_namei (struct shim_handle * hdl, struct shim_dentry * start,
             goto exit;
         }
 
-        goto do_open;
+        goto do_open_locked;
     }
 
-    lock(dcache_lock);
-
     /* no create, just look it up. */
     if (!(flags & O_CREAT)) {
         err = path_lookup_walk(start, path, lookup_flags|LOOKUP_OPEN,
                                &look, cur_thread);
-
-        unlock(dcache_lock);
         SAVE_PROFILE_INTERVAL(path_lookup_walk_for_open_namei);
-
         if (err) {
             debug("path_lookup error in open_namei\n");
-            SAVE_PROFILE_INTERVAL(end_open_namei);
             goto exit;
         }
 
+do_open_locked:
+        unlock(dcache_lock);
 do_open:
         if ((err = permission(look.dentry, acc_mode, true)) < 0)
             goto exit;
-
         SAVE_PROFILE_INTERVAL(open_namei_permission);
-
         if (hdl) {
             if (look.dentry->state & DENTRY_ISDIRECTORY) {
                 assert(flags & O_DIRECTORY);
@@ -811,33 +809,22 @@ do_open:
 
     SAVE_PROFILE_INTERVAL(path_lookup_walk_2_for_open_namei);
 
-    if (err < 0) {
-        unlock(dcache_lock);
-        SAVE_PROFILE_INTERVAL(end_open_namei);
+    if (err < 0 || look.last_type != LAST_NORM)
         goto exit;
-    }
-
-    if (look.last_type != LAST_NORM) {
-        unlock(dcache_lock);
-        goto exit;
-    }
 
     struct shim_dentry * new = NULL;
     dir = look.dentry;
     err = lookup_dentry(dir, look.last, strlen(look.last), true, &new);
-    unlock(dcache_lock);
-
     SAVE_PROFILE_INTERVAL(open_namei_lookup_2);
-
     if (err < 0 && (err != -ENOENT || !new))
         goto exit;
 
     path_reacquire(&look, new);
-
     SAVE_PROFILE_INTERVAL(open_namei_path_reacquire);
 
 do_creat:
     assert(dir);
+    unlock(dcache_lock);
 
     /* negative dentry */
     if (look.dentry->state & DENTRY_NEGATIVE) {
@@ -894,6 +881,9 @@ done:
 
     path_release(&look);
 
+    if (locked(dcache_lock))
+        unlock(dcache_lock);
+
     SAVE_PROFILE_INTERVAL(end_open_namei);
     return 0;
 
@@ -903,6 +893,9 @@ exit:
     if (dir)
         put_dentry(dir);
 
+    if (locked(dcache_lock))
+        unlock(dcache_lock);
+
     SAVE_PROFILE_INTERVAL(end_open_namei);
     return err;
 }

+ 4 - 1
LibOS/shim/src/sys/shim_clone.c

@@ -153,7 +153,10 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr,
                       CLONE_VM|CLONE_FILES|
                       CLONE_FS|CLONE_SIGHAND|CLONE_THREAD|
                       CLONE_DETACHED| // Unused
-                      CLONE_SYSVSEM)) == 0);
+#ifdef CLONE_PTRACE
+                      CLONE_PTRACE| // Unused
+#endif
+                      CLONE_SYSVSEM|CSIGNAL)) == 0);
 
     new_args->create_event = DkNotificationEventCreate(0);
     if (!new_args->create_event) {

+ 6 - 0
LibOS/shim/src/sys/shim_stat.c

@@ -113,6 +113,11 @@ int shim_do_readlink (const char * file, char * buf, int bufsize)
     if (bufsize <= 0)
         return -EINVAL;
 
+    /* The correct behavior is to return -EINVAL if file is not a
+       symbolic link */
+    return -EINVAL;
+
+#if 0
     int ret;
     struct shim_dentry * dent = NULL;
 
@@ -128,4 +133,5 @@ int shim_do_readlink (const char * file, char * buf, int bufsize)
     memcpy(buf, relpath, len);
     put_dentry(dent);
     return len;
+#endif
 }

+ 2 - 2
LibOS/shim/test/apps/Makefile

@@ -1,6 +1,6 @@
 apps = lmbench gcc busybox lighttpd bash apache make
 
-targets = pal build-all
+targets = pal
 clean-extra = clean-all
 
 level = ../
@@ -22,7 +22,7 @@ libpal.so:
 	make pal
 
 build-all:
-	for f in $(apps); do (cd $$f; make $(DEBUG); cd ..); done
+	for f in $(apps); do (cd $$f; make $(DEBUG) || true; cd ..); done
 
 clean-all:
 	for f in $(apps); do (cd $$f; make clean; cd ..); done

+ 1 - 0
LibOS/shim/test/apps/python/.gitignore

@@ -0,0 +1 @@
+*.pyc

+ 16 - 0
LibOS/shim/test/apps/python/Makefile

@@ -0,0 +1,16 @@
+manifests = python.manifest
+
+all debug: $(manifests)
+
+test_targets =  testsamplebash
+
+test: all $(test_targets)
+
+%.manifest: %.manifest.template
+	make -C .. python/$@ appdir=python/
+
+clean: clean-manifests
+distclean: clean-manifests
+
+clean-manifests:
+	rm -rf $(manifests)

+ 116 - 0
LibOS/shim/test/apps/python/benchrun.py

@@ -0,0 +1,116 @@
+"""
+Downloaded from https://code.google.com/p/benchrun/
+
+A benchmark is defined by creating a subclass of Benchmark.
+The subclass should define a method run() that executes the code
+to be timed and returns the elapsed time in seconds (as a float),
+or None if the benchmark should be skipped.
+
+See fibonacci.py for example.
+"""
+
+import sys
+if sys.platform=='win32':
+    from time import clock
+else:
+    from time import time as clock
+
+# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/302478
+def combinations(*seqin):
+    def rloop(seqin,comb):
+        if seqin:
+            for item in seqin[0]:
+                newcomb = comb + [item]
+                for item in rloop(seqin[1:],newcomb):   
+                    yield item
+        else:
+            yield comb
+    return rloop(seqin,[])
+
+
+class Benchmark:
+    sort_by = []
+    reference = None
+
+    def __init__(self):
+        self.pnames = []
+        self.pvalues = []
+        self.results = []
+        self.results_dict = {}
+        for pname in self.parameters:
+            value = getattr(self, pname)
+            self.pnames.append(pname)
+            self.pvalues.append(value)
+        self.pcombos = list(combinations(*self.pvalues))
+        if self.reference:
+            self.reference_param = self.reference[0]
+            self.reference_value = self.reference[1]
+
+    def time_all(self):
+        """Run benchmark for all versions and parameters."""
+        for params in self.pcombos:
+            args = dict(zip(self.pnames, params))
+            t = self.run(**args)
+            self.results.append(tuple(params) + (t,))
+            self.results_dict[tuple(params)] = t
+
+    def sort_results(self):
+        sort_keys = []
+        for name in self.sort_by:
+            sort_keys += [self.pnames.index(name)]
+        for i, name in enumerate(self.pnames):
+            if i not in sort_keys:
+                sort_keys += [i]
+        def key(v):
+            return list(v[i] for i in sort_keys)
+        self.results.sort(key=key)
+
+    def get_factor(self, pvalues, time):
+        if not self.reference or not time:
+            return None
+        pvalues = list(pvalues)
+        i = self.pnames.index(self.reference_param)
+        if pvalues[i] == self.reference_value:
+            return None
+        else:
+            pvalues[i] = self.reference_value
+        ref = self.results_dict[tuple(pvalues)]
+        if ref == None:
+            return None
+        return ref / time
+
+    def print_result(self):
+        """Run benchmark for all versions and parameters and print results
+        in tabular form to the standard output."""
+        self.time_all()
+        self.sort_results()
+
+        print "=" * 78
+        print
+        print self.__class__.__name__
+        print self.__doc__, "\n"
+
+        colwidth = 15
+        reftimes = {}
+
+        ts = "seconds"
+        if self.reference:
+            ts += " (x faster than " + (str(self.reference_value)) + ")"
+        print "  ", "   ".join([str(r).ljust(colwidth) for r in self.pnames + [ts]])
+        print "-"*79
+
+        rows = []
+        for vals in self.results:
+            pvalues =  vals[:-1]
+            time = vals[-1]
+            if time == None:
+                stime = "(n/a)"
+            else:
+                stime = "%.8f" % time
+                factor = self.get_factor(pvalues, time)
+                if factor != None:
+                    stime += ("  (%.2f)" % factor)
+            vals = pvalues + (stime,)
+            row = [str(val).ljust(colwidth) for val in vals]
+            print "  ", "   ".join(row)
+        print

+ 54 - 0
LibOS/shim/test/apps/python/fibonacci.py

@@ -0,0 +1,54 @@
+"""
+Downloaded from https://code.google.com/p/benchrun/
+
+Fibonacci numbers test benchmark
+"""
+
+from benchrun import Benchmark, clock
+
+def fib1(n):
+    if n < 2:
+        return n
+    return fib1(n-1) + fib1(n-2)
+
+def fib2(n):
+    if n < 2:
+        return n
+    a, b = 1, 0
+    for i in xrange(n-1):
+        a, b = a+b, a
+    return a
+
+class FibonacciBenchmark(Benchmark):
+    """Compare time to compute the nth Fibonacci number recursively
+    (fib1) and iteratively (fib2)."""
+
+    # Execute for all combinations of these parameters
+    parameters = ['version', 'n']
+    version = ['fib1', 'fib2']
+    n = range(0, 60, 5)
+
+    # Compare timings against this parameter value
+    reference = ('version', 'fib1')
+
+    def run(self, n, version):
+        f = globals()[version]
+        # Don't repeat when slow
+        if version == 'fib1' and n > 10:
+            # Skip altogether
+            if n > 30:
+                return None
+            t1 = clock()
+            f(n)
+            t2 = clock()
+            return t2-t1
+        # Need to repeat many times to get accurate timings for small n
+        else:
+            t1 = clock()
+            f(n); f(n); f(n); f(n); f(n); f(n); f(n)
+            f(n); f(n); f(n); f(n); f(n); f(n); f(n)
+            t2 = clock()
+            return (t2 - t1) / 14
+
+if __name__ == '__main__':
+    FibonacciBenchmark().print_result()

+ 3 - 0
LibOS/shim/test/apps/python/helloworld.py

@@ -0,0 +1,3 @@
+#!/usr/bin/python
+
+print "Hello World"

+ 28 - 0
LibOS/shim/test/apps/python/python.manifest.template

@@ -0,0 +1,28 @@
+#!$(PWD)../libpal.so
+
+loader.preload = file:$(SHIMPATH)
+loader.exec = file:/usr/bin/python
+loader.execname = python
+loader.env.LD_LIBRARY_PATH = /lib:/lib/x86_64-linux-gnu:/usr/lib:/usr/lib/x86_64-linux-gnu
+loader.env.PATH = /usr/bin
+loader.env.USERNAME =
+loader.env.HOME =
+loader.env.PWD =
+loader.debug_type = none
+
+fs.mount.root.type = chroot
+fs.mount.root.uri = file:
+
+fs.mount.other.lib1.type = chroot
+fs.mount.other.lib1.path = /lib
+fs.mount.other.lib1.uri = file:$(GLIBCDIR)
+
+fs.mount.other.lib2.type = chroot
+fs.mount.other.lib2.path = /lib/x86_64-linux-gnu
+fs.mount.other.lib2.uri = file:/lib/x86_64-linux-gnu
+
+fs.mount.other.usr.type = chroot
+fs.mount.other.usr.path = /usr
+fs.mount.other.usr.uri = file:/usr
+
+sys.brk.size = 262144  # 256K

+ 70 - 0
LibOS/shim/test/apps/python/sympybench.py

@@ -0,0 +1,70 @@
+"""
+Downloaded from https://code.google.com/p/benchrun/
+
+Test code for benchrun: sympy performance benchmark.
+"""
+
+from benchrun import Benchmark, clock
+
+import sympycore
+import sympy
+
+class SympyBenchmark(Benchmark):
+    version = ['sympy', 'sympycore']
+    reference = ('version', 'sympy')
+
+
+class DirectSymbolicAddition(SympyBenchmark):
+    """Add small polynomials with rational coefficients"""
+    parameters = ['version']
+    def run(self, version):
+        module = __import__(version)
+        x, y, z = map(module.Symbol, 'xyz')
+        a = 3*x + 2*x*y - module.Rational(1,2)*z + 2
+        b = 2*x + module.Rational(3,2)*x*y + 4*z - 2
+        n = N = 100
+        t1 = clock()
+        while n:
+            a + n*b
+            n -= 1
+        t2 = clock()
+        return (t2-t1)/N
+
+class PowerExpansion(SympyBenchmark):
+    """Expand (x+y+z)**n * (y+x)**(n-1)"""
+    parameters = ['version', 'n']
+    n = [5, 10, 20]
+    def run(self, version, n):
+        module = __import__(version)
+        if version == 'sympy' and n > 10:
+            return None
+        x, y, z = map(module.Symbol, 'xyz')
+        t1 = clock()
+        e = ((x+y+z)**n * (y+x)**(n-1)).expand()
+        t2 = clock()
+        return t2-t1
+
+class LegendreRecurrence(SympyBenchmark):
+    """Calculate the nth Legendre polynomial by recurrence."""
+    parameters = ['version', 'n']
+    n = [3, 10, 30, 100]
+    def run(self, version, n):
+        module = __import__(version)
+        x = module.Symbol('x')
+        if version == 'sympy' and n > 30:
+            return None
+        b, a = x, 1
+        t1 = clock()
+        for n in range(1, n):
+            b, a = (((2*n+1)*x*b - n*a)/(n+1)).expand(), b
+        t2 = clock()
+        return t2-t1
+
+all_benchmarks = [
+  DirectSymbolicAddition(),
+  PowerExpansion(),
+  LegendreRecurrence(),
+]
+
+for bench in all_benchmarks:
+    bench.print_result()

+ 11 - 2
Pal/Makefile

@@ -1,5 +1,5 @@
 LINUX_GEN = 3.x
-LINUX_SRC = linux-3.5
+LINUX_SRC = linux-3.14
 SRC_DIR = src
 TEST_DIR = test
 DIRS = ${SRC_DIR} ${TEST_DIR} $(LINUX_SRC)
@@ -35,7 +35,16 @@ $(LINUX_SRC)/Makefile:
 	[ ! -f $(LINUX_SRC).patch ] || git apply $(LINUX_SRC).patch
 
 $(LINUX_SRC)/.config:
-	$(error "Configure the kernel source and rerun the make command")
+	$(error "Configure the Linux kernel source and rerun the make command; Or run 'make linux-deb' to build a Linux kernel package")
+
+linux-deb:
+	[ -f $(LINUX_SRC)/.config ] || \
+		(cp /boot/config-$(shell uname -r) $(LINUX_SRC)/.config && \
+		cd $(LINUX_SRC) && make menuconfig)
+	cd $(LINUX_SRC) && \
+	CONCURRENCY_LEVEL=$(NPROCS) make-kpkg --rootcmd fakeroot \
+		--append-to-version -graphene --initrd \
+		kernel-image kernel-headers
 
 clean:
 	for d in ${SRC_DIR} $(TEST_DIR) $(LINUX_SRC); \

+ 23 - 10
Pal/ipc/linux/graphene-ipc.c

@@ -471,21 +471,34 @@ int recv_helper (unsigned long *addr, unsigned long len, int prot,
 		 * vma.  Correct if not. 
 		 */
 #if defined(CONFIG_GRAPHENE_BULK_IPC) || LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
-		my_addr = do_mmap_pgoff(vm_file, my_addr, PAGE_SIZE * (page_count - i),
-				      prot,
-				      flags, vm_pgoff);
-#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
-		my_addr = my_do_mmap_pgoff(vm_file, my_addr, PAGE_SIZE * (page_count - i),
-					 prot,
-					 flags, vm_pgoff);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
+		my_addr = do_mmap_pgoff(vm_file, my_addr,
+					PAGE_SIZE * (page_count - i),
+					prot, flags, vm_pgoff);
 #else
 		{
 			unsigned long populate;
-			my_addr = my_do_mmap_pgoff(vm_file, my_addr, PAGE_SIZE * (page_count - i),
-						 prot,
-						 flags, vm_pgoff, &populate);
+			my_addr = do_mmap_pgoff(vm_file, my_addr,
+						PAGE_SIZE * (page_count - i),
+						prot,
+						flags, vm_pgoff, &populate);
 		}
 #endif /* kernel_version >= 3.9.0 */
+#else
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)
+		my_addr = my_do_mmap_pgoff(vm_file, my_addr,
+					   PAGE_SIZE * (page_count - i),
+					   prot, flags, vm_pgoff);
+#else
+		{
+			unsigned long populate;
+			my_addr = my_do_mmap_pgoff(vm_file, my_addr,
+						   PAGE_SIZE * (page_count - i),
+						   prot,
+						   flags, vm_pgoff, &populate);
+		}
+#endif /* kernel_version >= 3.9.0 */
+#endif
 
 		if (!my_addr) {
 			printk(KERN_ERR

+ 1 - 2
Pal/lib/Makefile

@@ -30,5 +30,4 @@ graphene-lib.a: $(objs)
 	@$(CC) $(CFLAGS) -c $< -o $@
 
 clean:
-	rm -rf $(objs)
-	[ ! -f graphene-lib.a ] || mv -f graphene-lib.a graphene-lib.a.backup
+	rm -f $(objs) graphene-lib.a

+ 0 - 0
Pal/linux-3.14.patch


+ 17 - 0
Pal/linux-3.14/graphene/Kconfig

@@ -0,0 +1,17 @@
+menuconfig GRAPHENE
+	bool "Graphene support (EXPERIMENTAL)"
+	default y
+
+if GRAPHENE
+	config GRAPHENE_ISOLATE
+		bool "Graphene isolation support (EXPERIMENTAL)"
+		default y
+
+	config GRAPHENE_BULK_IPC
+		tristate "Graphene Bulk IPC support (EXPERIMENTAL)"
+		default y
+
+	config GRAPHENE_DEBUG
+		bool "Graphene debug feature (EXPERIMENTAL)"
+		default n
+endif

+ 2 - 0
Pal/linux-3.14/graphene/Makefile

@@ -0,0 +1,2 @@
+obj-$(CONFIG_GRAPHENE) += graphene.o
+obj-$(CONFIG_GRAPHENE_BULK_IPC) += graphene-ipc.o

+ 1 - 0
Pal/linux-3.14/graphene/graphene-ipc.c

@@ -0,0 +1 @@
+../../ipc/linux/graphene-ipc.c

+ 1 - 0
Pal/linux-3.14/graphene/graphene-ipc.h

@@ -0,0 +1 @@
+../../ipc/linux/graphene-ipc.h

+ 1653 - 0
Pal/linux-3.14/graphene/graphene.c

@@ -0,0 +1,1653 @@
+/*
+ *  linux/graphene/graphene.c
+ *
+ *  Copyright (C) 2013-, Chia-Che Tsai, Bhushan Jain and Donald Porter
+ *
+ *  Manage the graphene information and security policies.
+ */
+
+#include <linux/version.h>
+#include <linux/atomic.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/fdtable.h>
+#include <linux/dcache.h>
+#include <linux/namei.h>
+#include <linux/fs_struct.h>
+#include <linux/mount.h>
+#include <linux/rcupdate.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <linux/un.h>
+#include <linux/net.h>
+#include <net/sock.h>
+#include <net/inet_sock.h>
+#include <net/tcp_states.h>
+#include <linux/pipe_fs_i.h>
+#include <../fs/internal.h>
+#include <../security/apparmor/include/audit.h>
+#include "graphene.h"
+#include "graphene-ipc.h"
+
+static struct list_head unix_list = LIST_HEAD_INIT(unix_list);
+static DEFINE_SPINLOCK(unix_list_lock);
+
+static atomic_t gipc_session;
+
+static int add_graphene_unix(struct graphene_unix *u)
+{
+	struct graphene_unix *tmp;
+	int err = 0;
+
+	rcu_read_lock();
+
+	list_for_each_entry_rcu(tmp, &unix_list, list) {
+		if (u->root.mnt) {
+			if (!tmp->root.mnt)
+				continue;
+			if (!path_equal(&tmp->root, &u->root))
+				continue;
+		}
+		if (u->prefix.len) {
+			int len;
+			if (!tmp->prefix.len)
+				continue;
+			len = u->prefix.len < tmp->prefix.len ?
+			      u->prefix.len : tmp->prefix.len;
+			if (!strncmp(u->prefix.name, tmp->prefix.name, len)) {
+				err = -EACCES;
+				break;
+			}
+		}
+	}
+
+	if (!err) {
+		spin_lock(&unix_list_lock);
+		list_add_tail_rcu(&u->list, &unix_list);
+		spin_unlock(&unix_list_lock);
+	}
+
+	rcu_read_unlock();
+	return err;;
+}
+
+int dup_graphene_struct(struct task_struct *tsk)
+{
+	struct graphene_struct *gs, *new;
+	struct graphene_info *gi;
+
+	if (!(tsk->graphene))
+		return 0;
+
+	if (tsk->group_leader != tsk) {
+		atomic_inc(&tsk->graphene->g_count);
+		return 0;
+	}
+
+	gs = tsk->graphene;
+	new = kmalloc(sizeof(struct graphene_struct), GFP_KERNEL);
+	if (!new)
+		return -ENOMEM;
+
+	spin_lock(&gs->g_lock);
+	gi = gs->g_info;
+	atomic_inc(&gi->gi_count);
+	new->g_info = gi;
+	spin_unlock(&gs->g_lock);
+
+	atomic_set(&new->g_count, 1);
+	spin_lock_init(&new->g_lock);
+	tsk->graphene = new;
+
+	return 0;
+}
+
+static void drop_graphene_info(struct graphene_info *info)
+{
+	struct graphene_path *p, *n;
+	int i;
+
+	list_for_each_entry_safe(p, n, &info->gi_paths, list) {
+		path_put(&p->path);
+		kfree(p);
+	}
+
+	list_for_each_entry_safe(p, n, &info->gi_rpaths, list) {
+		path_put(&p->path);
+		kfree(p);
+	}
+
+	if (info->gi_libexec.dentry)
+		path_put(&info->gi_libexec);
+
+	if (info->gi_unix) {
+		struct graphene_unix *u = info->gi_unix;
+		if (!atomic_dec_return(&u->count)) {
+			spin_lock(&unix_list_lock);
+			if (!list_empty(&u->list)) {
+				list_del_rcu(&u->list);
+				spin_unlock(&unix_list_lock);
+				synchronize_rcu();
+			}
+			if (u->root.mnt)
+				path_put(&u->root);
+			if (u->prefix.len)
+				kfree(u->prefix.name);
+			kfree(u);
+		}
+	}
+
+	for (i = 0 ; i < 3 ; i++)
+		if (info->gi_console[i].mnt)
+			path_put(&info->gi_console[i]);
+
+	kfree(info);
+}
+
+static void put_graphene_info(struct graphene_info *info)
+{
+	if (!atomic_dec_return(&info->gi_count))
+		drop_graphene_info(info);
+}
+
+void put_graphene_struct(struct task_struct *tsk)
+{
+	struct graphene_struct *gs = tsk->graphene;
+	if (gs) {
+		tsk->graphene = NULL;
+		if (atomic_dec_return(&gs->g_count))
+			return;
+		put_graphene_info(gs->g_info);
+		kfree(gs);
+	}
+}
+
+static inline
+struct graphene_info *get_graphene_info(struct graphene_struct *gs)
+{
+	struct graphene_info *info;
+	if (!gs)
+		return NULL;
+	rcu_read_lock();
+	info = rcu_dereference_check(gs->g_info,
+				     lockdep_is_held(&gs->g_lock) ||
+				     atomic_read(&gs->g_count) == 1 ||
+				     rcu_my_thread_group_empty());
+	rcu_read_unlock();
+	return info;
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
+# define FILE_INODE(file) ((file)->f_inode)
+#else
+# define FILE_INODE(file) ((file)->f_dentry->d_inode)
+#endif
+
+static loff_t graphene_lib_llseek(struct file *file, loff_t offset, int origin)
+{
+	struct inode *inode = FILE_INODE(file);
+
+	if (!inode)
+		return -EINVAL;
+	if (!inode->i_fop || !inode->i_fop->llseek)
+		return -EINVAL;
+
+	return inode->i_fop->llseek(file, offset, origin);
+}
+
+static ssize_t graphene_lib_read (struct file *file, char __user *buf,
+				  size_t len, loff_t *ppos)
+{
+	struct inode *inode = FILE_INODE(file);
+
+	if (!inode)
+		return -EINVAL;
+	if (!inode->i_fop || !inode->i_fop->read)
+		return -EINVAL;
+
+	return inode->i_fop->read(file, buf, len, ppos);
+}
+
+static ssize_t graphene_lib_aio_read (struct kiocb *iocb, const struct iovec *iov,
+				      unsigned long nr_segs, loff_t pos)
+{
+	struct inode *inode = FILE_INODE(iocb->ki_filp);
+
+	if (!inode)
+		return -EINVAL;
+	if (!inode->i_fop || !inode->i_fop->aio_read)
+		return -EINVAL;
+
+	return inode->i_fop->aio_read(iocb, iov, nr_segs, pos);
+}
+
+static int graphene_lib_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct inode *inode = FILE_INODE(file);
+
+	if (!inode)
+		return -EINVAL;
+	if (!inode->i_fop || !inode->i_fop->mmap)
+		return -EINVAL;
+
+	return inode->i_fop->mmap(file, vma);
+}
+
+static int graphene_lib_release(struct inode *inode, struct file *file)
+{
+	if (!inode)
+		return -EINVAL;
+	if (!inode->i_fop || !inode->i_fop->release)
+		return -EINVAL;
+	return inode->i_fop->release(inode, file);
+}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+# define DEFINE_PATH_BUFFER(fn, kpath, max) struct filename *fn; char *kpath; int max;
+#else
+# define DEFINE_PATH_BUFFER(fn, kpath, max) char * kpath; int max;
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+# define GET_PATH_BUFFER(fn, kpath, max)				\
+	fn = __getname();						\
+	kpath = (char *) fn + sizeof(*fn);				\
+	max = PATH_MAX - sizeof(*fn);
+#else
+# define GET_PATH_BUFFER(fn, kpath, max)				\
+	kpath = __getname();						\
+	max = PATH_MAX;
+#endif
+
+
+#define DEFINE_PATH(dp, path, fn, kpath, max)				\
+	DEFINE_PATH_BUFFER(fn, kpath, max)				\
+	char *dp;							\
+	GET_PATH_BUFFER(fn, kpath, max)					\
+	dp = d_path(path, kpath, max);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
+# define PUT_PATH_BUFFER(fn, kpath) final_putname(fn);
+#else
+# define PUT_PATH_BUFFER(fn, kpath) putname(kpath);
+#endif
+
+static unsigned long
+graphene_lib_get_area(struct file *file, unsigned long addr, unsigned long len,
+		      unsigned long pgoff, unsigned long flags)
+{
+	struct task_struct *current_tsk = current;
+	struct graphene_info *gi = get_graphene_info(current_tsk->graphene);
+	struct inode *inode = FILE_INODE(file);
+	unsigned long (*get_area) (struct file *, unsigned long, unsigned long,
+				   unsigned long, unsigned long);
+
+	if (!inode)
+		return -EINVAL;
+
+	if (gi->gi_libaddr) {
+		if (!path_equal(&file->f_path, &gi->gi_libexec))
+			BUG();
+
+		if (!addr)
+			addr = gi->gi_libaddr + pgoff * PAGE_SIZE;
+
+#ifdef CONFIG_GRAPHENE_DEBUG
+		{
+			DEFINE_PATH(dp, &file->f_path, fn, kpath, max)
+			if (!IS_ERR(dp))
+				printk(KERN_INFO "Graphene: PID %d MAP FILE %s"
+				       " OFF 0x%08lx AT 0x%016lx\n",
+				       current->pid, dp,
+				       pgoff * PAGE_SIZE, addr);
+			PUT_PATH_BUFFER(fn, kpath)
+		}
+#endif
+		return addr;
+	}
+
+	get_area = (inode->i_fop && inode->i_fop->get_unmapped_area) ?
+		   inode->i_fop->get_unmapped_area :
+		   current_tsk->mm->get_unmapped_area;
+
+	return get_area(file, addr, len, pgoff, flags);
+}
+
+/* These are file oprations required for execve */
+static struct file_operations graphene_lib_operations = {
+	.llseek			= graphene_lib_llseek,
+	.read			= graphene_lib_read,
+	.aio_read		= graphene_lib_aio_read,
+	.mmap			= graphene_lib_mmap,
+	.get_unmapped_area	= graphene_lib_get_area,
+	.release		= graphene_lib_release,
+};
+
+#ifdef CONFIG_GRAPHENE_DEBUG
+static void print_path(const char * fmt, struct path *path)
+{
+	DEFINE_PATH(dp, path, fn, kpath, max)
+	printk(fmt, current->pid, IS_ERR(dp) ? "(unknown)" : dp);
+	PUT_PATH_BUFFER(fn, kpath)
+}
+#else
+# define print_path(...) do {} while (0)
+#endif
+
+int graphene_execve_open(struct file *file)
+{
+	struct task_struct *current_tsk = current;
+	struct graphene_info *gi = get_graphene_info(current_tsk->graphene);
+
+	if (!current_tsk->in_execve)
+		BUG();
+
+	if (!path_equal(&file->f_path, &gi->gi_libexec)) {
+		print_path(KERN_INFO "Graphene: DENY EXEC PID %d PATH %s\n",
+			   &file->f_path);
+		return -EACCES;
+	}
+
+	if (!gi->gi_libaddr)
+		goto accepted;
+
+	file->f_op = &graphene_lib_operations;
+accepted:
+	print_path(KERN_INFO "Graphene: ALLOW EXEC PID %d PATH %s\n",
+		   &file->f_path);
+	return 0;
+}
+
+static int graphene_check_path(struct graphene_info *gi, int op, u32 mask,
+			       struct path *path, struct graphene_path *gp,
+			       int is_recursive)
+{
+	if (!path_equal(path, &gp->path))
+		return 0;
+
+	if (mask & (MAY_READ|MAY_EXEC|MAY_ACCESS|
+		    AA_MAY_META_READ|AA_EXEC_MMAP|AA_MAY_LINK)) {
+		if (!(gp->type & GRAPHENE_FS_READ))
+			return -EACCES;
+	}
+
+	if (mask & (MAY_WRITE|MAY_APPEND|
+		    AA_MAY_CREATE|AA_MAY_DELETE|AA_MAY_META_WRITE|
+		    AA_MAY_CHMOD|AA_MAY_CHOWN)) {
+		if (!(gp->type & GRAPHENE_FS_WRITE))
+			return -EACCES;
+	}
+
+	return 1;
+}
+
+static int __common_perm(struct graphene_info *gi, int op, struct path *target,
+			 u32 mask)
+{
+	struct graphene_path *p;
+	struct path root, path = *target;
+	struct qstr last;
+	int rv = 0, i;
+
+	BUG_ON(!path.dentry);
+	path_get(&path);
+
+	if (op == OP_OPEN) {
+		int minor = iminor(path.dentry->d_inode);
+		if (minor == GRAPHENE_MINOR)
+			goto out;
+		if (minor == GIPC_MINOR)
+			goto out;
+	}
+
+	rcu_read_lock();
+
+	for (i = 0 ; i < 3 ; i++) {
+		if (!gi->gi_console[i].mnt)
+			continue;
+		if (path_equal(&gi->gi_console[i], &path))
+			goto out;
+	}
+
+	list_for_each_entry_rcu(p, &gi->gi_paths, list) {
+		rv = graphene_check_path(gi, op, mask, &path, p, 0);
+		if (rv)
+			goto out;
+	}
+
+	if (gi->gi_libexec.mnt && path_equal(&path, &gi->gi_libexec)) {
+		rv = 0;
+		goto out;
+	}
+
+	get_fs_root(current->fs, &root);
+	last.len = 0;
+
+	while (!path_equal(&path, &root)) {
+		int is_recursive = 0;
+
+		list_for_each_entry_rcu(p, &gi->gi_rpaths, list) {
+			rv = graphene_check_path(gi, op, mask, &path, p,
+						 is_recursive);
+			if (rv)
+				goto out_root;
+		}
+
+		if (gi->gi_unix && gi->gi_unix->root.mnt) {
+			struct graphene_unix *u = gi->gi_unix;
+
+			if (path_equal(&path, &u->root)) {
+				rv = 0;
+				if (op == OP_MKNOD)
+					goto out_root;
+				if (op == OP_UNLINK) {
+					if (!u->prefix.len)
+						goto out_root;
+					if (last.len) {
+						int len = u->prefix.len;
+						if (last.len < len)
+							len = last.len;
+						if (!strncmp(last.name,
+							     u->prefix.name,
+							     len))
+							goto out_root;
+					}
+				}
+				break;
+			}
+		}
+
+		last = path.dentry->d_name;
+		while(1) {
+			struct dentry *old = path.dentry;
+
+			if (path_equal(&path, &root))
+				break;
+
+			if (path.dentry != path.mnt->mnt_root) {
+				path.dentry = dget_parent(path.dentry);
+				dput(old);
+				break;
+			}
+
+			if (!follow_up(&path))
+				break;
+		}
+		is_recursive = 1;
+	}
+
+	rv = -EACCES;
+out_root:
+	path_put(&root);
+out:
+	rcu_read_unlock();
+	path_put(&path);
+	if (rv >= 0) {
+		rv = 0;
+		print_path(KERN_INFO "Graphene: ALLOW PID %d PATH %s\n", target);
+	} else {
+		print_path(KERN_INFO "Graphene: DENY PID %d PATH %s\n", target);
+	}
+	return rv;
+}
+
+int graphene_common_perm(int op, struct path *path, u32 mask)
+{
+	struct graphene_info *gi = get_graphene_info(current->graphene);
+
+	if (!gi)
+		return 0;
+
+	return __common_perm(gi, op, path, mask);
+}
+
+static int __unix_perm(struct sockaddr *address, int addrlen)
+{
+	struct graphene_info *gi = get_graphene_info(current->graphene);
+	const char *path, *sun_path;
+	struct nameidata nd;
+	struct path *p = NULL;
+	int err = 0;
+
+	if (!gi->gi_unix)
+		return -EPERM;
+
+	path = sun_path = ((struct sockaddr_un *) address)->sun_path;
+
+	if (gi->gi_unix->root.mnt) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+		struct path parent;
+
+		err = kern_path(path, LOOKUP_FOLLOW, &nd.path);
+		if (!err)
+			return err;
+
+		p = &nd.path;
+
+		err = vfs_path_lookup(nd.path.dentry, nd.path.mnt, "..", 0,
+				      &parent);
+		if (!err)
+			goto denied;
+
+		if (!path_equal(&gi->gi_unix->root, &parent))
+			goto denied;
+
+		path_put(&parent);
+		path = nd.path.dentry->d_name.name;
+#else
+		err = kern_path_parent(path, &nd);
+		if (!err)
+			return err;
+
+		path_put(&nd.path);
+		path = nd.last.name;
+
+		if (!path_equal(&gi->gi_unix->root, &nd.path))
+			goto denied;
+
+#endif
+	}
+
+	if (gi->gi_unix->prefix.len &&
+	    memcmp(path, gi->gi_unix->prefix.name,
+		   gi->gi_unix->prefix.len))
+		err = -EPERM;
+
+	if (p)
+		path_put(p);
+
+	if (!err)
+		return 0;
+
+denied:
+#ifdef CONFIG_GRAPHENE_DEBUG
+	printk(KERN_INFO "Graphene: DENY PID %d SOCKET %s\n",
+	       current->pid, sun_path);
+#endif
+	if (p)
+		path_put(p);
+	return -EPERM;
+}
+
+static int net_cmp(int family, int addr_any, int port_any,
+		   struct graphene_net_addr *ga,
+		   struct sockaddr *addr, int addrlen)
+{
+	switch(family) {
+	case AF_INET: {
+		struct sockaddr_in *a = (void *) addr;
+
+		if (!addr_any) {
+			if (a->sin_addr.s_addr != ga->addr.sin_addr.s_addr)
+				return -EPERM;
+		}
+		if (!port_any) {
+			unsigned short port = ntohs(a->sin_port);
+			if (!(port >= ga->port_begin && port <= ga->port_end))
+				return -EPERM;
+		}
+
+		break;
+	}
+#ifdef CONFIG_IPV6
+	case AF_INET6: {
+		struct sockaddr_in6 *a6 = (void *) addr;
+
+		if (!addr_any) {
+			if (memcmp(&a6->sin6_addr, &ga->addr.sin6_addr,
+				   sizeof(struct in6_addr)))
+				return -EPERM;
+		}
+		if (!port_any) {
+			unsigned short port = ntohs(a6->sin6_port);
+			if (!(port >= ga->port_begin && port <= ga->port_end))
+				return -EPERM;
+		}
+
+		break;
+	}
+#endif
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_GRAPHENE_DEBUG
+static void print_net(int allow, int family, int op,
+		      struct sockaddr *local_addr, int local_addrlen,
+		      struct sockaddr *peer_addr, int peer_addrlen)
+{
+	const char *allow_str = allow ? "ALLOW" : "DENY";
+	const char *op_str = "";
+	int print_peer = (op == OP_CONNECT || op == OP_SENDMSG);
+
+	switch(op) {
+		case OP_BIND:		op_str = "BIND";	break;
+		case OP_LISTEN:		op_str = "LISTEN";	break;
+		case OP_CONNECT:	op_str = "CONNECT";	break;
+		case OP_SENDMSG:	op_str = "SENDMSG";	break;
+		case OP_RECVMSG:	op_str = "RECVMSG";	break;
+	}
+
+	if (family == AF_INET) {
+		struct sockaddr_in *la = (void *) local_addr;
+		u8 *a1 = (u8 *) &la->sin_addr.s_addr;
+		struct sockaddr_in *pa = (void *) peer_addr;
+		u8 *a2 = (u8 *) &pa->sin_addr.s_addr;
+
+		if (print_peer && peer_addr) {
+			printk(KERN_INFO "Graphene: %s %s PID %d SOCKET "
+			       "%d.%d.%d.%d:%d:%d.%d.%d.%d:%d\n",
+			       allow_str, op_str, current->pid,
+			       a1[0], a1[1], a1[2], a1[3], ntohs(la->sin_port),
+			       a2[0], a2[1], a2[2], a2[3], ntohs(pa->sin_port));
+		} else {
+			printk(KERN_INFO "Graphene: %s %s PID %d SOCKET "
+			       "%d.%d.%d.%d:%d\n",
+			       allow_str, op_str, current->pid,
+			       a1[0], a1[1], a1[2], a1[3], ntohs(la->sin_port));
+		}
+	}
+
+#ifdef CONFIG_IPV6
+	if (family == AF_INET6) {
+		struct sockaddr_in6 *la = (void *) local_addr;
+		u16 *a1 = (u16 *) &la->sin6_addr.s6_addr;
+		struct sockaddr_in6 *pa = (void *) peer_addr;
+		u16 *a2 = (u16 *) &pa->sin6_addr.s6_addr;
+
+		if (print_peer) {
+			printk(KERN_INFO "Graphene: %s %s PID %d SOCKET "
+			       "[%d:%d:%d:%d:%d:%d:%d:%d]:%d:"
+			       "[%d.%d.%d.%d:%d:%d:%d:%d]:%d\n",
+			       allow_str, op_str, current->pid,
+			       a1[0], a1[1], a1[2], a1[3],
+			       a1[4], a1[5], a1[6], a1[7], ntohs(la->sin6_port),
+			       a2[0], a2[1], a2[2], a2[3],
+			       a2[4], a2[5], a2[6], a2[7], ntohs(pa->sin6_port));
+		} else {
+			printk(KERN_INFO "Graphene: %s %s PID %d SOCKET "
+			       "[%d.%d.%d.%d:%d:%d:%d:%d]:%d\n",
+			       allow_str, op_str, current->pid,
+			       a1[0], a1[1], a1[2], a1[3],
+			       a1[4], a1[5], a1[6], a1[7], ntohs(la->sin6_port));
+		}
+	}
+#endif
+}
+#else
+# define print_net(...) do {} while (0)
+#endif
+
+/*
+ * network rules:
+ *    bind:
+ *        input addr/port match local addr/port
+ *    listen:
+ *        local addr/port match local addr/port
+ *        allow ANY peer addr/port
+ *    connect:
+ *        local/remote addr/port match local/remote addr/port
+ *    sendmsg:
+ *        EITHER stream socket OR no inport addr/port OR
+ *        local/remote addr/port match local/remote addr/port
+ *    recvmsg:
+ *        EITHER stream socket OR connected OR
+ *        allow ANY peer addr/port
+ */
+static
+int __common_net_perm(struct graphene_info *gi, int op, struct socket *sock,
+		      struct sockaddr *address, int addrlen)
+{
+	struct sock *sk = sock->sk;
+	struct inet_sock *inet = inet_sk(sk);
+	struct graphene_net *gn;
+	struct sockaddr_storage addrbuf;
+	struct sockaddr * local_addr = NULL, * peer_addr = NULL;
+	int local_addrlen, peer_addrlen;
+	int local_needcmp = 0, peer_needcmp = 0;
+	int local_needany = 0, peer_needany = 0;
+	int err;
+
+	if (sk->sk_type != SOCK_STREAM && sk->sk_type != SOCK_DGRAM)
+		return -EPERM;
+
+#ifdef CONFIG_IPV6
+	if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)
+#else
+	if (sk->sk_family != AF_INET)
+#endif
+		return -EPERM;
+
+	if (list_empty(&gi->gi_net))
+		return -EPERM;
+
+	if (op == OP_LISTEN)
+		peer_needany = 1;
+
+	if (op == OP_RECVMSG) {
+		if (inet->inet_dport)
+			return 0;
+
+		peer_needany = 1;
+	}
+
+	if (op == OP_CONNECT || op == OP_SENDMSG) {
+		BUG_ON(!address);
+		peer_addr = address;
+		peer_addrlen = addrlen;
+		peer_needcmp = 1;
+	}
+
+	if (op == OP_BIND) {
+		BUG_ON(!address);
+		local_addr = address;
+		local_addrlen = addrlen;
+		local_needcmp = 1;
+		if (sk->sk_type == SOCK_DGRAM)
+			peer_needany = 1;
+	} else {
+		local_addr = (struct sockaddr *) &addrbuf;
+		local_needcmp = 1;
+
+		err = sock->ops->getname(sock, local_addr, &local_addrlen, 0);
+		if (err < 0)
+			return err;
+	}
+
+	list_for_each_entry(gn, &gi->gi_net, list) {
+		if (gn->family != sk->sk_family)
+			continue;
+
+		if (local_needany &&
+		    (gn->flags & (LOCAL_ADDR_ANY|LOCAL_PORT_ANY)) !=
+		    (LOCAL_ADDR_ANY|LOCAL_PORT_ANY))
+			continue;
+
+		if (peer_needany &&
+		    (gn->flags & (PEER_ADDR_ANY|PEER_PORT_ANY)) !=
+		    (PEER_ADDR_ANY|PEER_PORT_ANY))
+			continue;
+
+		if (local_needcmp) {
+			err = net_cmp(sk->sk_family, gn->flags & LOCAL_ADDR_ANY,
+				      gn->flags & LOCAL_PORT_ANY,
+				      &gn->local, local_addr, local_addrlen);
+			if (err < 0)
+				continue;
+		}
+
+		if (peer_needcmp) {
+			err = net_cmp(sk->sk_family, gn->flags & PEER_ADDR_ANY,
+				      gn->flags & PEER_PORT_ANY,
+				      &gn->peer, peer_addr, peer_addrlen);
+			if (err < 0)
+				continue;
+		}
+
+		print_net(1, sk->sk_family, op, local_addr, local_addrlen,
+			  peer_addr, peer_addrlen);
+		return 0;
+	}
+
+	print_net(0, sk->sk_family, op, local_addr, local_addrlen,
+		  peer_addr, peer_addrlen);
+	return -EPERM;
+}
+
+int graphene_socket_bind(struct socket *sock,
+			 struct sockaddr *address, int addrlen)
+{
+	if (GRAPHENE_ENABLED()) {
+		struct graphene_info *gi = get_graphene_info(current->graphene);
+
+		if (!sock || !sock->sk)
+			return 0;
+
+		if (sock->sk->sk_family == PF_UNIX) {
+			if (sock->sk->sk_type != SOCK_STREAM)
+				return -EPERM;
+
+			return __unix_perm(address, addrlen);
+		}
+
+		return __common_net_perm(gi, OP_BIND, sock, address, addrlen);
+	}
+	return 0;
+}
+
+int graphene_socket_listen(struct socket *sock, int backlog)
+{
+	if (GRAPHENE_ENABLED()) {
+		struct graphene_info *gi = get_graphene_info(current->graphene);
+
+		if (!sock || !sock->sk || sock->sk->sk_family == PF_UNIX)
+			return 0;
+
+		return __common_net_perm(gi, OP_LISTEN, sock, NULL, 0);
+	}
+	return 0;
+}
+
+int graphene_socket_connect(struct socket *sock,
+			    struct sockaddr *address, int addrlen)
+{
+	if (GRAPHENE_ENABLED()) {
+		struct graphene_info *gi = get_graphene_info(current->graphene);
+
+		if (!sock || !sock->sk)
+			return 0;
+
+		if (sock->sk->sk_family == PF_UNIX) {
+			if (sock->sk->sk_type != SOCK_STREAM)
+				return -EPERM;
+
+			return __unix_perm(address, addrlen);
+		}
+
+		return __common_net_perm(gi, OP_CONNECT, sock, address,
+					 addrlen);
+	}
+	return 0;
+}
+
+int graphene_socket_sendmsg(struct socket *sock,
+			    struct msghdr *msg, int size)
+{
+	if (GRAPHENE_ENABLED()) {
+		struct graphene_info *gi = get_graphene_info(current->graphene);
+
+		if (!sock || !sock->sk || sock->sk->sk_family == PF_UNIX)
+			return 0;
+
+		if (sock->sk->sk_type == SOCK_STREAM)
+			return 0;
+
+		if (!msg->msg_name)
+			return 0;
+
+		return __common_net_perm(gi, OP_SENDMSG, sock,
+					 msg->msg_name, msg->msg_namelen);
+	}
+	return 0;
+
+}
+
+int graphene_socket_recvmsg(struct socket *sock,
+			    struct msghdr *msg, int size, int flags)
+{
+	if (GRAPHENE_ENABLED()) {
+		struct graphene_info *gi = get_graphene_info(current->graphene);
+
+		if (!sock || !sock->sk || sock->sk->sk_family == PF_UNIX)
+			return 0;
+
+		if (sock->sk->sk_type == SOCK_STREAM)
+			return 0;
+
+		return __common_net_perm(gi, OP_RECVMSG, sock, NULL, 0);
+	}
+	return 0;
+}
+
+int graphene_task_kill(struct task_struct *tsk, struct siginfo *info,
+		       int sig, u32 secid)
+{
+	struct task_struct *current_tsk = current;
+
+	if (!current_tsk->graphene)
+		return 0;
+
+	if (sig != SIGCONT)
+		return -EPERM;
+
+	return (tsk->tgid == current_tsk->tgid) ? 0 : -EPERM;
+}
+
+static void get_console(struct graphene_info *gi, struct files_struct *files)
+{
+	int i, j, n = 0;
+	struct fdtable *fdt = files_fdtable(files);
+	j = 0;
+
+	rcu_read_lock();
+	fdt = files_fdtable(files);
+	rcu_read_unlock();
+	for (;;) {
+		unsigned long set;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+		i = j * BITS_PER_LONG;
+#else
+		i = j * __NFDBITS;
+#endif
+		if (i >= fdt->max_fds)
+			break;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+		set = fdt->open_fds[j++];
+#else
+		set = fdt->open_fds->fds_bits[j++];
+#endif
+		for ( ; set ; i++, set >>= 1) {
+			struct file *file;
+			int k;
+
+			if (!(set & 1))
+				continue;
+
+			if (i > 2)
+				goto out;
+
+			file = xchg(&fdt->fd[i], NULL);
+			if (!file)
+				continue;
+
+			for (k = 0 ; k < n ; k++)
+				if (path_equal(&file->f_path, &gi->gi_console[k]))
+					break;
+			if (k == n) {
+				path_get(&file->f_path);
+				gi->gi_console[n++] = file->f_path;
+			}
+#ifdef CONFIG_GRAPHENE_DEBUG
+			{
+				DEFINE_PATH(dp, &file->f_path, fn, kpath, max)
+				if (!IS_ERR(dp))
+					printk(KERN_INFO "Graphene: "
+					       "PID %d CONSOLE %s\n",
+					       current->pid, dp);
+				PUT_PATH_BUFFER(fn, kpath)
+			}
+#endif
+			xchg(&fdt->fd[i], file);
+		}
+	}
+out:
+	for ( ; n < 3 ; n++)
+		gi->gi_console[n].mnt = NULL;
+}
+
+static int update_graphene(struct task_struct *current_tsk,
+			   struct graphene_info *gi);
+
+#ifdef CONFIG_GRAPHENE_DEBUG
+static void print_net_rule(const char *fmt, struct graphene_net *n)
+{
+# ifdef CONFIG_IPV6
+#  define ADDR_STR_MAX	128
+# else
+#  define ADDR_STR_MAX	48
+# endif
+
+	char str[ADDR_STR_MAX];
+	int len = 0, i;
+
+	for (i = 0; i < 2; i++) {
+		unsigned char addr_any = i ? PEER_ADDR_ANY : LOCAL_ADDR_ANY;
+		unsigned char port_any = i ? PEER_PORT_ANY : LOCAL_PORT_ANY;
+		struct graphene_net_addr *a = i ? &n->peer : &n->local;
+
+		if (i)
+			str[len++] = ':';
+
+		switch(n->family) {
+		case AF_INET:
+			if (n->flags & addr_any) {
+				str[len++] = ':';
+			} else {
+				u8 *ip = (u8 *) &a->addr.sin_addr.s_addr;
+				len += snprintf(str + len,
+						ADDR_STR_MAX - len,
+						"%u.%u.%u.%u:",
+						ip[0], ip[1], ip[2], ip[3]);
+			}
+			break;
+#ifdef CONFIG_IPV6
+		case AF_INET6:
+			if (n->flags & addr_any) {
+				str[len++] = '[';
+				str[len++] = ']';
+				str[len++] = ':';
+			} else {
+				u16 *ip = (u16 *) &a->addr.sin6_addr.s6_addr;
+				len += snprintf(str + len,
+						ADDR_STR_MAX - len,
+						"[%u:%u:%u:%u:%u:%u:%u:%u]:",
+						ip[0], ip[1], ip[2], ip[3],
+						ip[4], ip[5], ip[6], ip[7]);
+			}
+			break;
+#endif /* CONFIG_IPV6 */
+		}
+
+		if (!(n->flags & port_any)) {
+			if (a->port_begin == a->port_end)
+				len += snprintf(str + len, ADDR_STR_MAX - len,
+						"%u", a->port_begin);
+			else
+				len += snprintf(str + len, ADDR_STR_MAX - len,
+						"%u-%u",
+						a->port_begin, a->port_end);
+		}
+	}
+
+	BUG_ON(len >= ADDR_STR_MAX);
+	str[len] = 0;
+	printk(fmt, current->pid, str);
+}
+#else
+# define print_net_rule(...) do {} while (0)
+#endif
+
+static int set_net_rule(struct graphene_net_policy *np,
+			struct graphene_info *gi)
+{
+	struct graphene_net *n;
+	int i;
+
+#ifdef CONFIG_IPV6
+	if (np->family != AF_INET && np->family != AF_INET6)
+#else
+	if (np->family != AF_INET)
+#endif
+		return -EINVAL;
+
+	n = kmalloc(sizeof(struct graphene_net), GFP_KERNEL);
+	if (!n)
+		return -ENOMEM;
+
+	n->family  = np->family;
+	n->flags   = 0;
+	n->local   = np->local;
+	n->peer    = np->peer;
+
+	for (i = 0; i < 2; i++) {
+		unsigned char addr_any = i ? PEER_ADDR_ANY : LOCAL_ADDR_ANY;
+		unsigned char port_any = i ? PEER_PORT_ANY : LOCAL_PORT_ANY;
+		struct graphene_net_addr *a = i ? &n->peer : &n->local;
+
+		switch(n->family) {
+		case AF_INET:
+			if (!a->addr.sin_addr.s_addr)
+				n->flags |= addr_any;
+			break;
+#ifdef CONFIG_IPV6
+		case AF_INET6:
+			if (!memcmp(&a->addr.sin6_addr.s6_addr, &in6addr_any, 16))
+				n->flags |= addr_any;
+			break;
+#endif /* CONFIG_IPV6 */
+		}
+
+		if (a->port_begin == 0 && a->port_end == 65535)
+			n->flags |= port_any;
+	}
+
+	INIT_LIST_HEAD(&n->list);
+	list_add_tail(&n->list, &gi->gi_net);
+	print_net_rule(KERN_INFO "Graphene: PID %d NET RULE %s\n", n);
+	return 0;
+}
+
+u32 gipc_get_session(struct task_struct *tsk)
+{
+	struct graphene_info *gi = get_graphene_info(tsk->graphene);
+	return gi ? gi->gi_gipc_session : 0;
+}
+
+int set_graphene(struct task_struct *current_tsk,
+		 const struct graphene_policies __user *gpolicies)
+{
+	int npolicies;
+	const struct graphene_user_policy __user *policies = gpolicies->policies;
+	struct graphene_info *gi;
+	struct graphene_user_policy ptmp;
+	struct graphene_path *p;
+	struct graphene_unix *u;
+	int i, rv = 0;
+	DEFINE_PATH_BUFFER(fn, kpath, max)
+#ifdef CONFIG_GRAPHENE_DEBUG
+	char *dp;
+#endif
+
+	rv = copy_from_user(&npolicies, &gpolicies->npolicies, sizeof(int));
+	if (rv < 0)
+		return -EFAULT;
+
+	if (npolicies && !policies)
+		return -EINVAL;
+
+#ifndef CONFIG_GRAPHENE_ISOLATE
+	if (current_tsk->graphene)
+		return -EAGAIN;
+
+	if (current_tsk != current_tsk->group_leader)
+		return -EPERM;
+#endif
+
+	gi = kmalloc(sizeof(struct graphene_info), GFP_KERNEL);
+	if (!gi)
+		return -ENOMEM;
+
+	GET_PATH_BUFFER(fn, kpath, max)
+	memset(gi, 0, sizeof(struct graphene_info));
+	INIT_LIST_HEAD(&gi->gi_paths);
+	INIT_LIST_HEAD(&gi->gi_rpaths);
+	INIT_LIST_HEAD(&gi->gi_net);
+	gi->gi_gipc_session = atomic_inc_return(&gipc_session);
+
+#ifdef CONFIG_GRAPHENE_DEBUG
+	printk(KERN_INFO "Graphene: PID %d GIPC SESSION %u\n",
+	       current_tsk->pid, gi->gi_gipc_session);
+#endif
+
+	for (i = 0 ; i < npolicies ; i++) {
+		int type, flags;
+		rv = copy_from_user(&ptmp, policies + i,
+				    sizeof(struct graphene_user_policy));
+		if (rv < 0)
+			goto err;
+
+		if (!ptmp.value) {
+			rv = -EINVAL;
+			goto err;
+		}
+
+		type = ptmp.type & ~(GRAPHENE_FS_READ | GRAPHENE_FS_WRITE);
+		flags = ptmp.type & ~type;
+
+		switch(type) {
+		case GRAPHENE_LIB_NAME:
+			rv = strncpy_from_user(kpath, ptmp.value, max);
+			if (rv < 0)
+				goto err;
+
+			rv = kern_path(kpath, LOOKUP_FOLLOW, &gi->gi_libexec);
+			if (rv)
+				goto err;
+#ifdef CONFIG_GRAPHENE_DEBUG
+			dp = d_path(&gi->gi_libexec, kpath, max);
+			if (IS_ERR(dp)) {
+				rv = -EINVAL;
+				goto err;
+			}
+			printk(KERN_INFO "Graphene: PID %d LIB NAME %s\n",
+			       current_tsk->pid, dp);
+#endif
+			break;
+
+		case GRAPHENE_LIB_ADDR:
+			gi->gi_libaddr = (u64) ptmp.value;
+#ifdef CONFIG_GRAPHENE_DEBUG
+			printk(KERN_INFO "Graphene: PID %d LIB ADDR 0x%016llx\n",
+			       current_tsk->pid, gi->gi_libaddr);
+#endif
+			break;
+
+		case GRAPHENE_UNIX_ROOT:
+			rv = strncpy_from_user(kpath, ptmp.value, max);
+			if (rv < 0)
+				goto err;
+
+			u = gi->gi_unix;
+			if (!u) {
+				u = kmalloc(sizeof(struct graphene_unix),
+				            GFP_KERNEL);
+				if (!u) {
+					rv = -ENOMEM;
+					goto err;
+				}
+
+				u->root.mnt = NULL;
+				u->prefix.len = 0;
+				atomic_set(&u->count, 1);
+				INIT_LIST_HEAD(&u->list);
+				gi->gi_unix = u;
+			}
+			if (u && u->root.mnt)
+				path_put(&u->root);
+
+			rv = kern_path(kpath, LOOKUP_FOLLOW, &u->root);
+			if (rv)
+				goto err;
+
+#ifdef CONFIG_GRAPHENE_DEBUG
+			dp = d_path(&u->root, kpath, max);
+			if (IS_ERR(dp)) {
+				rv = -EINVAL;
+				goto err;
+			}
+			printk(KERN_INFO "Graphene: PID %d UNIX ROOT %s\n",
+			       current_tsk->pid, dp);
+#endif
+			break;
+
+		case GRAPHENE_UNIX_PREFIX: {
+			char * prefix;
+
+			rv = strncpy_from_user(kpath, ptmp.value, max);
+			if (rv < 0)
+				goto err;
+
+			u = gi->gi_unix;
+			if (!u) {
+				u = kmalloc(sizeof(struct graphene_unix),
+				            GFP_KERNEL);
+				if (!u) {
+					rv = -ENOMEM;
+					goto err;
+				}
+
+				u->root.mnt = NULL;
+				u->prefix.len = 0;
+				atomic_set(&u->count, 1);
+				INIT_LIST_HEAD(&u->list);
+				gi->gi_unix = u;
+			}
+			if (u && u->prefix.len)
+				kfree(&u->prefix.name);
+
+			prefix = kmalloc(rv + 1, GFP_KERNEL);
+			if (!prefix) {
+				rv = -ENOMEM;
+				goto err;
+			}
+
+			memcpy(prefix, kpath, rv + 1);
+			u->prefix.len = rv;
+			u->prefix.name = prefix;
+
+#ifdef CONFIG_GRAPHENE_DEBUG
+			printk(KERN_INFO "Graphene: PID %d UNIX PREFIX %s\n",
+			       current_tsk->pid, kpath);
+#endif
+			break;
+		}
+
+		case GRAPHENE_NET_RULE: {
+			struct graphene_net_policy np;
+
+			rv = copy_from_user(&np, ptmp.value,
+					    sizeof(struct graphene_net_policy));
+			if (rv < 0)
+				goto err;
+
+			rv = set_net_rule(&np, gi);
+			if (rv < 0)
+				goto err;
+
+			break;
+		}
+
+		case GRAPHENE_FS_PATH:
+		case GRAPHENE_FS_RECURSIVE:
+			rv = strncpy_from_user(kpath, ptmp.value, max);
+			if (rv < 0)
+				goto err;
+
+			p = kmalloc(sizeof(struct graphene_path),
+				    GFP_KERNEL);
+			if (!p) {
+				rv = -ENOMEM;
+				goto err;
+			}
+
+			rv = kern_path(kpath, LOOKUP_FOLLOW, &p->path);
+			if (rv) {
+				kfree(p);
+				goto err;
+			}
+
+#ifdef CONFIG_GRAPHENE_DEBUG
+			dp = d_path(&p->path, kpath, max);
+			if (IS_ERR(dp)) {
+				rv = -EINVAL;
+				kfree(p);
+				goto err;
+			}
+			printk(KERN_INFO "Graphene: PID %d PATH %s%s\n",
+			       current_tsk->pid, dp,
+			       type == GRAPHENE_FS_PATH ? "" :
+			       " (recursive)");
+#endif
+			p->type = flags;
+			INIT_LIST_HEAD(&p->list);
+			list_add_tail(&p->list,
+				      type == GRAPHENE_FS_PATH ?
+				      &gi->gi_paths : &gi->gi_rpaths);
+			break;
+		}
+	}
+
+	if (!current_tsk->graphene) {
+		struct graphene_struct *gs;
+
+		if (gi->gi_unix) {
+			rv = add_graphene_unix(gi->gi_unix);
+			if (rv < 0)
+				goto err;
+		}
+
+		get_console(gi, current_tsk->files);
+
+		gs = kmalloc(sizeof(struct graphene_struct), GFP_KERNEL);
+		if (!gs) {
+			rv = -ENOMEM;
+			goto err;
+		}
+
+		atomic_set(&gs->g_count, 1);
+		gs->g_info = gi;
+		spin_lock_init(&gs->g_lock);
+		current_tsk->graphene = gs;
+		printk(KERN_INFO "Graphene: PID %d registered\n",
+		       current_tsk->pid);
+	}
+#ifdef CONFIG_GRAPHENE_ISOLATE
+	else {
+		if ((rv = update_graphene(current_tsk, gi)) < 0) {
+			printk(KERN_INFO "Graphene: PID %d cannot be updated (%d)\n",
+			       current_tsk->pid, rv);
+			goto err;
+		}
+
+		printk(KERN_INFO "Graphene: PID %d updated\n",
+		       current_tsk->pid);
+	}
+#endif
+	rv = 0;
+	goto out;
+err:
+	drop_graphene_info(gi);
+out:
+	PUT_PATH_BUFFER(fn, kpath)
+	return rv;
+}
+
+#ifdef CONFIG_GRAPHENE_ISOLATE
+static int do_close_sock(struct graphene_info *gi, struct socket *sock,
+			 int close_unix)
+{
+	struct sock *sk = sock->sk;
+	struct sockaddr_storage address;
+	struct sockaddr *addr = (void *) &address;
+	struct inet_sock *inet;
+	int len, err;
+
+	if (!sk)
+		return 0;
+
+	if (sk->sk_family == PF_UNIX)
+		return close_unix ? -EPERM : 0;
+
+	inet = inet_sk(sk);
+	if (inet->inet_dport) {
+		err = sock->ops->getname(sock, addr, &len, 1);
+		if (err < 0)
+			return err;
+
+		err = __common_net_perm(gi, OP_CONNECT, sock, addr, len);
+		if (err < 0)
+			return err;
+
+		return 0;
+	}
+
+	if (!inet->inet_num)
+		return 0;
+
+	if (sk->sk_state == TCP_LISTEN) {
+		err = __common_net_perm(gi, OP_LISTEN, sock, NULL, 0);
+	} else {
+		err = sock->ops->getname(sock, addr, &len, 0);
+		if (err < 0)
+			return err;
+
+		err = __common_net_perm(gi, OP_BIND, sock, addr, len);
+	}
+
+	return err;
+}
+
+static int do_close_fds(struct graphene_info *gi, struct files_struct *files,
+			int close_unix)
+{
+	int i, j;
+	struct fdtable *fdt = files_fdtable(files);
+	j = 0;
+
+	rcu_read_lock();
+	fdt = files_fdtable(files);
+	rcu_read_unlock();
+	for (;;) {
+		unsigned long set;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+		i = j * BITS_PER_LONG;
+#else
+		i = j * __NFDBITS;
+#endif
+		if (i >= fdt->max_fds)
+			break;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
+		set = fdt->open_fds[j++];
+#else
+		set = fdt->open_fds->fds_bits[j++];
+#endif
+		for ( ; set ; i++, set >>= 1) {
+			struct socket *sock = NULL;
+			struct file *file;
+			int err;
+
+			if (!(set & 1))
+				continue;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
+			sock = sockfd_lookup(i, &err);
+#endif
+
+			file = xchg(&fdt->fd[i], NULL);
+			if (!file)
+				continue;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+			sock = sock_from_file(file, &err);
+#endif
+
+			if (sock) {
+				err = do_close_sock(gi, sock, close_unix);
+				if (!err)
+					goto allow;
+				goto deny;
+			}
+
+			if (get_pipe_info(file))
+				goto deny;
+
+			err = __common_perm(gi, OP_OPEN, &file->f_path,
+					    aa_map_file_to_perms(file));
+
+			if (!err) {
+allow:
+				xchg(&fdt->fd[i], file);
+				continue;
+			}
+
+deny:
+			filp_close(file, files);
+			cond_resched();
+		}
+	}
+	return 0;
+}
+
+static
+int net_check (int family, int addr_any, int port_any,
+	       int flags1, struct graphene_net_addr * addr1,
+	       int flags2, struct graphene_net_addr * addr2)
+{
+	if (flags2 & addr_any)
+		goto port;
+	if (flags1 & addr_any)
+		goto port;
+	
+	switch (family) {
+	case AF_INET:
+		if (memcmp(&addr1->addr.sin_addr,
+			   &addr2->addr.sin_addr,
+			   sizeof(struct in_addr)))
+			return -EACCES;
+		break;
+	case AF_INET6:
+		if (memcmp(&addr1->addr.sin6_addr,
+			   &addr2->addr.sin6_addr,
+			   sizeof(struct in6_addr)))
+			return -EACCES;
+		break;
+	}
+
+port:
+	if (flags2 & port_any)
+		return 0;
+	if (flags1 & port_any)
+		return 0;
+
+	if (addr1->port_begin < addr2->port_begin ||
+	    addr1->port_end > addr2->port_end)
+		return -EACCES;
+
+	return 0;
+}
+
+static int update_graphene(struct task_struct *current_tsk,
+			   struct graphene_info *new)
+{
+	struct graphene_struct *gs = current_tsk->graphene;
+	struct graphene_info *gi = get_graphene_info(gs);
+	struct graphene_path *p;
+	struct graphene_net *n1, *n2;
+	int i = 0, close_unix = 0;
+
+	if (new->gi_unix) {
+		if (!new->gi_unix->root.mnt &&
+		    gi->gi_unix && gi->gi_unix->root.mnt) {
+			if (!path_equal(&new->gi_unix->root,
+					&gi->gi_unix->root))
+				return -EACCES;
+			path_get(&gi->gi_unix->root);
+			new->gi_unix->root = gi->gi_unix->root;
+		}
+		if (new->gi_unix->prefix.len) {
+			int err = add_graphene_unix(new->gi_unix);
+			if (err < 0)
+				return err;
+		}
+		close_unix = 1;
+	}
+
+	for (i = 0 ; i < 3 ; i++)
+		if (gi->gi_console[i].mnt) {
+			path_get(&gi->gi_console[i]);
+			new->gi_console[i] = gi->gi_console[i];
+		} else {
+			new->gi_console[i].mnt = NULL;
+		}
+
+	list_for_each_entry(p, &new->gi_paths, list) {
+		u32 mask = 0;
+		if (p->type & GRAPHENE_FS_READ)
+			mask |= MAY_READ;
+		if (p->type & GRAPHENE_FS_WRITE)
+			mask |= MAY_WRITE;
+		print_path(KERN_INFO "Graphene: PID %d CHECK RULE %s\n",
+			   &p->path);
+		if (__common_perm(gi, OP_OPEN, &p->path, mask) < 0)
+			return -EACCES;
+	}
+
+	list_for_each_entry(n1, &new->gi_net, list) {
+		bool accepted = false;
+		print_net_rule(KERN_INFO "Graphene: PID %d CHECK RULE %s\n",
+			       n1);
+		list_for_each_entry(n2, &gi->gi_net, list) {
+			if (n1->family != n2->family)
+				continue;
+
+			if (net_check(n1->family,
+				      LOCAL_ADDR_ANY, LOCAL_PORT_ANY,
+				      n1->flags, &n1->local,
+				      n2->flags, &n2->local) < 0)
+				continue;
+
+			if (net_check(n1->family,
+				      PEER_ADDR_ANY, PEER_PORT_ANY,
+				      n1->flags, &n1->peer,
+				      n2->flags, &n2->peer) < 0)
+				continue;
+
+			accepted = true;
+			print_net_rule(KERN_INFO "Graphene: PID %d ALLOW %s\n",
+				       n1);
+			break;
+		}
+
+		if (!accepted) {
+			print_net_rule(KERN_INFO "Graphene: PID %d DENY %s\n",
+				       n1);
+			return -EACCES;
+		}
+	}
+
+	spin_lock(&gs->g_lock);
+	put_graphene_info(gs->g_info);
+	gs->g_info = new;
+	spin_unlock(&gs->g_lock);
+
+	do_close_fds(new, current_tsk->files, close_unix);
+	return 0;
+}
+
+#endif /* CONFIG_GRAPHENE_ISOLATE */
+
+static long graphene_ioctl(struct file *file, unsigned int cmd,
+			   unsigned long arg)
+{
+	struct task_struct *current_tsk = current;
+
+	switch (cmd) {
+	case GRAPHENE_SET_TASK:
+		return set_graphene(current_tsk,
+			(const struct graphene_policies __user *) arg);
+	default:
+		return -ENOSYS;
+	}
+}
+
+static struct file_operations graphene_operations = {
+	.unlocked_ioctl	= graphene_ioctl,
+	.compat_ioctl	= graphene_ioctl,
+	.llseek		= noop_llseek,
+};
+
+static struct miscdevice graphene_dev = {
+	.minor		= GRAPHENE_MINOR,
+	.name		= "graphene",
+	.fops		= &graphene_operations,
+	.mode		= 0666,
+};
+
+static int __init graphene_init(void)
+{
+	int rv;
+
+	rv = misc_register(&graphene_dev);
+	if (rv) {
+		printk(KERN_ERR "Graphene error: "
+		       "failed to add a char device (rv=%d)\n", rv);
+		return rv;
+	}
+
+	return 0;
+}
+
+device_initcall(graphene_init);

+ 180 - 0
Pal/linux-3.14/graphene/graphene.h

@@ -0,0 +1,180 @@
+#ifndef _LINUX_GRAPHENE_H
+#define _LINUX_GRAPHENE_H
+
+#include <linux/ioctl.h>
+#include <linux/in.h>
+#include <linux/in6.h>
+
+#define GRAPHENE_FILE   "/dev/graphene"
+#define GRAPHENE_MINOR		239
+
+/* symbolic link this header file in include/linux */
+
+/* This header needs to be included in include/linux/sched.h */
+
+#ifndef __KERNEL__
+# ifdef __user
+#  undef __user
+# endif
+# define __user
+#endif
+
+#define GRAPHENE_LIB_NAME	0x01
+#define GRAPHENE_LIB_ADDR	0x02
+#define GRAPHENE_UNIX_ROOT	0x03
+#define GRAPHENE_UNIX_PREFIX	0x04
+#define GRAPHENE_NET_RULE	0x05
+#define GRAPHENE_FS_PATH	0x06
+#define GRAPHENE_FS_RECURSIVE	0x07
+#define GRAPHENE_FS_READ	0x10
+#define GRAPHENE_FS_WRITE	0x20
+
+struct graphene_user_policy {
+	int			type;
+	const void __user *	value;
+};
+
+struct graphene_net_addr {
+	union {
+		struct in_addr 		sin_addr;
+		struct in6_addr		sin6_addr;
+	} addr;
+	unsigned short		port_begin;
+	unsigned short		port_end;
+};
+
+struct graphene_net_policy {
+	unsigned short			family;
+	struct graphene_net_addr	local, peer;
+};
+
+#define GRAPHENE_SET_TASK	_IO('k', 16)
+
+struct graphene_policies {
+	int				npolicies;
+	struct graphene_user_policy	policies[];
+};
+
+#ifdef __KERNEL__
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/net.h>
+#include <linux/path.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/dcache.h>
+#include <linux/rcupdate.h>
+
+struct task_struct;
+struct path;
+struct qstr;
+
+struct graphene_path {
+	struct list_head	list;
+	struct path		path;
+	int			type;
+};
+
+#define LOCAL_ADDR_ANY		0x1
+#define LOCAL_PORT_ANY		0x2
+#define PEER_ADDR_ANY		0x4
+#define PEER_PORT_ANY		0x8
+
+struct graphene_net {
+	struct list_head	list;
+	short			family;
+	unsigned char		flags;
+	struct graphene_net_addr	local, peer;
+};
+
+struct graphene_unix {
+	atomic_t		count;
+	struct list_head	list;
+	struct path		root;
+	struct qstr		prefix;
+};
+
+/*
+ * add the following line to struct task_struct (include/linux/sched.h):
+ * 	struct graphene_struct *graphene;
+ */
+struct graphene_info {
+	atomic_t		gi_count;
+	struct path		gi_libexec;
+	u64			gi_libaddr;
+	struct path		gi_console[3];
+	struct graphene_unix *	gi_unix;
+	struct list_head	gi_paths;
+	struct list_head	gi_rpaths;
+	struct list_head	gi_net;
+	u32			gi_gipc_session;
+};
+
+struct graphene_struct {
+	atomic_t g_count;
+	struct graphene_info __rcu *g_info;
+	spinlock_t g_lock ____cacheline_aligned_in_smp;
+};
+
+#define GRAPHENE_ENABLED()	(current->graphene != NULL)
+
+/* use this function in __put_task_struct (kernel/fork.c) */
+int dup_graphene_struct(struct task_struct *task);
+
+/* use this function in dup_task_struct (kernel/fork.c) */
+void put_graphene_struct(struct task_struct *task);
+
+/* add the following lines to common_perm (security/apparmor/lsm.c):
+ * (when current->in_execve is true)
+ * if (GRAPHNEE_ENABLED() && (error = graphene_execve_open(file))
+ * 	return error;
+ */
+int graphene_execve_open(struct file *file);
+
+/*
+ * add the following lines to common_perm (security/apparmor/lsm.c):
+ * if (GRAPHENE_ENABLED() &&
+ *     (error = graphene_common_perm(op, path, mask)))
+ * 	return error;
+ *
+ * add the following lines to apparmor_dentry_open (security/apparmor/lsm.c):
+ * if (GRAPHENE_ENABLED() &&
+ *     (error = graphene_common_perm(OP_OPEN, &file->path, mask)))
+ * 	return error;
+ */
+int graphene_common_perm(int op, struct path *path, u32 mask);
+
+/*
+ * add the following lines to the initializer of apparmor_ops
+ * (security/apparmor/lsm.c):
+ * 	task_kill =			graphene_task_kill,
+ */
+int graphene_task_kill(struct task_struct *task, struct siginfo *info,
+		       int sig, u32 secid);
+
+/*
+ * add the following lines to the initializer of apparmor_ops
+ * (security/apparmor/lsm.c):
+ * 	socket_bind =			graphene_socket_bind,
+ * 	socket_listen =			graphene_socket_listen,
+ * 	socket_connect =		graphene_socket_connect,
+ * 	socket_sendmsg =		graphene_socket_sendmsg,
+ * 	socket_recvmsg =		grapheen_socket_recvmsg,
+ */
+int graphene_socket_bind(struct socket *sock,
+			 struct sockaddr *address, int addrlen);
+
+int graphene_socket_listen(struct socket *sock, int backlog);
+int graphene_socket_connect(struct socket *sock,
+			    struct sockaddr *address, int addrlen);
+int graphene_socket_sendmsg(struct socket *sock,
+			    struct msghdr *msg, int size);
+int graphene_socket_recvmsg(struct socket *sock,
+			    struct msghdr *msg, int size, int flags);
+
+u32 gipc_get_session(struct task_struct *tsk);
+
+#endif /* __KERNEL__ */
+
+#endif

+ 1 - 0
Pal/linux-3.14/graphene/my_mmap.h

@@ -0,0 +1 @@
+../../ipc/linux/my_mmap.h

+ 1 - 0
Pal/linux-3.14/graphene/my_tlb.h

@@ -0,0 +1 @@
+../../ipc/linux/my_tlb.h

+ 2 - 8
Pal/src/Makefile

@@ -18,7 +18,7 @@ pal_target = libpal.a libpal.so
 
 include host/$(OS)/Makefile.am
 
-defs	= -DIN_PAL -DSRCDIR="$(PWD)/"
+defs	= -DIN_PAL
 objs	= $(addprefix db_,streams memory threading semaphore events process \
 	    object main misc ipc exception rtld) slab printf
 graphene_lib = ../lib/graphene-lib.a
@@ -46,12 +46,10 @@ security:
 libpal.so: $(addsuffix .o,$(objs)) $(filter %.map %.lds,$(LDFLAGS)) \
 	   $(host_lib) $(graphene_lib)
 	@echo [ $@ ]
-	@[ ! -f $@ ] || mv -f $@ $@.backup
 	@$(LD) $(LDFLAGS) -o $@ $(filter-out %.map %.lds,$^) -soname=$@
 
 libpal.a: $(addsuffix .o,$(objs)) $(host_lib) $(graphene_lib)
 	@echo [ $@ ]
-	@[ ! -f $@ ] || mv -f $@ $@.backup
 	@$(AR) $(ARFLAGS) $@ $^
 
 %.asm: %.c $(headers)
@@ -68,10 +66,6 @@ libpal.a: $(addsuffix .o,$(objs)) $(host_lib) $(graphene_lib)
 	@$(CC) $(CFLAGS) $(defs) -E $< -o $@
 
 clean:
-	rm -rf $(addsuffix .o,$(objs))
-	for f in $(pal_target); \
-	do \
-		[ ! -f $$f ] || mv -f $$f $$f.backup || true; \
-	done
+	rm -f $(addsuffix .o,$(objs)) $(pal_target)
 	@[ ! -d host/$(OS) ] || make -C host/$(OS) clean
 	@[ ! -d security/$(OS) ] || make -C security/$(OS) clean

+ 0 - 2
Pal/src/db_rtld.c

@@ -38,8 +38,6 @@
 #include <elf/elf.h>
 #include <bits/dlfcn.h>
 
-DEFINE_GDB_SCRIPT_IN_SRCDIR("pal-gdb.py")
-
 struct link_map * loaded_libraries = NULL;
 struct link_map * rtld_map = NULL;
 struct link_map * exec_map = NULL;

+ 2 - 7
Pal/src/host/Linux/Makefile

@@ -16,7 +16,7 @@ ARFLAGS	=
 
 host_target = libpal-Linux.a
 
-defs	= -DIN_PAL -DSRCDIR="$(PWD)/"
+defs	= -DIN_PAL -DGDB_SCRIPT="$(CURDIR)/pal-gdb.py"
 objs	= $(addprefix db_,files devices pipes sockets streams memory threading \
 	    semaphore mutex events process object main rtld misc ipc \
 	    exception) manifest clone-x86_64 gettimeofday-x86_64
@@ -35,7 +35,6 @@ $(graphene_lib):
 
 libpal-Linux.a: $(addsuffix .o,$(objs)) $(graphene_lib)
 	@echo [ host/Linux/$@ ]
-	@[ ! -f $@ ] || mv -f $@ $@.backup
 	@$(AR) $(ARFLAGS) $@ $^
 
 %.asm: %.c $(headers)
@@ -60,8 +59,4 @@ libpal-Linux.a: $(addsuffix .o,$(objs)) $(graphene_lib)
 	@$(AS) $(ASFLAGS) $(defs) -E $< -o $@
 
 clean:
-	rm -rf $(addsuffix .o,$(objs))
-	for f in $(host_target); \
-	do \
-		[ ! -f $$f ] || mv -f $$f $$f.backup || true; \
-	done
+	rm -f $(addsuffix .o,$(objs)) $(host_target)

+ 5 - 0
Pal/src/host/Linux/db_main.c

@@ -54,6 +54,11 @@ asm ("pal_start: \n"
      "  movq %rsp, %rdi \n"
      "  call pal_linux_main \n");
 
+asm (".pushsection \".debug_gdb_scripts\", \"MS\",@progbits,1\r\n"
+     ".byte 1\r\n"
+     ".asciz \"" XSTRINGIFY(GDB_SCRIPT) "\"\r\n"
+     ".popsection\r\n");
+
 struct pal_linux_config pal_linux_config;
 
 static size_t pagesz = PRESET_PAGESIZE;

+ 2 - 1
Pal/src/host/Linux/db_process.c

@@ -174,7 +174,8 @@ int _DkProcessCreate (PAL_HANDLE * handle, const char * uri,
                               pal_config.environments);
 
         /* shouldn't get to here */
-        INLINE_SYSCALL(exit_group, 0);
+        printf("unexpected failure of new process\n");
+        asm("hlt");
         return 0;
     }
 

+ 5 - 7
Pal/src/pal-gdb.py → Pal/src/host/Linux/pal-gdb.py

@@ -3,15 +3,13 @@
 import os, sys, gdb
 
 if len(gdb.inferiors()) == 1:
-    print "Are you loading the script [Y]/n ? ",
+    gdb.execute("set auto-load off")
+    sys.stdout.write("Are you loading the script [Y]/n ? ")
+    sys.stdout.flush()
     ans = sys.stdin.readline()
 
-    if ans[0] == 'n' or ans[0] == 'N':
-        gdb.execute("set detach-on-fork on")
-        gdb.execute("set follow-fork-mode child")
-
-    else:
+    if ans[0] != 'n' and ans[0] != 'N':
         gdbfile = os.path.dirname(__file__) + "/pal.gdb"
         gdb.execute("set env IN_GDB = 1")
         gdb.execute("source " + gdbfile)
-        print "script",  gdbfile, "loaded"
+        sys.stdout.write("script %s loaded\n" % gdbfile)

+ 36 - 0
Pal/src/host/Linux/pal.gdb

@@ -0,0 +1,36 @@
+handle SIGCONT pass noprint nostop
+handle SIGKILL pass print stop
+
+set disable-randomization off
+set detach-on-fork off
+set schedule-multiple on
+set follow-exec-mode same
+set follow-fork-mode child
+
+catch vfork
+commands
+	echo [A child process created]\n
+	set scheduler-locking on
+	continue
+end
+
+catch fork
+commands
+	echo [A child process created]\n
+	set scheduler-locking on
+	continue
+end
+
+catch exec
+commands
+	echo [Child process begin running]\n
+	set scheduler-locking off
+	continue
+end
+
+define hook-stop
+	if $_thread == 0
+		echo [Child process exited]\n
+		info inferior
+	end
+end

+ 1 - 1
Pal/src/host/Linux/pal_linux.h

@@ -71,7 +71,7 @@ extern struct pal_linux_config {
 #endif
 
 #define ARCH_FORK() INLINE_SYSCALL(clone, 4, CLONE_CHILD_SETTID, 0, \
-                                   NULL, &pal_config.pid)
+                                   NULL, &pal_linux_config.pid)
 
 #define ARCH_VFORK() INLINE_SYSCALL(clone, 4, CLONE_VM|CLONE_VFORK, 0, \
                                     NULL, NULL)

+ 1 - 6
Pal/src/host/Skeleton/Makefile

@@ -43,7 +43,6 @@ $(graphene_lib):
 
 libpal-Skeleton.a: $(addsuffix .o,$(objs)) $(graphene_lib)
 	@echo [ $@ ]
-	@[ ! -f $@ ] || mv -f $@ $@.backup
 	@$(AR) $(ARFLAGS) $@ $^
 
 %.asm: %.c $(headers)
@@ -68,8 +67,4 @@ libpal-Skeleton.a: $(addsuffix .o,$(objs)) $(graphene_lib)
 	@$(AS) $(ASFLAGS) $(defs) -E $< -o $@
 
 clean:
-	rm -rf $(addsuffix .o,$(objs))
-	for f in $(host_target); \
-	do \
-		[ ! -f $$f ] || mv -f $$f $$f.backup || true; \
-	done
+	rm -f $(addsuffix .o,$(objs)) $(host_target)

+ 0 - 17
Pal/src/pal.gdb

@@ -1,17 +0,0 @@
-handle SIGCONT pass noprint nostop
-handle SIGKILL pass print stop
-
-set disable-randomization off
-set detach-on-fork off
-set schedule-multiple on
-set follow-exec-mode same
-set follow-fork-mode child
-
-define hook-continue
-  inferior 1
-end
-
-if $_thread == 0
-  tbreak pal_main
-  run
-end

+ 0 - 13
Pal/src/pal_debug.h

@@ -52,19 +52,6 @@ void __assert (void);
         }                                                                \
     } while (0)
 
-#define DEFINE_GDB_SCRIPT(script_name)                                  \
-    asm (".pushsection \".debug_gdb_scripts\", \"MS\",@progbits,1\r\n"  \
-         ".byte 1\r\n"                                                  \
-         ".asciz \"" script_name "\"\r\n"                               \
-         ".popsection\r\n");
-
-#define DEFINE_GDB_SCRIPT_IN_DIR(dir, script_name)  \
-    DEFINE_GDB_SCRIPT_IN_DIR2(dir, script_name)
-#define DEFINE_GDB_SCRIPT_IN_DIR2(dir, script_name)  \
-    DEFINE_GDB_SCRIPT(#dir script_name)
-#define DEFINE_GDB_SCRIPT_IN_SRCDIR(script_name)    \
-    DEFINE_GDB_SCRIPT_IN_DIR(SRCDIR, script_name)
-
 #else
 
 int pal_printf  (const char *fmt, ...);

+ 3 - 3
README

@@ -38,9 +38,9 @@ contact us with a detailed bug report.
 
 The following packages are required for building Graphene: (can be installed
 with 'apt-get install')
-   - Build-essential
-   - Autoconf
-   - Gawk
+   - build-essential
+   - autoconf
+   - gawk
 
 To build the system, simply run the following commands in the root of the
 source tree: