[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] runcon: add --no-new-privs option
From: |
Sebastian Kisela |
Subject: |
[PATCH] runcon: add --no-new-privs option |
Date: |
Wed, 26 Apr 2017 15:57:12 +0200 |
* src/runcon.c: add --no-new-privs option to allow user to test
if given context grants more privileges to given command.
Uses no_new_privs bit introduced in Linux 3.5.
* tests/runcon/no-new-privs.sh: Add a test case.
* tests/local.mk: Reference the new test.
* NEWS: Mention the new feature
Discussed at https://bugzilla.redhat.com/1360903
---
NEWS | 4 ++++
src/runcon.c | 39 +++++++++++++++++++++++++++++++++++----
tests/local.mk | 1 +
tests/runcon/no-new-privs.sh | 44
++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 84 insertions(+), 4 deletions(-)
create mode 100755 tests/runcon/no-new-privs.sh
diff --git a/NEWS b/NEWS
index 72981b6..87d96cf 100644
--- a/NEWS
+++ b/NEWS
@@ -31,6 +31,10 @@ GNU coreutils NEWS
-*- outline -*-
split supports a new --hex-suffixes[=from] option to create files with
lower case hexadecimal suffixes, similar to the --numeric-suffixes
option.
+ runcon --no-new-privs now added for testing purposes. If the option is
used
+ runcon will not run a process in a context which has additional
privileges.
+ [uses no_new_privs bit added in Linux 3.5]
+
* Noteworthy changes in release 8.27 (2017-03-08) [stable]
diff --git a/src/runcon.c b/src/runcon.c
index 92f519d..9021614 100644
--- a/src/runcon.c
+++ b/src/runcon.c
@@ -50,12 +50,20 @@
#include "die.h"
#include "error.h"
#include "quote.h"
+#include <sys/prctl.h>
/* The official name of this program (e.g., no 'g' prefix). */
#define PROGRAM_NAME "runcon"
#define AUTHORS proper_name ("Russell Coker")
+/* For long options that have no equivalent short option, use a
+ non-character as a pseudo short option, starting with CHAR_MAX + 1. */
+enum
+{
+ NO_NEW_PRIVS_ARG = CHAR_MAX + 1,
+};
+
static struct option const long_options[] =
{
{"role", required_argument, NULL, 'r'},
@@ -63,6 +71,7 @@ static struct option const long_options[] =
{"user", required_argument, NULL, 'u'},
{"range", required_argument, NULL, 'l'},
{"compute", no_argument, NULL, 'c'},
+ {"no-new-privs", no_argument, NULL, NO_NEW_PRIVS_ARG},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
@@ -76,8 +85,9 @@ usage (int status)
else
{
printf (_("\
-Usage: %s CONTEXT COMMAND [args]\n\
- or: %s [ -c ] [-u USER] [-r ROLE] [-t TYPE] [-l RANGE] COMMAND [args]\n\
+Usage: %s [OPTION] CONTEXT COMMAND [args]\n\
+ or: %s [ --no-new-privs ] [ -c ] [-u USER] [-r ROLE] \
+ [-t TYPE] [-l RANGE] COMMAND [args]\n\
"), program_name, program_name);
fputs (_("\
Run a program in a different SELinux security context.\n\
@@ -93,8 +103,10 @@ With neither CONTEXT nor COMMAND, print the current
security context.\n\
-u, --user=USER user identity\n\
-r, --role=ROLE role\n\
-l, --range=RANGE levelrange\n\
+ --no-new-privs set NO_NEW_PRIVS bit to forbid additional
privileges\n\
\n\
"), stdout);
+
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
emit_ancillary_info (PROGRAM_NAME);
@@ -114,6 +126,7 @@ main (int argc, char **argv)
char *file_context = NULL;
char *new_context = NULL;
bool compute_trans = false;
+ bool no_new_privs = false;
context_t con;
@@ -157,7 +170,15 @@ main (int argc, char **argv)
case 'c':
compute_trans = true;
break;
-
+ case NO_NEW_PRIVS_ARG:
+#ifdef PR_SET_NO_NEW_PRIVS
+ no_new_privs = true;
+ break;
+#else
+ die (EXIT_FAILURE, 0,
+ _("--no-new-privs cannot be used in the cureutils version,\
+ that is currently installed."));
+#endif
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
default:
@@ -253,11 +274,21 @@ main (int argc, char **argv)
if (setexeccon (context_str (con)) != 0)
die (EXIT_FAILURE, errno, _("unable to set security context %s"),
quote (context_str (con)));
+
if (cur_context != NULL)
freecon (cur_context);
- execvp (argv[optind], argv + optind);
+ /* do not allow more privileges than this process has */
+ if (no_new_privs)
+ {
+#ifdef PR_SET_NO_NEW_PRIVS
+ if (prctl (PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0)
+ die (EXIT_FAILURE, errno, _("unable to set NO_NEW_PRIVS bit: %s"),
+ quote (context_str (con)));
+#endif
+ }
+ execvp (argv[optind], argv + optind);
int exit_status = errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE;
error (0, errno, "%s", quote (argv[optind]));
return exit_status;
diff --git a/tests/local.mk b/tests/local.mk
index e890c9a..0e386ba 100644
--- a/tests/local.mk
+++ b/tests/local.mk
@@ -664,6 +664,7 @@ all_tests = \
tests/rmdir/fail-perm.sh \
tests/rmdir/ignore.sh \
tests/rmdir/t-slash.sh \
+ tests/runcon/no-new-privs.sh \
tests/tail-2/assert-2.sh \
tests/tail-2/big-4gb.sh \
tests/tail-2/flush-initial.sh \
diff --git a/tests/runcon/no-new-privs.sh b/tests/runcon/no-new-privs.sh
new file mode 100755
index 0000000..1186f2e
--- /dev/null
+++ b/tests/runcon/no-new-privs.sh
@@ -0,0 +1,44 @@
+#!/bin/sh
+# Makes sure, inotify will switch to polling mode if directory
+# of the watched file was removed and recreated.
+# (...instead of getting stuck forever)
+
+# Copyright (C) 2006-2017 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+. "${srcdir=.}/tests/init.sh"; path_prepend_ ./src
+print_ver_ runcon
+
+_check_runcon_output ()
+{
+ pattern="$1"
+ file="$2"
+ grep -e "$pattern" "$file" > /dev/null ||
+ { return 1; }
+}
+
+# Run process with inappropriate context
+runcon --no-new-privs -t svirt_lxc_net_t /bin/sh &> out
+
+# Correct behaviour is to permit the operation.
+_check_runcon_output "Operation not permitted" "out" ||\
+# Systems without PR_SET_NO_NEW_PRIVS at the coreutils build time
+# should be sanitized with '...--no-new-privs cannot be used...' message.
+_check_runcon_output "--no-new-privs cannot be used." "out" ||\
+# Sanitize runcon if not run on a SELinux kernel
+_check_runcon_output "runcon may be used only on a SELinux kernel" "out"||\
+fail=1
+
+Exit $fail
--
2.9.3
- [PATCH] runcon: add --no-new-privs option,
Sebastian Kisela <=