Below is a patch to update file capabilities tests to work on
64-bit kernels. It switches from manually setting file xattrs
to making use of libcap.
I'm sending it but sending it as RFC because I'm getting odd
failures which I suspect are due to libcap and no the testcases.
Figure in the meantime I can at least send it out for some
more comments from Andrew. Andrew, I'm also attaching the
new verify_caps_exec.c verbatim for easier review.
-serge
Signed-off-by: Serge E. Hallyn <[EMAIL PROTECTED]>
---
Makefile | 8 +
makenumcapsh.c | 21 ++++
verify_caps_exec.c | 225 +++++++++++++++++++++--------------------------------
3 files changed, 121 insertions(+), 133 deletions(-)
diff --git a/testcases/kernel/security/filecaps/Makefile
b/testcases/kernel/security/filecaps/Makefile
index ec5cf8f..651769b 100644
--- a/testcases/kernel/security/filecaps/Makefile
+++ b/testcases/kernel/security/filecaps/Makefile
@@ -37,9 +37,15 @@ all:
TARGETS =
endif
+numcaps.h: makenumcapsh.c
+ gcc -o makenumcapsh makenumcapsh.c
+ ./makenumcapsh > numcaps.h
+
+verify_caps_exec: verify_caps_exec.c numcaps.h
+
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 caps_fifo checkforlibcap
+ rm -f $(TARGETS) *.o caps_fifo checkforlibcap numcaps.h makenumcapsh
diff --git a/testcases/kernel/security/filecaps/makenumcapsh.c
b/testcases/kernel/security/filecaps/makenumcapsh.c
new file mode 100644
index 0000000..6676176
--- /dev/null
+++ b/testcases/kernel/security/filecaps/makenumcapsh.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+#include <errno.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
+
+#ifndef PR_CAPBSET_READ
+#define PR_CAPBSET_READ 23
+#endif
+
+int main(int argc, char *argv[])
+{
+ int i, ret = 0;
+
+ for (i=0; ret != -1; i++) {
+ ret = prctl(PR_CAPBSET_READ, i);
+ if (ret == -1)
+ break;
+ }
+ printf("#define NUM_CAPS %d\n", i);
+ return 0;
+}
diff --git a/testcases/kernel/security/filecaps/verify_caps_exec.c
b/testcases/kernel/security/filecaps/verify_caps_exec.c
index 38aa1ad..77f995a 100644
--- a/testcases/kernel/security/filecaps/verify_caps_exec.c
+++ b/testcases/kernel/security/filecaps/verify_caps_exec.c
@@ -21,7 +21,7 @@
* File: verify_caps_exec.c
* Author: Serge Hallyn
* Purpose: perform several tests of file capabilities:
- * 1. try setting caps without CAP_SYS_ADMIN
+ * 1. try setting caps without privilege
* 2. test proper calculation of pI', pE', and pP'.
* Try setting valid caps, drop rights, and run the executable,
* make sure we get the rights
@@ -35,13 +35,14 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
-#include <attr/xattr.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/capability.h>
#include <sys/prctl.h>
#include <test.h>
+#include "numcaps.h"
+
#define TSTPATH "./print_caps"
char *TCID = "filecaps";
int TST_TOTAL=1;
@@ -51,7 +52,7 @@ int errno;
void usage(char *me)
{
tst_resm(TFAIL, "Usage: %s <0|1> [arg]\n", me);
- tst_resm(TINFO, " 0: set file caps without CAP_SYS_ADMIN\n");
+ tst_resm(TINFO, " 0: set file caps without privilegeCAP_SYS_ADMIN\n");
tst_resm(TINFO, " 1: test that file caps are set correctly on exec\n");
tst_exit(1);
}
@@ -63,6 +64,7 @@ void print_my_caps()
{
cap_t cap = cap_get_proc();
tst_resm(TINFO, "\ncaps are %s\n", cap_to_text(cap, NULL));
+ cap_free(cap);
}
int drop_root(int keep_perms)
@@ -78,52 +80,27 @@ int drop_root(int keep_perms)
tst_exit(4);
}
if (keep_perms) {
- cap_t cap = cap_from_text("=eip cap_setpcap-eip");
+ cap_t cap = cap_from_text("=eip");
cap_set_proc(cap);
+ cap_free(cap);
}
return 1;
}
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define cpu_to_le32(x) x
-#else
-#define cpu_to_le32(x) bswap_32(x)
-#endif
-
-/*
- * TODO: find a better way to do this. Emulate libcap's
- * way, or just take it from linux/capability.h
- */
-/*
- * TODO: accomodate 64-bit capabilities
- */
-#define CAPNAME "security.capability"
-#ifndef __CAP_BITS
-#define __CAP_BITS 31
-#endif
-
-#define XATTR_CAPS_SZ (3*sizeof(__le32))
-#define VFS_CAP_REVISION_MASK 0xFF000000
-#define VFS_CAP_REVISION 0x01000000
-
-#define VFS_CAP_FLAGS_MASK ~VFS_CAP_REVISION_MASK
-#define VFS_CAP_FLAGS_EFFECTIVE 0x000001
-
int perms_test(void)
{
int ret;
- unsigned int value[3];
- unsigned int v;
+ cap_t cap;
drop_root(DROP_PERMS);
- v = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE;
- value[0] = cpu_to_le32(v);
- value[1] = 1;
- value[2] = 1;
- ret = setxattr(TSTPATH, CAPNAME, value, 3*sizeof(unsigned int), 0);
+ cap = cap_from_text("all=eip");
+ if (!cap) {
+ tst_resm(TFAIL, "could not get cap from text for perms test\n");
+ return 1;
+ }
+ ret = cap_set_file(TSTPATH, cap);
if (ret) {
- perror("setxattr");
tst_resm(TPASS, "could not set capabilities as non-root\n");
ret = 0;
} else {
@@ -131,6 +108,7 @@ int perms_test(void)
ret = 1;
}
+ cap_free(cap);
return ret;
}
@@ -231,17 +209,15 @@ int fork_drop_and_exec(int keepperms, char *capstxt)
int caps_actually_set_test(void)
{
- int i, whichset, whichcap, finalret = 0, ret;
- cap_t cap;
+ int whichcap, finalret = 0, ret;
+ cap_t fcap, pcap, cap_fullpi;
char *capstxt;
- unsigned int value[3];
cap_value_t capvalue[1];
- unsigned int magic;
-
- magic = VFS_CAP_REVISION;
+ int i;
- cap = cap_init();
- if (!cap) {
+ fcap = cap_init();
+ pcap = cap_init();
+ if (!fcap || !pcap) {
perror("cap_init");
exit(2);
}
@@ -249,61 +225,64 @@ int caps_actually_set_test(void)
create_fifo();
/* first, try each bit in fP (forced) with fE on and off. */
- value[1] = value[2] = cpu_to_le32(0);
- for (whichcap=0; whichcap < __CAP_BITS; whichcap++) {
- if (whichcap == 8)
- continue;
- /* fE = 0, don't gain the perm */
+ for (whichcap=0; whichcap < NUM_CAPS; whichcap++) {
+ /*
+ * fP=whichcap, fE=fI=0
+ * pP'=whichcap, pI'=pE'=0
+ */
capvalue[0] = whichcap;
- value[0] = cpu_to_le32(magic);
- value[1] = cpu_to_le32(1 << whichcap);
- ret = setxattr(TSTPATH, CAPNAME, value, 3*sizeof(unsigned int),
0);
+ cap_clear(fcap);
+ cap_set_flag(fcap, CAP_PERMITTED, 1, capvalue, CAP_SET);
+ ret = cap_set_file(TSTPATH, fcap);
if (ret) {
- tst_resm(TINFO, "%d %d\n", whichset, whichcap);
- perror("setxattr");
+ tst_resm(TINFO, "%d\n", whichcap);
continue;
}
- /* do a sanity check */
- cap_clear(cap);
- cap_set_flag(cap, CAP_PERMITTED, 1, capvalue, CAP_SET);
- capstxt = cap_to_text(cap, NULL);
+ capstxt = cap_to_text(fcap, NULL);
ret = fork_drop_and_exec(DROP_PERMS, capstxt);
+ cap_free(capstxt);
if (ret) {
tst_resm(TINFO, "Failed CAP_PERMITTED=%d
CAP_EFFECTIVE=0\n",
whichcap);
- if (!finalret)
- finalret = ret;
+ if (!finalret) finalret = ret;
}
- /* fE = 1, do gain the perm */
- value[0] = cpu_to_le32(magic | VFS_CAP_FLAGS_EFFECTIVE);
- value[1] = cpu_to_le32(1 << whichcap);
- ret = setxattr(TSTPATH, CAPNAME, value, 3*sizeof(unsigned int),
0);
+/* SERGE here */
+ /*
+ * fP = fE = whichcap, fI = 0
+ * pP = pE = whichcap, pI = 0
+ */
+ cap_clear(fcap);
+ cap_set_flag(fcap, CAP_PERMITTED, 1, capvalue, CAP_SET);
+ cap_set_flag(fcap, CAP_EFFECTIVE, 1, capvalue, CAP_SET);
+ ret = cap_set_file(TSTPATH, fcap);
if (ret) {
- tst_resm(TINFO, "%d %d\n", whichset, whichcap);
- perror("setxattr");
+ tst_resm(TINFO, "%d\n", whichcap);
continue;
}
- /* do a sanity check */
- cap_clear(cap);
- cap_set_flag(cap, CAP_PERMITTED, 1, capvalue, CAP_SET);
- cap_set_flag(cap, CAP_EFFECTIVE, 1, capvalue, CAP_SET);
- capstxt = cap_to_text(cap, NULL);
+ capstxt = cap_to_text(fcap, NULL);
if (strcmp(capstxt, "=")==0) {
tst_resm(TINFO, "%s: libcap doesn't know about cap %d,
not running\n",
__FUNCTION__, whichcap);
ret = 0;
} else
ret = fork_drop_and_exec(DROP_PERMS, capstxt);
+ cap_free(capstxt);
if (ret) {
tst_resm(TINFO, "Failed CAP_PERMITTED=%d
CAP_EFFECTIVE=1\n",
whichcap);
- if (!finalret)
- finalret = ret;
+ if (!finalret) finalret = ret;
}
}
+ cap_free(pcap);
+ cap_free(fcap);
+ cap_fullpi = cap_init();
+ for (i=0; i<NUM_CAPS; i++) {
+ capvalue[0] = i;
+ cap_set_flag(cap_fullpi, CAP_INHERITABLE, 1, capvalue, CAP_SET);
+ }
/*
* next try each bit in fI
* The first two attemps have the bit which is in fI in pI.
@@ -313,72 +292,60 @@ int caps_actually_set_test(void)
* This should result in empty capability, as there were
* no bits to be inherited from the original process.
*/
- value[1] = value[2] = cpu_to_le32(0);
- for (whichcap=0; whichcap < __CAP_BITS; whichcap++) {
- if (whichcap == 8)
- continue;
+ for (whichcap=0; whichcap < NUM_CAPS; whichcap++) {
+ capvalue[0] = whichcap;
+
/*
- * bit is in fI and pI, so should be in pI'.
- * but fE=0, so cap is in pP' but not pE'.
+ * fI=whichcap, fP=fE=0
+ * pI=full
+ * pI'=full, pP'=whichcap, pE'=0
*/
- value[0] = cpu_to_le32(magic);
- value[2] = cpu_to_le32(1 << whichcap);
- ret = setxattr(TSTPATH, CAPNAME, value, 3*sizeof(unsigned int),
0);
+ /* fill pI' */
+ pcap = cap_dup(cap_fullpi);
+ /* pP' = whichcap */
+ cap_set_flag(pcap, CAP_PERMITTED, 1, capvalue, CAP_SET);
+
+ /* fI = whichcap */
+ fcap = cap_init();
+ cap_set_flag(fcap, CAP_INHERITABLE, 1, capvalue, CAP_SET);
+ ret = cap_set_file(TSTPATH, fcap);
if (ret) {
- tst_resm(TINFO, "%d %d\n", whichset, whichcap);
- perror("setxattr");
+ tst_resm(TINFO, "%d\n", whichcap);
continue;
}
- /* do a sanity check */
- cap_clear(cap);
- for (i=0; i<32; i++) {
- if (i != 8) {
- capvalue[0] = i;
- cap_set_flag(cap, CAP_INHERITABLE, 1, capvalue,
CAP_SET);
- }
- }
- capvalue[0] = whichcap;
- cap_set_flag(cap, CAP_PERMITTED, 1, capvalue, CAP_SET);
- capstxt = cap_to_text(cap, NULL);
+ capstxt = cap_to_text(pcap, NULL);
ret = fork_drop_and_exec(KEEP_PERMS, capstxt);
+ cap_free(capstxt);
if (ret) {
tst_resm(TINFO, "Failed with_perms CAP_INHERITABLE=%d "
"CAP_EFFECTIVE=0\n", whichcap);
- if (!finalret)
- finalret = ret;
+ if (!finalret) finalret = ret;
}
/*
- * bit is in fI and pI, so should be in pI'.
- * and fE=1, so cap is in pP' and pE'.
+ * fI=fE=whichcap, fP=0
+ * pI=full
+ * pI'=full, pP'=whichcap, pE'=whichcap
+ *
+ * Note that only fE and pE' change, so keep prior
+ * fcap and pcap and set those bits.
*/
- value[0] = cpu_to_le32(magic | VFS_CAP_FLAGS_EFFECTIVE);
- value[2] = cpu_to_le32(1 << whichcap);
- ret = setxattr(TSTPATH, CAPNAME, value, 3*sizeof(unsigned int),
0);
+ cap_set_flag(fcap, CAP_EFFECTIVE, 1, capvalue, CAP_SET);
+ cap_set_flag(pcap, CAP_EFFECTIVE, 1, capvalue, CAP_SET);
+ ret = cap_set_file(TSTPATH, fcap);
if (ret) {
- tst_resm(TINFO, "%d %d\n", whichset, whichcap);
- perror("setxattr");
+ tst_resm(TINFO, "%d\n", whichcap);
continue;
}
- /* do a sanity check */
- cap_clear(cap);
- for (i=0; i<32; i++) {
- if (i != 8) {
- capvalue[0] = i;
- cap_set_flag(cap, CAP_INHERITABLE, 1, capvalue,
CAP_SET);
- }
- }
- capvalue[0] = whichcap;
- cap_set_flag(cap, CAP_PERMITTED, 1, capvalue, CAP_SET);
- cap_set_flag(cap, CAP_EFFECTIVE, 1, capvalue, CAP_SET);
- capstxt = cap_to_text(cap, NULL);
+ capstxt = cap_to_text(pcap, NULL);
if (strcmp(capstxt, "=")==0) {
tst_resm(TINFO, "%s: libcap doesn't know about cap %d,
not running\n",
__FUNCTION__, whichcap);
ret = 0;
} else
ret = fork_drop_and_exec(KEEP_PERMS, capstxt);
+ cap_free(capstxt);
if (ret) {
tst_resm(TINFO, "Failed with_perms CAP_INHERITABLE=%d "
"CAP_EFFECTIVE=1\n", whichcap);
@@ -387,31 +354,25 @@ int caps_actually_set_test(void)
}
/*
- * bit is in fI but not in pI
- * So pP' is empty.
- * pE' must be empty.
+ * fI=fE=whichcap, fP=0 (so fcap is same as before)
+ * pI=0 (achieved using DROP_PERMS)
+ * pI'=pP'=pE'=0
*/
- value[0] = cpu_to_le32(magic | VFS_CAP_FLAGS_EFFECTIVE);
- value[2] = cpu_to_le32(1 << whichcap);
- ret = setxattr(TSTPATH, CAPNAME, value, 3*sizeof(unsigned int),
0);
- if (ret) {
- tst_resm(TINFO, "%d %d\n", whichset, whichcap);
- perror("setxattr");
- continue;
- }
- /* do a sanity check */
- cap_clear(cap);
- capstxt = cap_to_text(cap, NULL);
+ cap_clear(pcap);
+ capstxt = cap_to_text(pcap, NULL);
ret = fork_drop_and_exec(DROP_PERMS, capstxt);
+ cap_free(capstxt);
if (ret) {
tst_resm(TINFO, "Failed without_perms
CAP_INHERITABLE=%d",
whichcap);
if (!finalret)
finalret = ret;
}
+
+ cap_free(fcap);
+ cap_free(pcap);
}
- cap_free(cap);
return finalret;
}
/******************************************************************************/
/* */
/* 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: verify_caps_exec.c
* Author: Serge Hallyn
* Purpose: perform several tests of file capabilities:
* 1. try setting caps without privilege
* 2. test proper calculation of pI', pE', and pP'.
* Try setting valid caps, drop rights, and run the executable,
* make sure we get the rights
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <endian.h>
#include <byteswap.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/capability.h>
#include <sys/prctl.h>
#include <test.h>
#include "numcaps.h"
#define TSTPATH "./print_caps"
char *TCID = "filecaps";
int TST_TOTAL=1;
int errno;
void usage(char *me)
{
tst_resm(TFAIL, "Usage: %s <0|1> [arg]\n", me);
tst_resm(TINFO, " 0: set file caps without privilegeCAP_SYS_ADMIN\n");
tst_resm(TINFO, " 1: test that file caps are set correctly on exec\n");
tst_exit(1);
}
#define DROP_PERMS 0
#define KEEP_PERMS 1
void print_my_caps()
{
cap_t cap = cap_get_proc();
tst_resm(TINFO, "\ncaps are %s\n", cap_to_text(cap, NULL));
cap_free(cap);
}
int drop_root(int keep_perms)
{
int ret;
if (keep_perms)
prctl(PR_SET_KEEPCAPS, 1);
ret = setresuid(1000, 1000, 1000);
if (ret) {
perror("setresuid");
tst_resm(TFAIL, "Error dropping root privs\n");
tst_exit(4);
}
if (keep_perms) {
cap_t cap = cap_from_text("=eip");
cap_set_proc(cap);
cap_free(cap);
}
return 1;
}
int perms_test(void)
{
int ret;
cap_t cap;
drop_root(DROP_PERMS);
cap = cap_from_text("all=eip");
if (!cap) {
tst_resm(TFAIL, "could not get cap from text for perms test\n");
return 1;
}
ret = cap_set_file(TSTPATH, cap);
if (ret) {
tst_resm(TPASS, "could not set capabilities as non-root\n");
ret = 0;
} else {
tst_resm(TFAIL, "could set capabilities as non-root\n");
ret = 1;
}
cap_free(cap);
return ret;
}
#define FIFOFILE "caps_fifo"
void create_fifo(void)
{
int ret;
ret = mkfifo(FIFOFILE, S_IRWXU | S_IRWXG | S_IRWXO);
if (ret == -1 && errno != EEXIST) {
perror("mkfifo");
tst_resm(TFAIL, "failed creating %s\n", FIFOFILE);
tst_exit(1);
}
}
void write_to_fifo(char *buf)
{
int fd;
fd = open(FIFOFILE, O_WRONLY);
write(fd, buf, strlen(buf));
close(fd);
}
void read_from_fifo(char *buf)
{
int fd;
memset(buf, 0, 200);
fd = open(FIFOFILE, O_RDONLY);
if (fd < 0) {
perror("open");
tst_resm(TFAIL, "Failed opening fifo\n");
tst_exit(1);
}
read(fd, buf, 199);
close(fd);
}
int compare_caps(char *buf1, char *buf2)
{
int res;
res = strcmp(buf1, buf2) == 0;
return res;
}
int fork_drop_and_exec(int keepperms, char *capstxt)
{
int pid;
int ret = 0;
char buf[200], *p;
static int seqno = 0;
pid = fork();
if (pid < 0) {
perror("fork");
tst_resm(TFAIL, "%s: failed fork\n", __FUNCTION__);
tst_exit(1);
}
if (pid == 0) {
drop_root(keepperms);
print_my_caps();
sprintf(buf, "%d", seqno);
ret = execlp(TSTPATH, TSTPATH, buf, NULL);
perror("execl");
tst_resm(TFAIL, "%s: exec failed\n", __FUNCTION__);
snprintf(buf, 200, "failed to run as %s\n", capstxt);
write_to_fifo(buf);
tst_exit(1);
} else {
p = buf;
while (1) {
int c, s;
read_from_fifo(buf);
c = sscanf(buf, "%d", &s);
if (c==1 && s==seqno)
break;
tst_resm(TINFO, "got a bad seqno (c=%d, s=%d, seqno=%d)",
c, s, seqno);
}
p = index(buf, '.')+1;
if (p==(char *)1) {
tst_resm(TFAIL, "got a bad message from print_caps\n");
tst_exit(1);
}
tst_resm(TINFO, "Expected to run as .%s., ran as .%s..\n",
capstxt, p);
if (strcmp(p, capstxt) != 0) {
tst_resm(TINFO, "those are not the same\n");
ret = -1;
}
seqno++;
}
return ret;
}
int caps_actually_set_test(void)
{
int whichcap, finalret = 0, ret;
cap_t fcap, pcap, cap_fullpi;
char *capstxt;
cap_value_t capvalue[1];
int i;
fcap = cap_init();
pcap = cap_init();
if (!fcap || !pcap) {
perror("cap_init");
exit(2);
}
create_fifo();
/* first, try each bit in fP (forced) with fE on and off. */
for (whichcap=0; whichcap < NUM_CAPS; whichcap++) {
/*
* fP=whichcap, fE=fI=0
* pP'=whichcap, pI'=pE'=0
*/
capvalue[0] = whichcap;
cap_clear(fcap);
cap_set_flag(fcap, CAP_PERMITTED, 1, capvalue, CAP_SET);
ret = cap_set_file(TSTPATH, fcap);
if (ret) {
tst_resm(TINFO, "%d\n", whichcap);
continue;
}
capstxt = cap_to_text(fcap, NULL);
ret = fork_drop_and_exec(DROP_PERMS, capstxt);
cap_free(capstxt);
if (ret) {
tst_resm(TINFO, "Failed CAP_PERMITTED=%d CAP_EFFECTIVE=0\n",
whichcap);
if (!finalret) finalret = ret;
}
/* SERGE here */
/*
* fP = fE = whichcap, fI = 0
* pP = pE = whichcap, pI = 0
*/
cap_clear(fcap);
cap_set_flag(fcap, CAP_PERMITTED, 1, capvalue, CAP_SET);
cap_set_flag(fcap, CAP_EFFECTIVE, 1, capvalue, CAP_SET);
ret = cap_set_file(TSTPATH, fcap);
if (ret) {
tst_resm(TINFO, "%d\n", whichcap);
continue;
}
capstxt = cap_to_text(fcap, NULL);
if (strcmp(capstxt, "=")==0) {
tst_resm(TINFO, "%s: libcap doesn't know about cap %d, not running\n",
__FUNCTION__, whichcap);
ret = 0;
} else
ret = fork_drop_and_exec(DROP_PERMS, capstxt);
cap_free(capstxt);
if (ret) {
tst_resm(TINFO, "Failed CAP_PERMITTED=%d CAP_EFFECTIVE=1\n",
whichcap);
if (!finalret) finalret = ret;
}
}
cap_free(pcap);
cap_free(fcap);
cap_fullpi = cap_init();
for (i=0; i<NUM_CAPS; i++) {
capvalue[0] = i;
cap_set_flag(cap_fullpi, CAP_INHERITABLE, 1, capvalue, CAP_SET);
}
/*
* next try each bit in fI
* The first two attemps have the bit which is in fI in pI.
* This should result in the bit being in pP'.
* If fE was set then it should also be in pE'.
* The last attempt starts with an empty pI.
* This should result in empty capability, as there were
* no bits to be inherited from the original process.
*/
for (whichcap=0; whichcap < NUM_CAPS; whichcap++) {
capvalue[0] = whichcap;
/*
* fI=whichcap, fP=fE=0
* pI=full
* pI'=full, pP'=whichcap, pE'=0
*/
/* fill pI' */
pcap = cap_dup(cap_fullpi);
/* pP' = whichcap */
cap_set_flag(pcap, CAP_PERMITTED, 1, capvalue, CAP_SET);
/* fI = whichcap */
fcap = cap_init();
cap_set_flag(fcap, CAP_INHERITABLE, 1, capvalue, CAP_SET);
ret = cap_set_file(TSTPATH, fcap);
if (ret) {
tst_resm(TINFO, "%d\n", whichcap);
continue;
}
capstxt = cap_to_text(pcap, NULL);
ret = fork_drop_and_exec(KEEP_PERMS, capstxt);
cap_free(capstxt);
if (ret) {
tst_resm(TINFO, "Failed with_perms CAP_INHERITABLE=%d "
"CAP_EFFECTIVE=0\n", whichcap);
if (!finalret) finalret = ret;
}
/*
* fI=fE=whichcap, fP=0
* pI=full
* pI'=full, pP'=whichcap, pE'=whichcap
*
* Note that only fE and pE' change, so keep prior
* fcap and pcap and set those bits.
*/
cap_set_flag(fcap, CAP_EFFECTIVE, 1, capvalue, CAP_SET);
cap_set_flag(pcap, CAP_EFFECTIVE, 1, capvalue, CAP_SET);
ret = cap_set_file(TSTPATH, fcap);
if (ret) {
tst_resm(TINFO, "%d\n", whichcap);
continue;
}
capstxt = cap_to_text(pcap, NULL);
if (strcmp(capstxt, "=")==0) {
tst_resm(TINFO, "%s: libcap doesn't know about cap %d, not running\n",
__FUNCTION__, whichcap);
ret = 0;
} else
ret = fork_drop_and_exec(KEEP_PERMS, capstxt);
cap_free(capstxt);
if (ret) {
tst_resm(TINFO, "Failed with_perms CAP_INHERITABLE=%d "
"CAP_EFFECTIVE=1\n", whichcap);
if (!finalret)
finalret = ret;
}
/*
* fI=fE=whichcap, fP=0 (so fcap is same as before)
* pI=0 (achieved using DROP_PERMS)
* pI'=pP'=pE'=0
*/
cap_clear(pcap);
capstxt = cap_to_text(pcap, NULL);
ret = fork_drop_and_exec(DROP_PERMS, capstxt);
cap_free(capstxt);
if (ret) {
tst_resm(TINFO, "Failed without_perms CAP_INHERITABLE=%d",
whichcap);
if (!finalret)
finalret = ret;
}
cap_free(fcap);
cap_free(pcap);
}
return finalret;
}
int main(int argc, char *argv[])
{
int ret = 0;
if (argc < 2)
usage(argv[0]);
switch(atoi(argv[1])) {
case 0:
ret = perms_test();
break;
case 1:
ret = caps_actually_set_test();
if (ret)
tst_resm(TFAIL, "Some tests failed\n");
else
tst_resm(TPASS, "All tests passed\n");
break;
default: usage(argv[0]);
}
tst_exit(ret);
}
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list