GrapheneOS / linux-hardened

Minimal supplement to upstream Kernel Self Protection Project changes. Features already provided by SELinux + Yama and archs other than multiarch arm64 / x86_64 aren't in scope. Only tags have stable history. Shared IRC channel with KSPP: irc.freenode.net ##linux-hardened. Currently maintained at https://github.com/anthraxx/linux-hardened.
https://grapheneos.org/
Other
390 stars 102 forks source link

extend SELinux memory protections to have parity with PaX MPROTECT #52

Open thestinger opened 6 years ago

thestinger commented 6 years ago

For example, PaX MPROTECT prevents relro sections from becoming writable again.

sempervictus commented 6 years ago

Does the SARA RFP meet this req? New LSM specifically targeting this aspect (and i think some level of device filtering).

thestinger commented 6 years ago

Yes, but it's likely not flexible enough to use a different policy for distinct Android apps. PaX wasn't flexible enough to handle that and we had to patch in a new exception mode.

sempervictus commented 6 years ago

Thanks for the disambiguation. You don't happen to have that exception mode patch or commit somewhere do you?

thestinger commented 6 years ago

Yes, I still have it along with the userspace changes that were paired with it. We're using SELinux for this now though, which is why the issue is filed about improving SELinux to have parity with PaX MPROTECT or to go beyond it.

From 2db7c8adfd0e57efb3554beb6ad424a144d1c2f7 Mon Sep 17 00:00:00 2001
From: Daniel Micay <danielmicay@gmail.com>
Date: Fri, 22 May 2015 18:17:24 -0400
Subject: [PATCH] implement PaX exception AIDs

---
 fs/binfmt_elf.c             | 34 ++++++++++++++++++++++++++++++++++
 include/linux/android_aid.h |  4 ++++
 include/linux/xattr.h       |  2 ++
 3 files changed, 40 insertions(+)

diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 03972f12dd5..43723df6c65 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -9,6 +9,7 @@
  * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
  */

+#include <linux/android_aid.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
@@ -879,6 +880,37 @@ static long pax_parse_pax_flags(const struct elfhdr * const elf_ex, const struct
 }
 #endif

+static bool pax_has_aids_xattr(struct dentry *dentry)
+{
+   struct inode *inode = dentry->d_inode;
+
+   if (inode_permission(inode, MAY_EXEC))
+       return false;
+
+   if (inode->i_op->getxattr)
+       return inode->i_op->getxattr(dentry, XATTR_NAME_PAX_AIDS, NULL, 0) >= 0;
+
+   return false;
+}
+
+static void pax_handle_aids(struct file * const file)
+{
+   if (!pax_has_aids_xattr(file->f_path.dentry))
+       return;
+#ifdef CONFIG_PAX_PAGEEXEC
+   if (in_group_p(AID_PAX_NO_PAGEEXEC))
+       current->mm->pax_flags &= ~MF_PAX_PAGEEXEC;
+#endif
+#ifdef CONFIG_PAX_MPROTECT
+   if (in_group_p(AID_PAX_NO_MPROTECT))
+       current->mm->pax_flags &= ~MF_PAX_MPROTECT;
+#endif
+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK)
+   if (in_group_p(AID_PAX_NO_RANDMMAP))
+       current->mm->pax_flags &= ~MF_PAX_RANDMMAP;
+#endif
+}
+
 /*
  * These are the functions used to load ELF style executables and shared
  * libraries.  There is no binary dependent code anywhere else.
@@ -1094,6 +1126,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
    }
 #endif

+   pax_handle_aids(bprm->file);
+
 #ifdef CONFIG_PAX_HAVE_ACL_FLAGS
    pax_set_initial_flags(bprm);
 #elif defined(CONFIG_PAX_HOOK_ACL_FLAGS)
diff --git a/include/linux/android_aid.h b/include/linux/android_aid.h
index 0f904b3ba7f..ea96d1c9ceb 100644
--- a/include/linux/android_aid.h
+++ b/include/linux/android_aid.h
@@ -25,4 +25,8 @@
 #define AID_NET_BW_STATS 3006  /* read bandwidth statistics */
 #define AID_NET_BW_ACCT  3007  /* change bandwidth statistics accounting */

+#define AID_PAX_NO_PAGEEXEC 3010  /* disable PaX's PAGEEXEC feature */
+#define AID_PAX_NO_MPROTECT 3011  /* disable PaX's MPROTECT feature */
+#define AID_PAX_NO_RANDMMAP 3012  /* disable PaX's RANDMMAP feature */
+
 #endif
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index cf5f26caa99..9501bb8c51e 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -60,7 +60,9 @@
 /* User namespace */
 #define XATTR_PAX_PREFIX XATTR_USER_PREFIX "pax."
 #define XATTR_PAX_FLAGS_SUFFIX "flags"
+#define XATTR_PAX_AIDS_SUFFIX "aids"
 #define XATTR_NAME_PAX_FLAGS XATTR_PAX_PREFIX XATTR_PAX_FLAGS_SUFFIX
+#define XATTR_NAME_PAX_AIDS XATTR_PAX_PREFIX XATTR_PAX_AIDS_SUFFIX

 #ifdef  __KERNEL__
thestinger commented 6 years ago

And FWIW, 100% of the blame Google for the naming of Android IDs (AIDs) is on Google. :P

sempervictus commented 6 years ago

Thank you! Mprotect with containers has been less than fun, especially with ro fs' for a bunch of the storage implementations.

thestinger commented 6 years ago

The way it works with this AIDs patch is that we used standard Android permissions for this. Android has the option of mapping a permission to a GID which is how the socket permissions work (similar to the grsecurity socket permissions) which is one of the few remaining out-of-tree patches for Android itself (as opposed to mobile SoC supported needed with or without Android).

thestinger commented 6 years ago

This code does require marking executables where the GIDs should enable the exceptions because we only wanted it to apply to app_process but it doesn't have to be done that way.