summaryrefslogtreecommitdiff
path: root/progs
diff options
context:
space:
mode:
authorAndrew G. Morgan <morgan@kernel.org>2020-12-20 16:27:13 -0800
committerAndrew G. Morgan <morgan@kernel.org>2020-12-22 20:57:33 -0800
commit87514ed4dcf2c1778cd9e405c48a0635551c78af (patch)
tree284e9adb8b96c8777b0dd7694d11706fa51f1515 /progs
parent99fcb7c3b8e75f4e5c0199986dab3ad0e8db6d5d (diff)
downloadlibcap2-87514ed4dcf2c1778cd9e405c48a0635551c78af.tar.gz
Improve the usage and diagnostic message for setcap
Also, explicitly support -h rather than fail over to display the usage info. Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
Diffstat (limited to 'progs')
-rw-r--r--progs/setcap.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/progs/setcap.c b/progs/setcap.c
index 442685d..f675cdd 100644
--- a/progs/setcap.c
+++ b/progs/setcap.c
@@ -11,15 +11,23 @@
#include <sys/capability.h>
#include <unistd.h>
-static void usage(void)
+static void usage(int status)
{
fprintf(stderr,
- "usage: setcap [-q] [-v] [-n <rootid>] (-r|-|<caps>) <filename> "
+ "usage: setcap [-h] [-q] [-v] [-n <rootid>] (-r|-|<caps>) <filename> "
"[ ... (-r|-|<capsN>) <filenameN> ]\n"
"\n"
" Note <filename> must be a regular (non-symlink) file.\n"
+ " -r remove capability from file\n"
+ " - read capability text from stdin\n"
+ " <capsN> cap_from_text(3) formatted file capability\n"
+ "\n"
+ " -h this message and exit status 0\n"
+ " -q quietly\n"
+ " -v validate supplied capability matches file\n"
+ " -n <rootid> write a user namespace limited capability\n"
);
- exit(1);
+ exit(status);
}
#define MAXCAP 2048
@@ -65,8 +73,8 @@ int main(int argc, char **argv)
cap_value_t capflag;
uid_t rootid = 0, f_rootid;
- if (argc < 3) {
- usage();
+ if (argc < 2) {
+ usage(1);
}
mycaps = cap_get_proc();
@@ -83,6 +91,9 @@ int main(int argc, char **argv)
quiet = 1;
continue;
}
+ if (!strcmp(*argv, "-h")) {
+ usage(0);
+ }
if (!strcmp(*argv, "-v")) {
verify = 1;
continue;
@@ -107,7 +118,7 @@ int main(int argc, char **argv)
if (!strcmp(*argv,"-")) {
retval = read_caps(quiet, *argv, buffer);
if (retval)
- usage();
+ usage(1);
text = buffer;
} else {
text = *argv;
@@ -116,7 +127,7 @@ int main(int argc, char **argv)
cap_d = cap_from_text(text);
if (cap_d == NULL) {
perror("fatal error");
- usage();
+ usage(1);
}
if (cap_set_nsowner(cap_d, rootid)) {
perror("unable to set nsowner");
@@ -134,7 +145,7 @@ int main(int argc, char **argv)
}
if (--argc <= 0)
- usage();
+ usage(1);
/*
* Set the filesystem capability for this file.
*/
@@ -194,6 +205,7 @@ int main(int argc, char **argv)
if (retval != 0) {
int explained = 0;
int oerrno = errno;
+ int somebits = 0;
#ifdef linux
cap_value_t cap;
cap_flag_value_t per_state;
@@ -201,24 +213,28 @@ int main(int argc, char **argv)
for (cap = 0;
cap_get_flag(cap_d, cap, CAP_PERMITTED, &per_state) != -1;
cap++) {
- cap_flag_value_t inh_state, eff_state;
+ cap_flag_value_t inh_state, eff_state, combined;
cap_get_flag(cap_d, cap, CAP_INHERITABLE, &inh_state);
cap_get_flag(cap_d, cap, CAP_EFFECTIVE, &eff_state);
- if ((inh_state | per_state) != eff_state) {
- fprintf(stderr, "NOTE: Under Linux, effective file capabilities must either be empty, or\n"
- " exactly match the union of selected permitted and inheritable bits.\n");
+ combined = (inh_state | per_state);
+ somebits |= !!eff_state;
+ if (combined != eff_state) {
explained = 1;
break;
}
}
+ if (somebits && explained) {
+ fprintf(stderr, "NOTE: Under Linux, effective file capabilities must either be empty, or\n"
+ " exactly match the union of selected permitted and inheritable bits.\n");
+ }
#endif /* def linux */
-
+
fprintf(stderr,
"Failed to set capabilities on file `%s' (%s)\n",
argv[0], strerror(oerrno));
if (!explained) {
- usage();
+ usage(1);
}
}
}