Add capability bounding set testcases, to verify the following:
1. prctl(CAP_BSET_READ, 0..NCAPS) returns 1
2. prctl(CAP_BSET_READ, -1|NCAPS+1) return -1
3. prctl(CAP_BSET_DROP, -1|NCAPS+1) returns -1
4. prctl(CAP_BSET_DROP, 0..NCAPS) returns 1
4b. prctl(CAP_BSET_READ, N) returns 0 after each unset, 1 for those
not yet removed
5. fI=empty; N \notin pP; prctl(CAPBSET_DROP, N); setting pI=N fails
6. pI=N; fI=fE=N; prctl(CAPBSET_DROP, N); exec(f) - N \in pE
(or make f setuid-root)
7. pI=0; fI=fE=N; prctl(CAPBSET_DROP, N); exec(f) - N \notin pE
(or make f setuid-root)
A set of securebits and keepcaps tests have yet to be written (as
per an email I sent a few months ago).
Signed-off-by: Serge Hallyn <[email protected]>
---
runltp | 1 +
runtest/cap_bounds | 2 +
testcases/kernel/security/Makefile | 2 +-
testcases/kernel/security/cap_bound/Makefile | 58 +++++++++
testcases/kernel/security/cap_bound/cap_bounds_r.c | 86 +++++++++++++
.../kernel/security/cap_bound/cap_bounds_rw.c | 124 ++++++++++++++++++
.../security/cap_bound/cap_bset_inh_bounds.c | 131 ++++++++++++++++++++
.../kernel/security/cap_bound/check_for_libcap.sh | 46 +++++++
testcases/kernel/security/cap_bound/check_pe.c | 80 ++++++++++++
testcases/kernel/security/cap_bound/dummy.c | 9 ++
.../kernel/security/cap_bound/exec_with_inh.c | 93 ++++++++++++++
.../kernel/security/cap_bound/exec_without_inh.c | 88 +++++++++++++
.../kernel/security/cap_bound/run_capbounds.sh | 62 +++++++++
13 files changed, 781 insertions(+), 1 deletions(-)
create mode 100644 runtest/cap_bounds
create mode 100644 testcases/kernel/security/cap_bound/Makefile
create mode 100644 testcases/kernel/security/cap_bound/cap_bounds_r.c
create mode 100644 testcases/kernel/security/cap_bound/cap_bounds_rw.c
create mode 100644 testcases/kernel/security/cap_bound/cap_bset_inh_bounds.c
create mode 100644 testcases/kernel/security/cap_bound/check_for_libcap.sh
create mode 100644 testcases/kernel/security/cap_bound/check_pe.c
create mode 100644 testcases/kernel/security/cap_bound/dummy.c
create mode 100644 testcases/kernel/security/cap_bound/exec_with_inh.c
create mode 100644 testcases/kernel/security/cap_bound/exec_without_inh.c
create mode 100755 testcases/kernel/security/cap_bound/run_capbounds.sh
diff --git a/runltp b/runltp
index 8626cc0..ceff41e 100755
--- a/runltp
+++ b/runltp
@@ -538,6 +538,7 @@ main()
${LTPROOT}/runtest/fs_bind \
${LTPROOT}/runtest/controllers \
${LTPROOT}/runtest/filecaps \
+ ${LTPROOT}/runtest/cap_bounds \
${LTPROOT}/runtest/fcntl-locktests \
${LTPROOT}/runtest/connectors \
${LTPROOT}/runtest/admin_tools \
diff --git a/runtest/cap_bounds b/runtest/cap_bounds
new file mode 100644
index 0000000..518d1e3
--- /dev/null
+++ b/runtest/cap_bounds
@@ -0,0 +1,2 @@
+#DESCRIPTION:Posix capability bounding set
+Cap_bounds run_capbounds.sh
diff --git a/testcases/kernel/security/Makefile
b/testcases/kernel/security/Makefile
index d94ff24..862691a 100644
--- a/testcases/kernel/security/Makefile
+++ b/testcases/kernel/security/Makefile
@@ -1,4 +1,4 @@
-SUBDIRS = mmc_security filecaps integrity
+SUBDIRS = mmc_security filecaps integrity cap_bound
all:
@set -e; for i in $(SUBDIRS); do $(MAKE) -C $$i ; done
diff --git a/testcases/kernel/security/cap_bound/Makefile
b/testcases/kernel/security/cap_bound/Makefile
new file mode 100644
index 0000000..5d0ae8b
--- /dev/null
+++ b/testcases/kernel/security/cap_bound/Makefile
@@ -0,0 +1,58 @@
+################################################################################
+##
##
+## Copyright (c) International Business Machines Corp., 2008
##
+##
##
+## 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 2 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, write to the Free Software
##
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
+##
##
+################################################################################
+
+HAVE_LIBCAP := $(shell sh check_for_libcap.sh yesno)
+
+SCRIPTS = run_capbounds.sh
+TARGETS = checkforlibcap
+
+CFLAGS += -I../../../../include -Wall
+LDLIBS += -L../../../../lib -lltp -lcap
+
+ifeq ($(HAVE_LIBCAP),yes)
+SRCS = $(wildcard *.c)
+TARGETS+= $(patsubst %.c,%,$(SRCS))
+endif
+
+all: $(TARGETS)
+
+ifeq ($(HAVE_LIBCAP),yes)
+checkforlibcap:
+ echo "#!/bin/sh" > $@
+ echo true >> $@
+ chmod a+rx $@
+else
+ @echo "libcap is not installed. Please install libcap from"; \
+ echo
"ftp://ftp.kernel.org/pub/linux/libs/security/linux-privs/libcap2."; \
+ echo "You must use libcap-2.11 or newer."; \
+ echo "Then make clean in ltp or ltp/testcases/kernel/security/filecaps,
and recompile ltp."
+checkforlibcap:
+ echo "#!/bin/sh" > $@
+ echo false >> $@
+ chmod a+rx $@
+endif
+
+
+INSTALLTARGETS = $(TARGETS) $(SCRIPTS) checkforlibcap
+install: $(INSTALLTARGETS)
+ @set -e; for i in $(INSTALLTARGETS); do ln -f $$i ../../../bin/$$i ;
chmod +x ../../../bin/$$i; done
+
+clean:
+ rm -f $(TARGETS) *.o checkforlibcap
diff --git a/testcases/kernel/security/cap_bound/cap_bounds_r.c
b/testcases/kernel/security/cap_bound/cap_bounds_r.c
new file mode 100644
index 0000000..9742494
--- /dev/null
+++ b/testcases/kernel/security/cap_bound/cap_bounds_r.c
@@ -0,0 +1,86 @@
+/******************************************************************************/
+/*
*/
+/* Copyright (c) International Business Machines Corp., 2007, 2008
*/
+/*
*/
+/* 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 2 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, write to the Free Software
*/
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/*
*/
+/******************************************************************************/
+/*
+ * File: cap_bounds_r.c
+ * Author: Serge Hallyn
+ * Purpose: test reading of capability bounding set.
+ * Test each valid cap value, as well as edge cases
+ */
+
+#include <errno.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#include <test.h>
+
+#ifndef CAP_LAST_CAP
+#warning out-of-date capability.h does not define CAP_LAST_CAP
+#define CAP_LAST_CAP 28 /* be ultra-conservative */
+#endif
+
+#ifndef CAP_BSET_READ
+#warning CAP_BSET_READ not defined
+#define CAP_BSET_READ 23
+#endif
+
+#ifndef CAP_BSET_DROP
+#warning CAP_BSET_DROP not defined
+#define CAP_BSET_DROP 24
+#endif
+
+char *TCID = "cap_bounds_r";
+int TST_TOTAL=1;
+
+int errno;
+
+int main(int argc, char *argv[])
+{
+ int ret = 1;
+ int i;
+
+ for (i=0; i<=CAP_LAST_CAP; i++) {
+ ret = prctl(CAP_BSET_READ, i);
+ if (ret != 1) {
+ tst_resm(TFAIL, "prctl(CAP_BSET_READ, %d) returned
%d\n", i, ret);
+ if (ret == -1)
+ tst_resm(TINFO, "errno was %d\n", errno);
+ tst_exit(1);
+ }
+ }
+ ret = prctl(CAP_BSET_READ, -1);
+ if (ret != -1) {
+ tst_resm(TFAIL, "prctl(CAP_BSET_READ, -1) returned %d\n", -1,
ret);
+ tst_exit(1);
+ }
+
+ /* Ideally I'd check CAP_LAST_CAP+1, but userspace
+ * tends to be far too unreliable to trust CAP_LAST_CAP>
+ * We could test using kernel API, but that's what we're
+ * testing... So let's take an insanely high value */
+#define INSANE 63
+#define max(x,y) (x > y ? x : y)
+ ret = prctl(CAP_BSET_READ, max(INSANE,CAP_LAST_CAP+1));
+ if (ret != -1) {
+ tst_resm(TFAIL, "prctl(CAP_BSET_READ, %d) returned %d\n",
CAP_LAST_CAP+1, ret);
+ tst_resm(TINFO, " %d is CAP_LAST_CAP+1 and should not exist\n",
CAP_LAST_CAP+1);
+ tst_exit(1);
+ }
+ tst_resm(TPASS, "CAP_BSET_READ tests passed\n");
+ tst_exit(0);
+}
diff --git a/testcases/kernel/security/cap_bound/cap_bounds_rw.c
b/testcases/kernel/security/cap_bound/cap_bounds_rw.c
new file mode 100644
index 0000000..fb4f065
--- /dev/null
+++ b/testcases/kernel/security/cap_bound/cap_bounds_rw.c
@@ -0,0 +1,124 @@
+/******************************************************************************/
+/*
*/
+/* Copyright (c) International Business Machines Corp., 2007, 2008
*/
+/*
*/
+/* 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 2 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, write to the Free Software
*/
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/*
*/
+/******************************************************************************/
+/*
+ * File: cap_bounds_rw
+ * Author: Serge Hallyn
+ * Purpose: test dropping capabilities from bounding set
+ */
+
+#include <errno.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#include <test.h>
+
+#ifndef CAP_LAST_CAP
+#warning out-of-date capability.h does not define CAP_LAST_CAP
+#define CAP_LAST_CAP 28 /* be ultra-conservative */
+#endif
+
+#ifndef CAP_BSET_READ
+#warning CAP_BSET_READ not defined
+#define CAP_BSET_READ 23
+#endif
+
+#ifndef CAP_BSET_DROP
+#warning CAP_BSET_DROP not defined
+#define CAP_BSET_DROP 24
+#endif
+
+char *TCID = "cap_bounds_rw";
+int TST_TOTAL=1;
+
+int errno;
+
+int check_remaining_caps(int lastdropped)
+{
+ int i;
+ int ret;
+
+ for (i=0; i <= lastdropped; i++) {
+ ret = prctl(CAP_BSET_READ, i);
+ if (ret == -1) {
+ tst_resm(TBROK, "Failed to read bounding set during
sanity check\n");
+ tst_exit(1);
+ }
+ if (ret == 1) {
+ tst_resm(TFAIL, "Bit %d should have been dropped but
wasn't\n", i);
+ return i;
+ }
+ }
+ for (; i<=CAP_LAST_CAP; i++) {
+ ret = prctl(CAP_BSET_READ, i);
+ if (ret == -1) {
+ tst_resm(TBROK, "Failed to read bounding set during
sanity check\n");
+ tst_exit(1);
+ }
+ if (ret == 0) {
+ tst_resm(TFAIL, "Bit %d wasn't yet dropped, but isn't
in bounding set\n", i);
+ return -i;
+ }
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret = 1;
+ int i;
+
+ ret = prctl(CAP_BSET_DROP, -1);
+ if (ret != -1) {
+ tst_resm(TFAIL, "prctl(CAP_BSET_DROP, -1) returned %d\n", ret);
+ tst_exit(1);
+ }
+ /* Ideally I'd check CAP_LAST_CAP+1, but userspace
+ * tends to be far too unreliable to trust CAP_LAST_CAP>
+ * We could test using kernel API, but that's what we're
+ * testing... So let's take an insanely high value */
+#define INSANE 63
+#define max(x,y) (x > y ? x : y)
+ ret = prctl(CAP_BSET_DROP, max(INSANE,CAP_LAST_CAP+1));
+ if (ret != -1) {
+ tst_resm(TFAIL, "prctl(CAP_BSET_DROP, %d) returned %d\n",
max(INSANE, CAP_LAST_CAP+1), ret);
+ tst_resm(TINFO, " %d is should not exist\n", max(INSANE,
CAP_LAST_CAP+1));
+ tst_exit(1);
+ }
+ for (i=0; i<=CAP_LAST_CAP; i++) {
+ ret = prctl(CAP_BSET_DROP, i);
+ if (ret != 0) {
+ tst_resm(TFAIL, "prctl(CAP_BSET_DROP, %d) returned
%d\n", i, ret);
+ if (ret == -1)
+ tst_resm(TINFO, "errno was %d\n", errno);
+ tst_exit(1);
+ }
+ ret = check_remaining_caps(i);
+ if (ret > 0) {
+ tst_resm(TFAIL, "after dropping bits 0..%d, %d was
still in bounding set\n",
+ i, ret);
+ tst_exit(1);
+ } else if (ret < 0) {
+ tst_resm(TFAIL, "after dropping bits 0..%d, %d was not
in bounding set\n",
+ i, -ret);
+ tst_exit(1);
+ }
+ }
+ tst_resm(TPASS, "CAP_BSET_DROP tests passed\n");
+ tst_exit(0);
+}
diff --git a/testcases/kernel/security/cap_bound/cap_bset_inh_bounds.c
b/testcases/kernel/security/cap_bound/cap_bset_inh_bounds.c
new file mode 100644
index 0000000..ff9f374
--- /dev/null
+++ b/testcases/kernel/security/cap_bound/cap_bset_inh_bounds.c
@@ -0,0 +1,131 @@
+/******************************************************************************/
+/*
*/
+/* Copyright (c) International Business Machines Corp., 2007, 2008
*/
+/*
*/
+/* 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 2 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, write to the Free Software
*/
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/*
*/
+/******************************************************************************/
+/*
+ * File: cap_bset_inh_bounds.c
+ * Author: Serge Hallyn
+ * Purpose: test bounding set constraint on pI
+ * (X = the capability bounding set)
+ * 1. if N \in pI, then dropping N from X does not drop it from pI
+ * 2. if N \notin X and N \notin pI, then adding N to pI fails
+ */
+
+#include <errno.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#include <test.h>
+
+#ifndef CAP_LAST_CAP
+#warning out-of-date capability.h does not define CAP_LAST_CAP
+#define CAP_LAST_CAP 28 /* be ultra-conservative */
+#endif
+
+#ifndef CAP_BSET_READ
+#warning CAP_BSET_READ not defined
+#define CAP_BSET_READ 23
+#endif
+
+#ifndef CAP_BSET_DROP
+#warning CAP_BSET_DROP not defined
+#define CAP_BSET_DROP 24
+#endif
+
+char *TCID = "cap_bounds_r";
+int TST_TOTAL=2;
+
+int errno;
+
+int main(int argc, char *argv[])
+{
+ int ret = 1;
+ cap_value_t v[1];
+ cap_flag_value_t f;
+ cap_t cur, tmpcap;
+
+ /* We pick a random capability... let's use CAP_SYS_ADMIN */
+ /* make sure we have the capability now */
+ ret = prctl(CAP_BSET_READ, CAP_SYS_ADMIN);
+ if (ret != 1) {
+ tst_resm(TBROK, "Not starting with CAP_SYS_ADMIN\n");
+ tst_exit(1);
+ }
+
+ /* Make sure it's in pI */
+ cur = cap_from_text("all=eip");
+ if (!cur) {
+ tst_resm(TBROK, "Failed to create cap_sys_admin+i cap_t (errno
%d)\n", errno);
+ tst_exit(1);
+ }
+ ret = cap_set_proc(cur);
+ if (ret) {
+ tst_resm(TBROK, "Failed to cap_set_proc with cap_sys_admin+i
(ret %d errno %d)\n",
+ ret, errno);
+ tst_exit(1);
+ }
+ cap_free(cur);
+ cur = cap_get_proc();
+ ret = cap_get_flag(cur, CAP_SYS_ADMIN, CAP_INHERITABLE, &f);
+ if (ret || f != CAP_SET) {
+ tst_resm(TBROK, "Failed to add CAP_SYS_ADMIN to pI\n");
+ tst_exit(1);
+ }
+ cap_free(cur);
+
+ /* drop the capability from bounding set */
+ ret = prctl(CAP_BSET_DROP, CAP_SYS_ADMIN);
+ if (ret) {
+ tst_resm(TFAIL, "Failed to drop CAP_SYS_ADMIN from bounding
set.\n");
+ tst_resm(TINFO, "(ret=%d, errno %d)\n", ret, errno);
+ tst_exit(1);
+ }
+
+ /* test 1: is CAP_SYS_ADMIN still in pI? */
+ cur = cap_get_proc();
+ ret = cap_get_flag(cur, CAP_SYS_ADMIN, CAP_INHERITABLE, &f);
+ if (ret || f != CAP_SET) {
+ tst_resm(TFAIL, "CAP_SYS_ADMIN not in pI after dropping from
bounding set\n");
+ tst_exit(1);
+ }
+ tst_resm(TPASS, "CAP_SYS_ADMIN remains in pI after removing from
bounding set\n");
+
+ tmpcap = cap_dup(cur);
+ v[0] = CAP_SYS_ADMIN;
+ ret = cap_set_flag(tmpcap, CAP_INHERITABLE, 1, v, CAP_CLEAR);
+ if (ret) {
+ tst_resm(TFAIL, "Failed to drop CAP_SYS_ADMIN from cap_t\n");
+ tst_exit(1);
+ }
+ ret = cap_set_proc(tmpcap);
+ if (ret) {
+ tst_resm(TFAIL, "Failed to drop CAP_SYS_ADMIN from pI\n");
+ tst_exit(1);
+ }
+ cap_free(tmpcap);
+
+ /* test 2: can we put it back in pI? */
+ ret = cap_set_proc(cur);
+ if (ret == 0) { /* success means pI was not bounded by X */
+ tst_resm(TFAIL, "Managed to put CAP_SYS_ADMIN back into pI
though not in X\n");
+ tst_exit(1);
+ }
+ cap_free(cur);
+
+ tst_resm(TPASS, "Couldn't put CAP_SYS_ADMIN back into pI when not in
bounding set\n");
+ tst_exit(0);
+}
diff --git a/testcases/kernel/security/cap_bound/check_for_libcap.sh
b/testcases/kernel/security/cap_bound/check_for_libcap.sh
new file mode 100644
index 0000000..b8d7f15
--- /dev/null
+++ b/testcases/kernel/security/cap_bound/check_for_libcap.sh
@@ -0,0 +1,46 @@
+#!/bin/sh
+################################################################################
+##
##
+## Copyright (c) International Business Machines Corp., 2008
##
+##
##
+## 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 2 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, write to the Free Software
##
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
+##
##
+################################################################################
+
+if [ "x$CC" = "x" ]; then
+ export CC=gcc
+fi
+yesno=0
+if [ "$1" = "yesno" ]; then
+ yesno=1
+fi
+
+$CC -o dummy dummy.c -lcap 2>/dev/null
+
+ret=$?
+
+if [ $ret -ne 0 ]; then
+ if [ $yesno -eq 1 ]; then
+ echo no
+ else
+ exit 1
+ fi
+else
+ if [ $yesno -eq 1 ]; then
+ echo yes
+ else
+ exit 0
+ fi
+fi
diff --git a/testcases/kernel/security/cap_bound/check_pe.c
b/testcases/kernel/security/cap_bound/check_pe.c
new file mode 100644
index 0000000..56c5be3
--- /dev/null
+++ b/testcases/kernel/security/cap_bound/check_pe.c
@@ -0,0 +1,80 @@
+/******************************************************************************/
+/*
*/
+/* Copyright (c) International Business Machines Corp., 2007, 2008
*/
+/*
*/
+/* 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 2 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, write to the Free Software
*/
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/*
*/
+/******************************************************************************/
+/*
+ * File: check_pe.c
+ * Author: Serge Hallyn
+ * check whether CAP_SYS_ADMIN is in pE.
+ * return PASS if
+ * * argv[0] is 1 and CAP_SYS_ADMIN is in PE, or
+ * * argv[0] is 0 and CAP_SYS_ADMIN is not in pE
+ * otherwise return FAIL
+ */
+
+#include <errno.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#include <test.h>
+
+char *TCID = "check_pe";
+int TST_TOTAL=1;
+
+int errno;
+
+int main(int argc, char *argv[])
+{
+ int ret = 1;
+ cap_flag_value_t f;
+ cap_t cur;
+ int n;
+
+ if (argc != 2) {
+ tst_resm(TBROK, "Usage: check_pe [0|1]\n");
+ tst_exit(1);
+ }
+ n = atoi(argv[1]);
+ if (n != 0 && n != 1) {
+ tst_resm(TBROK, "Usage: check_pe [0|1]\n");
+ tst_exit(1);
+ }
+
+ cur = cap_get_proc();
+ ret = cap_get_flag(cur, CAP_SYS_ADMIN, CAP_EFFECTIVE, &f);
+ if (ret) {
+ tst_resm(TBROK, "cap_get_flag failed (errno %d)\n", errno);
+ tst_exit(1);
+ }
+
+ cap_free(cur);
+ if (n == 1) {
+ if (f == CAP_SET) {
+ tst_resm(TPASS, "cap is in pE\n");
+ tst_exit(0);
+ }
+ tst_resm(TFAIL, "Cap is not in pE\n");
+ tst_exit(1);
+ }
+ if (f == CAP_CLEAR) {
+ tst_resm(TPASS, "cap is not in pE\n");
+ tst_exit(0);
+ }
+ tst_resm(TFAIL, "Cap is in pE\n");
+ tst_exit(1);
+
+}
diff --git a/testcases/kernel/security/cap_bound/dummy.c
b/testcases/kernel/security/cap_bound/dummy.c
new file mode 100644
index 0000000..cfb8a4d
--- /dev/null
+++ b/testcases/kernel/security/cap_bound/dummy.c
@@ -0,0 +1,9 @@
+#include <sys/capability.h>
+
+int main()
+{
+ cap_t cur;
+ cur = cap_from_text("all=eip");
+ cap_set_proc(cur);
+ cap_free(cur);
+}
diff --git a/testcases/kernel/security/cap_bound/exec_with_inh.c
b/testcases/kernel/security/cap_bound/exec_with_inh.c
new file mode 100644
index 0000000..8b1f602
--- /dev/null
+++ b/testcases/kernel/security/cap_bound/exec_with_inh.c
@@ -0,0 +1,93 @@
+/******************************************************************************/
+/*
*/
+/* Copyright (c) International Business Machines Corp., 2007, 2008
*/
+/*
*/
+/* 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 2 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, write to the Free Software
*/
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/*
*/
+/******************************************************************************/
+/*
+ * File: exec_with_inh.c
+ * Author: Serge Hallyn
+ * Make sure that CAP_SYS_ADMIN is in pI
+ * drop CAP_SYS_ADMIN from bounding set
+ * Then exec "check_pe 1"
+ * check_pe will return PASS if it has CAP_SYS_ADMIN in pE.
+ */
+
+#include <errno.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#include <test.h>
+
+#ifndef CAP_LAST_CAP
+#warning out-of-date capability.h does not define CAP_LAST_CAP
+#define CAP_LAST_CAP 28 /* be ultra-conservative */
+#endif
+
+#ifndef CAP_BSET_READ
+#warning CAP_BSET_READ not defined
+#define CAP_BSET_READ 23
+#endif
+
+#ifndef CAP_BSET_DROP
+#warning CAP_BSET_DROP not defined
+#define CAP_BSET_DROP 24
+#endif
+
+char *TCID = "exec_with_inh";
+int TST_TOTAL=1;
+
+int errno;
+
+int main(int argc, char *argv[])
+{
+ int ret = 1;
+ cap_flag_value_t f;
+ cap_t cur;
+
+ /* Make sure CAP_SYS_ADMIN is in pI */
+ cur = cap_from_text("all=eip");
+ if (!cur) {
+ tst_resm(TBROK, "Failed to create cap_sys_admin+i cap_t (errno
%d)\n", errno);
+ tst_exit(1);
+ }
+ ret = cap_set_proc(cur);
+ if (ret) {
+ tst_resm(TBROK, "Failed to cap_set_proc with cap_sys_admin+i
(ret %d errno %d)\n",
+ ret, errno);
+ tst_exit(1);
+ }
+ cap_free(cur);
+ cur = cap_get_proc();
+ ret = cap_get_flag(cur, CAP_SYS_ADMIN, CAP_INHERITABLE, &f);
+ if (ret || f != CAP_SET) {
+ tst_resm(TBROK, "Failed to add CAP_SYS_ADMIN to pI\n");
+ tst_exit(1);
+ }
+ cap_free(cur);
+
+ /* drop the capability from bounding set */
+ ret = prctl(CAP_BSET_DROP, CAP_SYS_ADMIN);
+ if (ret) {
+ tst_resm(TFAIL, "Failed to drop CAP_SYS_ADMIN from bounding
set.\n");
+ tst_resm(TINFO, "(ret=%d, errno %d)\n", ret, errno);
+ tst_exit(1);
+ }
+
+ /* execute "check_pe 1" */
+ execl("check_pe", "check_pe", "1", NULL);
+ tst_resm(TBROK, "Failed to execute check_pe (errno %d)\n", errno);
+ tst_exit(1);
+}
diff --git a/testcases/kernel/security/cap_bound/exec_without_inh.c
b/testcases/kernel/security/cap_bound/exec_without_inh.c
new file mode 100644
index 0000000..525d03b
--- /dev/null
+++ b/testcases/kernel/security/cap_bound/exec_without_inh.c
@@ -0,0 +1,88 @@
+/******************************************************************************/
+/*
*/
+/* Copyright (c) International Business Machines Corp., 2007, 2008
*/
+/*
*/
+/* 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 2 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, write to the Free Software
*/
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+/*
*/
+/******************************************************************************/
+/*
+ * File: exec_without_inh.c
+ * Author: Serge Hallyn
+ * Make sure that CAP_SYS_ADMIN is not in pI
+ * drop CAP_SYS_ADMIN from bounding set
+ * Then exec "check_pe 0"
+ * check_pe will return PASS if it does not have CAP_SYS_ADMIN in pE.
+ */
+
+#include <errno.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#include <test.h>
+
+#ifndef CAP_LAST_CAP
+#warning out-of-date capability.h does not define CAP_LAST_CAP
+#define CAP_LAST_CAP 28 /* be ultra-conservative */
+#endif
+
+#ifndef CAP_BSET_READ
+#warning CAP_BSET_READ not defined
+#define CAP_BSET_READ 23
+#endif
+
+#ifndef CAP_BSET_DROP
+#warning CAP_BSET_DROP not defined
+#define CAP_BSET_DROP 24
+#endif
+
+char *TCID = "exec_without_inh";
+int TST_TOTAL=1;
+
+int errno;
+
+int main(int argc, char *argv[])
+{
+ int ret = 1;
+ cap_flag_value_t f;
+ cap_value_t v[1];
+ cap_t cur;
+
+ /* Make sure CAP_SYS_ADMIN is not in pI */
+ cur = cap_get_proc();
+ ret = cap_get_flag(cur, CAP_SYS_ADMIN, CAP_INHERITABLE, &f);
+ if (f == CAP_SET) {
+ v[0] = CAP_SYS_ADMIN;
+ ret = cap_set_flag(cur, CAP_INHERITABLE, 1, v, CAP_CLEAR);
+ if (!ret)
+ ret = cap_set_proc(cur);
+ if (ret) {
+ tst_resm(TBROK, "Failed to drop cap_sys_admin from
pI\n");
+ tst_exit(1);
+ }
+ }
+ cap_free(cur);
+
+ /* drop the capability from bounding set */
+ ret = prctl(CAP_BSET_DROP, CAP_SYS_ADMIN);
+ if (ret) {
+ tst_resm(TFAIL, "Failed to drop CAP_SYS_ADMIN from bounding
set.\n");
+ tst_resm(TINFO, "(ret=%d, errno %d)\n", ret, errno);
+ tst_exit(1);
+ }
+
+ /* execute "check_pe 0" */
+ execl("check_pe", "check_pe", "0", NULL);
+ tst_resm(TBROK, "Failed to execute check_pe (errno %d)\n", errno);
+ tst_exit(1);
+}
diff --git a/testcases/kernel/security/cap_bound/run_capbounds.sh
b/testcases/kernel/security/cap_bound/run_capbounds.sh
new file mode 100755
index 0000000..8dd760b
--- /dev/null
+++ b/testcases/kernel/security/cap_bound/run_capbounds.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+################################################################################
+##
##
+## Copyright (c) International Business Machines Corp., 2008
##
+##
##
+## 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 2 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, write to the Free Software
##
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##
+##
##
+################################################################################
+
+if tst_kvercmp 2 6 25 ; then
+ tst_resm TCONF "System kernel version is less than 2.6.25"
+ tst_resm TCONF "Cannot execute test"
+ exit 0
+fi
+
+echo "testing bounding set reading"
+exit_code=0
+
+cap_bounds_r
+tmp=$?
+if [ $tmp -ne 0 ]; then
+ exit_code=$tmp
+fi
+
+echo "testing bounding set dropping"
+cap_bounds_rw
+tmp=$?
+if [ $tmp -ne 0 ]; then
+ exit_code=$tmp
+fi
+
+echo "checking bounding set constraint in pI"
+cap_bset_inh_bounds
+tmp=$?
+if [ $tmp -ne 0 ]; then
+ exit_code=$tmp
+fi
+
+exec_with_inh
+tmp=$?
+if [ $tmp -ne 0 ]; then
+ exit_code=$tmp;
+fi
+exec_without_inh
+tmp=$?
+if [ $tmp -ne 0 ]; then
+ exit_code=$tmp;
+fi
+
+exit $exit_code
--
1.6.1.1
------------------------------------------------------------------------------
Stay on top of everything new and different, both inside and
around Java (TM) technology - register by April 22, and save
$200 on the JavaOne (SM) conference, June 2-5, 2009, San Francisco.
300 plus technical and hands-on sessions. Register today.
Use priority code J9JMT32. http://p.sf.net/sfu/p
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list