diff options
author | Andrew G. Morgan <morgan@kernel.org> | 2023-06-24 22:23:31 -0700 |
---|---|---|
committer | Andrew G. Morgan <morgan@kernel.org> | 2023-06-24 22:24:00 -0700 |
commit | ac8d461a2ce1ca3ea68099d75b5e6fd09f48fcef (patch) | |
tree | c8bcee2ad7e9f64954aa3844279ea9543ad2dba1 | |
parent | 8785077d6c69482a2814a2f771aaada2f6ea1894 (diff) | |
download | libcap-ac8d461a2ce1ca3ea68099d75b5e6fd09f48fcef.tar.gz |
Make it harder to set invalid capabilities on files.
This change introduces the setcap -f argument to allow setting
of nonsense capabilities on files. But the default is to fail
when attempting to set such invalid capabilities.
This commit addresses:
https://bugzilla.kernel.org/show_bug.cgi?id=217592
Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
-rw-r--r-- | doc/getcap.8 | 24 | ||||
-rw-r--r-- | doc/setcap.8 | 8 | ||||
-rw-r--r-- | progs/setcap.c | 33 |
3 files changed, 55 insertions, 10 deletions
diff --git a/doc/getcap.8 b/doc/getcap.8 index 8b6d201..65214b3 100644 --- a/doc/getcap.8 +++ b/doc/getcap.8 @@ -22,6 +22,30 @@ enables recursive search. .TP 4 .B \-v display all searched entries, even if the have no file-capabilities. +.PP +NOTE: an +.I empty +value of +.B '=' +is +.B not +equivalent to an omitted (or removed) capability on a +file. This is most significant with respect to the Ambient capability +vector, since a process with Ambient capabilities will lose them when +executing a file having +.B '=' +capabilities, but will retain the Ambient inheritance of privilege +when executing a file with an omitted file capability. This special +.I empty +setting can be used to prevent a binary from executing with +privilege. For some time, the kernel honored this suppression for root +executing the file, but the kernel developers decided after a number +of years that this behavior was unexpected for the superuser and +reverted it just for that user identity. Suppression of root +privilege, for a process tree, is possible, using the +.BR capsh (1) +.B \-\-mode +option. .TP 4 .IR filename One file per line. diff --git a/doc/setcap.8 b/doc/setcap.8 index d652076..c6b1d50 100644 --- a/doc/setcap.8 +++ b/doc/setcap.8 @@ -44,6 +44,14 @@ ambient+inheritable sets would otherwise bestow capabilities on executed binaries. .PP The +.BR '\-f' , +is used to force completion even when it is in some way considered +an invalid operation. This can affect +.B '\-r' +and setting file capabilities the kernel will not be able to make +sense of. +.PP +The .B \-q flag is used to make the program less verbose in its output. .SH "EXIT CODE" diff --git a/progs/setcap.c b/progs/setcap.c index 737efcc..598272c 100644 --- a/progs/setcap.c +++ b/progs/setcap.c @@ -24,6 +24,7 @@ static void usage(int status) " [ Note: capsh --suggest=\"something...\" might help you pick. ]" "\n" " -h this message and exit status 0\n" + " -f force setting even when the capability is invalid\n" " -q quietly\n" " -v validate supplied capability matches file\n" " -n <rootid> write a user namespace (!= 0) limited capability\n" @@ -99,7 +100,7 @@ int main(int argc, char **argv) { int tried_to_cap_setfcap = 0; char buffer[MAXCAP+1]; - int retval, quiet = 0, verify = 0; + int retval, quiet = 0, verify = 0, forced = 0; cap_t mycaps; cap_value_t capflag; uid_t rootid = 0, f_rootid; @@ -132,6 +133,10 @@ int main(int argc, char **argv) " <morgan@kernel.org>\n", argv[0]); exit(0); } + if (!strcmp(*argv, "-f")) { + forced = 1; + continue; + } if (!strcmp(*argv, "-h")) { usage(0); } @@ -245,12 +250,11 @@ int main(int argc, char **argv) } tried_to_cap_setfcap = 1; } - retval = cap_set_file(*++argv, cap_d); - if (retval != 0) { +#ifdef linux + { + // Linux's file capabilities have a compressed representation. int explained = 0; - int oerrno = errno; int somebits = 0; -#ifdef linux cap_value_t cap; cap_flag_value_t per_state; @@ -269,12 +273,18 @@ int main(int argc, char **argv) } } 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"); + fprintf(stderr, "Error: under Linux, effective file capabilities must either be empty, or\n" + " exactly match the union of selected permitted and inheritable bits.\n"); + if (!forced) { + exit(1); + } } + } #endif /* def linux */ - - switch (oerrno) { + errno = 0; + retval = cap_set_file(*++argv, cap_d); + if (retval != 0) { + switch (errno) { case EINVAL: fprintf(stderr, "Invalid file '%s' for capability operation\n", @@ -285,13 +295,16 @@ int main(int argc, char **argv) fprintf(stderr, "File '%s' has no capablity to remove\n", argv[0]); + if (forced) { + break; + } exit(1); } /* FALLTHROUGH */ default: fprintf(stderr, "Failed to set capabilities on file '%s': %s\n", - argv[0], strerror(oerrno)); + argv[0], strerror(errno)); exit(1); } } |