aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2015-08-13 22:58:37 -0400
committerMike Frysinger <vapier@gentoo.org>2015-08-20 10:38:35 -0400
commita743806ea4868371cf182f783fdcfbf1b1f98202 (patch)
treedcc780ac28414218d37628b599881d2683bd4cf7
parentlddtree.sh: fix interp handling when doing a full listing (diff)
downloadpax-utils-a743806ea4868371cf182f783fdcfbf1b1f98202.tar.gz
pax-utils-a743806ea4868371cf182f783fdcfbf1b1f98202.tar.bz2
pax-utils-a743806ea4868371cf182f783fdcfbf1b1f98202.zip
security: leverage namespaces to restrict the runtime a bit
In practice this isn't terribly useful as people aren't attacking these tools, but might as well be paranoid. It'd be nice to use mount & net namespaces too, but they're way too slow.
-rw-r--r--Makefile2
-rw-r--r--Makefile.am3
-rw-r--r--dumpelf.c1
-rw-r--r--paxinc.h1
-rw-r--r--porting.h1
-rw-r--r--pspax.c4
-rw-r--r--scanelf.c5
-rw-r--r--scanmacho.c1
-rw-r--r--security.c89
-rw-r--r--security.h29
10 files changed, 135 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index ba3b6a2..ac5e9cc 100644
--- a/Makefile
+++ b/Makefile
@@ -61,7 +61,7 @@ ELF_TARGETS = scanelf dumpelf $(shell echo | $(CC) -dM -E - | grep -q __svr4__
ELF_OBJS = paxelf.o
MACH_TARGETS = scanmacho
MACH_OBJS = paxmacho.o
-COMMON_OBJS = paxinc.o xfuncs.o
+COMMON_OBJS = paxinc.o security.o xfuncs.o
TARGETS = $(ELF_TARGETS) $(MACH_TARGETS)
SCRIPTS_SH = lddtree symtree
SCRIPTS_PY = lddtree
diff --git a/Makefile.am b/Makefile.am
index 5db3f75..e42dce4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -12,6 +12,7 @@ libpaxutils_la_SOURCES = \
paxelf.c \
paxinc.c \
paxmacho.c \
+ security.c \
xfuncs.c
LDADD = libpaxutils.la $(top_builddir)/autotools/gnulib/libgnu.a
@@ -84,6 +85,8 @@ EXTRA_DIST += \
pspax.c \
scanelf.c \
scanmacho.c \
+ security.c \
+ security.h \
symtree.sh \
tests/Makefile \
tests/lddtree/Makefile \
diff --git a/dumpelf.c b/dumpelf.c
index 3035b24..e9b1771 100644
--- a/dumpelf.c
+++ b/dumpelf.c
@@ -384,6 +384,7 @@ static void parseargs(int argc, char *argv[])
int main(int argc, char *argv[])
{
+ security_init(false);
if (argc < 2)
usage(EXIT_FAILURE);
parseargs(argc, argv);
diff --git a/paxinc.h b/paxinc.h
index 0a8e08a..a8d6d9b 100644
--- a/paxinc.h
+++ b/paxinc.h
@@ -13,6 +13,7 @@
#include "porting.h"
#include "xfuncs.h"
+#include "security.h"
#ifndef VERSION
# define VERSION "git"
diff --git a/porting.h b/porting.h
index 1f989d2..9dea528 100644
--- a/porting.h
+++ b/porting.h
@@ -29,6 +29,7 @@
#include <limits.h>
#include <pwd.h>
#include <regex.h>
+#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/pspax.c b/pspax.c
index e27b7eb..c64472c 100644
--- a/pspax.c
+++ b/pspax.c
@@ -535,6 +535,10 @@ int main(int argc, char *argv[])
{
char *name = NULL;
+ /* We unshare pidns but don't actually enter it. That means
+ * we still get to scan /proc, but just not fork children. */
+ security_init(false);
+
color_init(false);
parseargs(argc, argv);
diff --git a/scanelf.c b/scanelf.c
index 99192b2..7e3b077 100644
--- a/scanelf.c
+++ b/scanelf.c
@@ -2472,6 +2472,10 @@ static int parseargs(int argc, char *argv[])
}
if (be_verbose > 2) printf("Format: %s\n", out_format);
+ /* Now lock down the pidns since we know whether we'll be forking. */
+ if (!show_textrels || !be_verbose)
+ security_init_pid();
+
/* now lets actually do the scanning */
if (load_cache_config)
load_ld_cache_config(__PAX_UTILS_DEFAULT_LD_CACHE_CONFIG);
@@ -2570,6 +2574,7 @@ static void cleanup(void)
int main(int argc, char *argv[])
{
int ret;
+ security_init(true);
if (argc < 2)
usage(EXIT_FAILURE);
parseenv();
diff --git a/scanmacho.c b/scanmacho.c
index ee713f9..5a0afd5 100644
--- a/scanmacho.c
+++ b/scanmacho.c
@@ -764,6 +764,7 @@ static int parseargs(int argc, char *argv[])
int main(int argc, char *argv[])
{
int ret;
+ security_init(false);
if (argc < 2)
usage(EXIT_FAILURE);
color_init(false);
diff --git a/security.c b/security.c
new file mode 100644
index 0000000..9b48a9a
--- /dev/null
+++ b/security.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2015 Gentoo Foundation
+ * Distributed under the terms of the GNU General Public License v2
+ *
+ * Copyright 2015 Mike Frysinger - <vapier@gentoo.org>
+ */
+
+#include "paxinc.h"
+
+#ifdef __linux__
+
+#ifdef __SANITIZE_ADDRESS__
+/* ASAN does some weird stuff. */
+# define ALLOW_PIDNS 0
+#else
+# define ALLOW_PIDNS 1
+#endif
+
+static int ns_unshare(int flags)
+{
+ int flag, ret = 0;
+
+ /* Try to oneshot it. Maybe we'll get lucky! */
+ if (unshare(flags) == 0)
+ return flags;
+ /* No access at all, so don't waste time below. */
+ else if (errno == EPERM)
+ return ret;
+
+ /*
+ * We have to run these one permission at a time because if any are
+ * not supported (too old a kernel, or it's disabled), then all of
+ * them will be rejected and we won't know which one is a problem.
+ */
+
+ /* First the ones that work against the current process. */
+ flag = 1;
+ while (flags) {
+ if (flags & flag) {
+ if (unshare(flag) == 0)
+ ret |= flag;
+ flags &= ~flag;
+ }
+ flag <<= 1;
+ }
+
+ return ret;
+}
+
+void security_init_pid(void)
+{
+ int flags;
+
+ if (!ALLOW_PIDNS)
+ return;
+
+ flags = ns_unshare(CLONE_NEWPID);
+ if (USE_SLOW_SECURITY) {
+ if (flags & CLONE_NEWPID)
+ if (vfork() == 0)
+ _exit(0);
+ }
+}
+
+void security_init(bool allow_forking)
+{
+ int flags;
+
+ if (!ALLOW_PIDNS)
+ allow_forking = true;
+
+ /* None of the pax tools need access to these features. */
+ flags = CLONE_NEWIPC | CLONE_NEWUTS;
+ /* Would be nice to leverage mount/net ns, but they're just way too slow. */
+ if (USE_SLOW_SECURITY)
+ flags |= CLONE_NEWNET | CLONE_NEWNS;
+ if (!allow_forking)
+ flags |= CLONE_NEWPID;
+ flags = ns_unshare(flags);
+
+ if (USE_SLOW_SECURITY) {
+ /* We spawn one child and kill it so the kernel will fail in the future. */
+ if (flags & CLONE_NEWPID)
+ if (vfork() == 0)
+ _exit(0);
+ }
+}
+
+#endif
diff --git a/security.h b/security.h
new file mode 100644
index 0000000..c93ec3e
--- /dev/null
+++ b/security.h
@@ -0,0 +1,29 @@
+/* Various security related features.
+ *
+ * Copyright 2015 Gentoo Foundation
+ * Distributed under the terms of the GNU General Public License v2
+ *
+ * Copyright 2015 Mike Frysinger - <vapier@gentoo.org>
+ */
+
+#ifndef _PAX_SECURITY_H
+#define _PAX_SECURITY_H
+
+/* Whether to enable features that significantly impact speed. */
+#ifdef SLOW_SECURITY
+# define USE_SLOW_SECURITY 1
+#else
+# define USE_SLOW_SECURITY 0
+#endif
+
+#ifdef __linux__
+/* Lock down the runtime; allow_forking controls whether to use a pidns. */
+void security_init(bool allow_forking);
+/* Disable forking; usable only when allow_forking above was true. */
+void security_init_pid(void);
+#else
+static inline void security_init(bool allow_forking) {}
+static inline void security_init_pid(void) {}
+#endif
+
+#endif