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 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)                          \
 #define create_lock(l)                          \
     do {                                        \
     do {                                        \
@@ -511,7 +510,7 @@ static inline void __lock (LOCKTYPE * l)
 #endif
 #endif
 
 
     while (!DkObjectsWaitAny(1, &l->lock, NO_TIMEOUT));
     while (!DkObjectsWaitAny(1, &l->lock, NO_TIMEOUT));
-
+    l->owner = tcb->tid;
 #if DEBUG_LOCK == 1
 #if DEBUG_LOCK == 1
     debug("lock(%s=%p) by %s:%d\n", name, l, file, line);
     debug("lock(%s=%p) by %s:%d\n", name, l, file, line);
 #endif
 #endif
@@ -535,10 +534,22 @@ static inline void __unlock (LOCKTYPE * l)
     debug("unlock(%s=%p) %s:%d\n", name, l, file, line);
     debug("unlock(%s=%p) %s:%d\n", name, l, file, line);
 #endif
 #endif
 
 
+    l->owner = 0;
     DkSemaphoreRelease(l->lock, 1);
     DkSemaphoreRelease(l->lock, 1);
     enable_preempt(tcb);
     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
 #define DEBUG_MASTER_LOCK       0
 
 
 extern LOCKTYPE __master_lock;
 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 {
 typedef struct shim_lock {
     PAL_HANDLE lock;
     PAL_HANDLE lock;
-    //IDTYPE owner;
-    //unsigned int reowned;
+    IDTYPE owner;
 } LOCKTYPE;
 } LOCKTYPE;
 
 
 typedef struct shim_aevent {
 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)) \
 libsysdb.so: $(addsuffix .o,$(objs)) $(filter %.map %.lds,$(LDFLAGS)) \
 	     $(graphene_lib) $(pal_lib)
 	     $(graphene_lib) $(pal_lib)
 	@echo [ $@ ]
 	@echo [ $@ ]
-	@mv -f $@ $@.backup || true
 	$(LD) $(LDFLAGS) -o $@ $(filter-out %.map %.lds,$^) -soname $@ \
 	$(LD) $(LDFLAGS) -o $@ $(filter-out %.map %.lds,$^) -soname $@ \
 		-e shim_start
 		-e shim_start
 
 
@@ -69,7 +68,6 @@ libsysdb_debug.so: $(addsuffix .o,$(objs)) \
 		   $(filter %.map %.lds,$($LDFLAGS-debug)) \
 		   $(filter %.map %.lds,$($LDFLAGS-debug)) \
 		   $(graphene_lib) $(pal_lib)
 		   $(graphene_lib) $(pal_lib)
 	@echo [ $@ ]
 	@echo [ $@ ]
-	@mv -f $@ $@.backup || true
 	$(LD) $(LDFLAGS-debug) -o $@ $(filter-out %.map %.lds,$^) -soname $@ \
 	$(LD) $(LDFLAGS-debug) -o $@ $(filter-out %.map %.lds,$^) -soname $@ \
 		-e shim_start
 		-e shim_start
 
 
@@ -103,8 +101,4 @@ $(addsuffix .o,$(addprefix ipc/shim_ipc_,$(ipcns))): ipc/*.h
 	@$(AS) $(ASFLAGS) $(defs) -E $< -o $@
 	@$(AS) $(ASFLAGS) $(defs) -E $< -o $@
 
 
 clean:
 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);
     ADD_FUNC_ENTRY(new_thread);
 
 
     __libc_tcb_t * tcb = thread->tcb;
     __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_OFFSET(sizeof(__libc_tcb_t));
         ADD_ENTRY(ADDR, base + *offset);
         ADD_ENTRY(ADDR, base + *offset);
         if (!dry) {
         if (!dry) {

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

@@ -156,7 +156,7 @@ void __del_dcache (struct shim_dentry * dent)
 #endif
 #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)
 void del_dcache (struct shim_dentry * dent)
 {
 {
@@ -199,13 +199,13 @@ kill:   {
             dent->parent = NULL;
             dent->parent = NULL;
             dent = parent;
             dent = parent;
 
 
-            if (__put_dentry(dent, false))
+            if (__internal_put_dentry(dent))
                 break;
                 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);
     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);
           qstrgetstr(&dent->rel_path), count);
 #endif
 #endif
 
 
-    if (count || !dput)
-        return count;
-
-    __dput_dentry(dent);
-    return 0;
+    return count;
 }
 }
 
 
 void get_dentry (struct shim_dentry * dent)
 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)
 void put_dentry (struct shim_dentry * dent)
 {
 {
-    if (__put_dentry(dent, false))
+    if (__internal_put_dentry(dent))
         return;
         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,
 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
 /* check permission of a dentry. If force is not set, permission
    is consider granted on invalid dentries */
    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)
 int permission (struct shim_dentry * dent, int mask, bool force)
 {
 {
     mode_t mode = 0;
     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 */
 /* 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,
 int lookup_dentry (struct shim_dentry * parent, const char * name, int namelen,
                    bool force, struct shim_dentry ** new)
                    bool force, struct shim_dentry ** new)
 {
 {
@@ -149,7 +149,7 @@ out:
 static void path_reacquire (struct lookup * look, struct shim_dentry * dent);
 static void path_reacquire (struct lookup * look, struct shim_dentry * dent);
 
 
 /* looking up single dentry, but use struct lookup */
 /* 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,
 static int do_lookup (struct lookup * look, const char * name, int namelen,
                       bool force)
                       bool force)
 {
 {
@@ -170,6 +170,7 @@ fail:
 
 
 static int link_path_walk (const char * name, struct lookup * look);
 static int link_path_walk (const char * name, struct lookup * look);
 
 
+/* have dcache_lock acquired */
 void path_acquire (struct lookup * look)
 void path_acquire (struct lookup * look)
 {
 {
     if (look->dentry)
     if (look->dentry)
@@ -179,6 +180,7 @@ void path_acquire (struct lookup * look)
         get_mount(look->mount);
         get_mount(look->mount);
 }
 }
 
 
+/* have dcache_lock acquired */
 void path_release (struct lookup * look)
 void path_release (struct lookup * look)
 {
 {
     if (look->dentry)
     if (look->dentry)
@@ -188,6 +190,7 @@ void path_release (struct lookup * look)
         put_mount(look->mount);
         put_mount(look->mount);
 }
 }
 
 
+/* have dcache_lock acquired */
 static void path_reacquire (struct lookup * look, struct shim_dentry * dent)
 static void path_reacquire (struct lookup * look, struct shim_dentry * dent)
 {
 {
     struct shim_dentry * old_dent = look->dentry;
     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 */
 /* 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)
 static inline int __do_follow_link (struct lookup * look)
 {
 {
     int err = 0;
     int err = 0;
@@ -245,7 +248,7 @@ out:
 }
 }
 
 
 /* follow links on a dentry until the last target */
 /* 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)
 static int follow_link (struct lookup * look)
 {
 {
     int err = 0;
     int err = 0;
@@ -269,7 +272,7 @@ static int follow_link (struct lookup * look)
 }
 }
 
 
 /* follow a single dot-dot to the parent */
 /* follow a single dot-dot to the parent */
-/* have dcache_lock acquired (write) */
+/* have dcache_lock acquired */
 static int follow_dotdot (struct lookup * look)
 static int follow_dotdot (struct lookup * look)
 {
 {
     struct shim_dentry * dent = look->dentry;
     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,
 /* walk through a absolute path based on current lookup structure,
    across mount point, dot dot and symlinks */
    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)
 static int link_path_walk (const char * name, struct lookup * look)
 {
 {
     struct shim_dentry * dent = NULL;
     struct shim_dentry * dent = NULL;
@@ -503,7 +506,7 @@ static int path_lookup_dcache (struct shim_dentry * start, const char * path,
     return 0;
     return 0;
 }
 }
 
 
-/* have dcache_lock acquired (write) */
+/* have dcache_lock acquired */
 static int path_lookup_walk (struct shim_dentry * start,
 static int path_lookup_walk (struct shim_dentry * start,
                              const char * name, int flags,
                              const char * name, int flags,
                              struct lookup * look,
                              struct lookup * look,
@@ -578,6 +581,7 @@ out_if:
         else
         else
             put_dentry(found);
             put_dentry(found);
     }
     }
+
     return 0;
     return 0;
 }
 }
 
 
@@ -591,44 +595,42 @@ int path_lookupat (struct shim_dentry * start, const char * path, int flags,
     struct lookup look;
     struct lookup look;
 
 
     lock(dcache_lock);
     lock(dcache_lock);
+
     ret = path_lookup_dcache(start, path, flags, &found, cur_thread);
     ret = path_lookup_dcache(start, path, flags, &found, cur_thread);
-    unlock(dcache_lock);
 
 
-    if (ret < 0)
+    if (ret < 0) {
+        unlock(dcache_lock);
         return ret;
         return ret;
+    }
 
 
     if (!found) {
     if (!found) {
-        lock(dcache_lock);
-
         if ((ret = path_lookup_walk(start, path, flags, &look,
         if ((ret = path_lookup_walk(start, path, flags, &look,
                                     cur_thread)) < 0)
                                     cur_thread)) < 0)
-            goto out_if;
+            goto out;
 
 
         get_dentry(look.dentry);
         get_dentry(look.dentry);
         found = look.dentry;
         found = look.dentry;
 
 
         if (flags & LOOKUP_SYNC) {
         if (flags & LOOKUP_SYNC) {
             if ((ret = __do_lookup_dentry(found, true)) < 0)
             if ((ret = __do_lookup_dentry(found, true)) < 0)
-                goto out_dentry;
+                goto out_release;
         }
         }
 
 
         if (found->state & DENTRY_NEGATIVE &&
         if (found->state & DENTRY_NEGATIVE &&
             !(flags & LOOKUP_CREATE)) {
             !(flags & LOOKUP_CREATE)) {
             ret = -ENOENT;
             ret = -ENOENT;
-            goto out_dentry;
+            goto out_release;
         }
         }
 
 
         if (!(found->state & DENTRY_NEGATIVE) &&
         if (!(found->state & DENTRY_NEGATIVE) &&
             !(found->state & DENTRY_ISDIRECTORY) &&
             !(found->state & DENTRY_ISDIRECTORY) &&
             flags & LOOKUP_DIRECTORY) {
             flags & LOOKUP_DIRECTORY) {
             ret = -ENOTDIR;
             ret = -ENOTDIR;
-            goto out_dentry;
+            goto out_release;
         }
         }
 
 
-out_dentry:
+out_release:
         path_release(&look);
         path_release(&look);
-out_if:
-        unlock(dcache_lock);
     }
     }
 
 
     if (found) {
     if (found) {
@@ -637,6 +639,9 @@ out_if:
         else
         else
             put_dentry(found);
             put_dentry(found);
     }
     }
+
+out:
+    unlock(dcache_lock);
     return ret;
     return ret;
 }
 }
 
 
@@ -726,7 +731,6 @@ int open_namei (struct shim_handle * hdl, struct shim_dentry * start,
 #endif
 #endif
 
 
     BEGIN_PROFILE_INTERVAL();
     BEGIN_PROFILE_INTERVAL();
-
     lock(dcache_lock);
     lock(dcache_lock);
 
 
     err = path_lookup_dcache(start, path, lookup_flags|LOOKUP_OPEN,
     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);
             get_mount(look.mount);
     }
     }
 
 
-    unlock(dcache_lock);
     SAVE_PROFILE_INTERVAL(path_lookup_dcache_for_open_namei);
     SAVE_PROFILE_INTERVAL(path_lookup_dcache_for_open_namei);
 
 
     if (err < 0) {
     if (err < 0) {
+        unlock(dcache_lock);
         SAVE_PROFILE_INTERVAL(end_open_namei);
         SAVE_PROFILE_INTERVAL(end_open_namei);
         return err;
         return err;
     }
     }
@@ -763,31 +767,25 @@ int open_namei (struct shim_handle * hdl, struct shim_dentry * start,
             goto exit;
             goto exit;
         }
         }
 
 
-        goto do_open;
+        goto do_open_locked;
     }
     }
 
 
-    lock(dcache_lock);
-
     /* no create, just look it up. */
     /* no create, just look it up. */
     if (!(flags & O_CREAT)) {
     if (!(flags & O_CREAT)) {
         err = path_lookup_walk(start, path, lookup_flags|LOOKUP_OPEN,
         err = path_lookup_walk(start, path, lookup_flags|LOOKUP_OPEN,
                                &look, cur_thread);
                                &look, cur_thread);
-
-        unlock(dcache_lock);
         SAVE_PROFILE_INTERVAL(path_lookup_walk_for_open_namei);
         SAVE_PROFILE_INTERVAL(path_lookup_walk_for_open_namei);
-
         if (err) {
         if (err) {
             debug("path_lookup error in open_namei\n");
             debug("path_lookup error in open_namei\n");
-            SAVE_PROFILE_INTERVAL(end_open_namei);
             goto exit;
             goto exit;
         }
         }
 
 
+do_open_locked:
+        unlock(dcache_lock);
 do_open:
 do_open:
         if ((err = permission(look.dentry, acc_mode, true)) < 0)
         if ((err = permission(look.dentry, acc_mode, true)) < 0)
             goto exit;
             goto exit;
-
         SAVE_PROFILE_INTERVAL(open_namei_permission);
         SAVE_PROFILE_INTERVAL(open_namei_permission);
-
         if (hdl) {
         if (hdl) {
             if (look.dentry->state & DENTRY_ISDIRECTORY) {
             if (look.dentry->state & DENTRY_ISDIRECTORY) {
                 assert(flags & O_DIRECTORY);
                 assert(flags & O_DIRECTORY);
@@ -811,33 +809,22 @@ do_open:
 
 
     SAVE_PROFILE_INTERVAL(path_lookup_walk_2_for_open_namei);
     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;
         goto exit;
-    }
-
-    if (look.last_type != LAST_NORM) {
-        unlock(dcache_lock);
-        goto exit;
-    }
 
 
     struct shim_dentry * new = NULL;
     struct shim_dentry * new = NULL;
     dir = look.dentry;
     dir = look.dentry;
     err = lookup_dentry(dir, look.last, strlen(look.last), true, &new);
     err = lookup_dentry(dir, look.last, strlen(look.last), true, &new);
-    unlock(dcache_lock);
-
     SAVE_PROFILE_INTERVAL(open_namei_lookup_2);
     SAVE_PROFILE_INTERVAL(open_namei_lookup_2);
-
     if (err < 0 && (err != -ENOENT || !new))
     if (err < 0 && (err != -ENOENT || !new))
         goto exit;
         goto exit;
 
 
     path_reacquire(&look, new);
     path_reacquire(&look, new);
-
     SAVE_PROFILE_INTERVAL(open_namei_path_reacquire);
     SAVE_PROFILE_INTERVAL(open_namei_path_reacquire);
 
 
 do_creat:
 do_creat:
     assert(dir);
     assert(dir);
+    unlock(dcache_lock);
 
 
     /* negative dentry */
     /* negative dentry */
     if (look.dentry->state & DENTRY_NEGATIVE) {
     if (look.dentry->state & DENTRY_NEGATIVE) {
@@ -894,6 +881,9 @@ done:
 
 
     path_release(&look);
     path_release(&look);
 
 
+    if (locked(dcache_lock))
+        unlock(dcache_lock);
+
     SAVE_PROFILE_INTERVAL(end_open_namei);
     SAVE_PROFILE_INTERVAL(end_open_namei);
     return 0;
     return 0;
 
 
@@ -903,6 +893,9 @@ exit:
     if (dir)
     if (dir)
         put_dentry(dir);
         put_dentry(dir);
 
 
+    if (locked(dcache_lock))
+        unlock(dcache_lock);
+
     SAVE_PROFILE_INTERVAL(end_open_namei);
     SAVE_PROFILE_INTERVAL(end_open_namei);
     return err;
     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_VM|CLONE_FILES|
                       CLONE_FS|CLONE_SIGHAND|CLONE_THREAD|
                       CLONE_FS|CLONE_SIGHAND|CLONE_THREAD|
                       CLONE_DETACHED| // Unused
                       CLONE_DETACHED| // Unused
-                      CLONE_SYSVSEM)) == 0);
+#ifdef CLONE_PTRACE
+                      CLONE_PTRACE| // Unused
+#endif
+                      CLONE_SYSVSEM|CSIGNAL)) == 0);
 
 
     new_args->create_event = DkNotificationEventCreate(0);
     new_args->create_event = DkNotificationEventCreate(0);
     if (!new_args->create_event) {
     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)
     if (bufsize <= 0)
         return -EINVAL;
         return -EINVAL;
 
 
+    /* The correct behavior is to return -EINVAL if file is not a
+       symbolic link */
+    return -EINVAL;
+
+#if 0
     int ret;
     int ret;
     struct shim_dentry * dent = NULL;
     struct shim_dentry * dent = NULL;
 
 
@@ -128,4 +133,5 @@ int shim_do_readlink (const char * file, char * buf, int bufsize)
     memcpy(buf, relpath, len);
     memcpy(buf, relpath, len);
     put_dentry(dent);
     put_dentry(dent);
     return len;
     return len;
+#endif
 }
 }

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

@@ -1,6 +1,6 @@
 apps = lmbench gcc busybox lighttpd bash apache make
 apps = lmbench gcc busybox lighttpd bash apache make
 
 
-targets = pal build-all
+targets = pal
 clean-extra = clean-all
 clean-extra = clean-all
 
 
 level = ../
 level = ../
@@ -22,7 +22,7 @@ libpal.so:
 	make pal
 	make pal
 
 
 build-all:
 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:
 clean-all:
 	for f in $(apps); do (cd $$f; make clean; cd ..); done
 	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_GEN = 3.x
-LINUX_SRC = linux-3.5
+LINUX_SRC = linux-3.14
 SRC_DIR = src
 SRC_DIR = src
 TEST_DIR = test
 TEST_DIR = test
 DIRS = ${SRC_DIR} ${TEST_DIR} $(LINUX_SRC)
 DIRS = ${SRC_DIR} ${TEST_DIR} $(LINUX_SRC)
@@ -35,7 +35,16 @@ $(LINUX_SRC)/Makefile:
 	[ ! -f $(LINUX_SRC).patch ] || git apply $(LINUX_SRC).patch
 	[ ! -f $(LINUX_SRC).patch ] || git apply $(LINUX_SRC).patch
 
 
 $(LINUX_SRC)/.config:
 $(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:
 clean:
 	for d in ${SRC_DIR} $(TEST_DIR) $(LINUX_SRC); \
 	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. 
 		 * vma.  Correct if not. 
 		 */
 		 */
 #if defined(CONFIG_GRAPHENE_BULK_IPC) || LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
 #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
 #else
 		{
 		{
 			unsigned long populate;
 			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 */
 #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) {
 		if (!my_addr) {
 			printk(KERN_ERR
 			printk(KERN_ERR

+ 1 - 2
Pal/lib/Makefile

@@ -30,5 +30,4 @@ graphene-lib.a: $(objs)
 	@$(CC) $(CFLAGS) -c $< -o $@
 	@$(CC) $(CFLAGS) -c $< -o $@
 
 
 clean:
 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
 include host/$(OS)/Makefile.am
 
 
-defs	= -DIN_PAL -DSRCDIR="$(PWD)/"
+defs	= -DIN_PAL
 objs	= $(addprefix db_,streams memory threading semaphore events process \
 objs	= $(addprefix db_,streams memory threading semaphore events process \
 	    object main misc ipc exception rtld) slab printf
 	    object main misc ipc exception rtld) slab printf
 graphene_lib = ../lib/graphene-lib.a
 graphene_lib = ../lib/graphene-lib.a
@@ -46,12 +46,10 @@ security:
 libpal.so: $(addsuffix .o,$(objs)) $(filter %.map %.lds,$(LDFLAGS)) \
 libpal.so: $(addsuffix .o,$(objs)) $(filter %.map %.lds,$(LDFLAGS)) \
 	   $(host_lib) $(graphene_lib)
 	   $(host_lib) $(graphene_lib)
 	@echo [ $@ ]
 	@echo [ $@ ]
-	@[ ! -f $@ ] || mv -f $@ $@.backup
 	@$(LD) $(LDFLAGS) -o $@ $(filter-out %.map %.lds,$^) -soname=$@
 	@$(LD) $(LDFLAGS) -o $@ $(filter-out %.map %.lds,$^) -soname=$@
 
 
 libpal.a: $(addsuffix .o,$(objs)) $(host_lib) $(graphene_lib)
 libpal.a: $(addsuffix .o,$(objs)) $(host_lib) $(graphene_lib)
 	@echo [ $@ ]
 	@echo [ $@ ]
-	@[ ! -f $@ ] || mv -f $@ $@.backup
 	@$(AR) $(ARFLAGS) $@ $^
 	@$(AR) $(ARFLAGS) $@ $^
 
 
 %.asm: %.c $(headers)
 %.asm: %.c $(headers)
@@ -68,10 +66,6 @@ libpal.a: $(addsuffix .o,$(objs)) $(host_lib) $(graphene_lib)
 	@$(CC) $(CFLAGS) $(defs) -E $< -o $@
 	@$(CC) $(CFLAGS) $(defs) -E $< -o $@
 
 
 clean:
 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 host/$(OS) ] || make -C host/$(OS) clean
 	@[ ! -d security/$(OS) ] || make -C security/$(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 <elf/elf.h>
 #include <bits/dlfcn.h>
 #include <bits/dlfcn.h>
 
 
-DEFINE_GDB_SCRIPT_IN_SRCDIR("pal-gdb.py")
-
 struct link_map * loaded_libraries = NULL;
 struct link_map * loaded_libraries = NULL;
 struct link_map * rtld_map = NULL;
 struct link_map * rtld_map = NULL;
 struct link_map * exec_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
 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 \
 objs	= $(addprefix db_,files devices pipes sockets streams memory threading \
 	    semaphore mutex events process object main rtld misc ipc \
 	    semaphore mutex events process object main rtld misc ipc \
 	    exception) manifest clone-x86_64 gettimeofday-x86_64
 	    exception) manifest clone-x86_64 gettimeofday-x86_64
@@ -35,7 +35,6 @@ $(graphene_lib):
 
 
 libpal-Linux.a: $(addsuffix .o,$(objs)) $(graphene_lib)
 libpal-Linux.a: $(addsuffix .o,$(objs)) $(graphene_lib)
 	@echo [ host/Linux/$@ ]
 	@echo [ host/Linux/$@ ]
-	@[ ! -f $@ ] || mv -f $@ $@.backup
 	@$(AR) $(ARFLAGS) $@ $^
 	@$(AR) $(ARFLAGS) $@ $^
 
 
 %.asm: %.c $(headers)
 %.asm: %.c $(headers)
@@ -60,8 +59,4 @@ libpal-Linux.a: $(addsuffix .o,$(objs)) $(graphene_lib)
 	@$(AS) $(ASFLAGS) $(defs) -E $< -o $@
 	@$(AS) $(ASFLAGS) $(defs) -E $< -o $@
 
 
 clean:
 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"
      "  movq %rsp, %rdi \n"
      "  call pal_linux_main \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;
 struct pal_linux_config pal_linux_config;
 
 
 static size_t pagesz = PRESET_PAGESIZE;
 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);
                               pal_config.environments);
 
 
         /* shouldn't get to here */
         /* shouldn't get to here */
-        INLINE_SYSCALL(exit_group, 0);
+        printf("unexpected failure of new process\n");
+        asm("hlt");
         return 0;
         return 0;
     }
     }
 
 

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

@@ -3,15 +3,13 @@
 import os, sys, gdb
 import os, sys, gdb
 
 
 if len(gdb.inferiors()) == 1:
 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()
     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"
         gdbfile = os.path.dirname(__file__) + "/pal.gdb"
         gdb.execute("set env IN_GDB = 1")
         gdb.execute("set env IN_GDB = 1")
         gdb.execute("source " + gdbfile)
         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
 #endif
 
 
 #define ARCH_FORK() INLINE_SYSCALL(clone, 4, CLONE_CHILD_SETTID, 0, \
 #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, \
 #define ARCH_VFORK() INLINE_SYSCALL(clone, 4, CLONE_VM|CLONE_VFORK, 0, \
                                     NULL, NULL)
                                     NULL, NULL)

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

@@ -43,7 +43,6 @@ $(graphene_lib):
 
 
 libpal-Skeleton.a: $(addsuffix .o,$(objs)) $(graphene_lib)
 libpal-Skeleton.a: $(addsuffix .o,$(objs)) $(graphene_lib)
 	@echo [ $@ ]
 	@echo [ $@ ]
-	@[ ! -f $@ ] || mv -f $@ $@.backup
 	@$(AR) $(ARFLAGS) $@ $^
 	@$(AR) $(ARFLAGS) $@ $^
 
 
 %.asm: %.c $(headers)
 %.asm: %.c $(headers)
@@ -68,8 +67,4 @@ libpal-Skeleton.a: $(addsuffix .o,$(objs)) $(graphene_lib)
 	@$(AS) $(ASFLAGS) $(defs) -E $< -o $@
 	@$(AS) $(ASFLAGS) $(defs) -E $< -o $@
 
 
 clean:
 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)
     } 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
 #else
 
 
 int pal_printf  (const char *fmt, ...);
 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
 The following packages are required for building Graphene: (can be installed
 with 'apt-get install')
 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
 To build the system, simply run the following commands in the root of the
 source tree:
 source tree: