diff options
author | Andrew G. Morgan <morgan@kernel.org> | 2011-04-25 21:41:09 -0700 |
---|---|---|
committer | Andrew G. Morgan <morgan@kernel.org> | 2011-04-25 21:41:09 -0700 |
commit | f4df8a4ffeaeef271dee296d5fc88eb85827e638 (patch) | |
tree | f0571e44ca6d00a4379306c1ac0687ac9f1738e9 | |
parent | ea806ff7c5a835c0bc607f24f3ac40ef7b39f548 (diff) | |
download | libcap2-f4df8a4ffeaeef271dee296d5fc88eb85827e638.tar.gz |
Add some bounding set capability support to libcap.
Include some documentation and a link to capsh's man page.
Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
-rw-r--r-- | doc/Makefile | 3 | ||||
-rw-r--r-- | doc/cap_drop_bound.3 | 1 | ||||
-rw-r--r-- | doc/cap_get_bound.3 | 1 | ||||
-rw-r--r-- | doc/cap_get_proc.3 | 43 | ||||
-rw-r--r-- | doc/capsh.1 | 11 | ||||
-rw-r--r-- | doc/libcap.3 | 1 | ||||
-rw-r--r-- | libcap/cap_proc.c | 23 | ||||
-rw-r--r-- | libcap/include/sys/capability.h | 5 | ||||
-rw-r--r-- | progs/capsh.c | 36 |
9 files changed, 110 insertions, 14 deletions
diff --git a/doc/Makefile b/doc/Makefile index 5fe2189..7d1f347 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -12,7 +12,8 @@ MAN3S = cap_init.3 cap_free.3 cap_dup.3 \ cap_get_file.3 cap_get_fd.3 cap_set_file.3 cap_set_fd.3 \ cap_copy_ext.3 cap_size.3 cap_copy_int.3 \ cap_from_text.3 cap_to_text.3 cap_from_name.3 cap_to_name.3 \ - capsetp.3 capgetp.3 libcap.3 + capsetp.3 capgetp.3 libcap.3 \ + cap_get_bound.3 cap_drop_bound.3 MAN8S = getcap.8 setcap.8 MANS = $(MAN1S) $(MAN3S) $(MAN8S) diff --git a/doc/cap_drop_bound.3 b/doc/cap_drop_bound.3 new file mode 100644 index 0000000..65ea3e4 --- /dev/null +++ b/doc/cap_drop_bound.3 @@ -0,0 +1 @@ +.so man3/cap_get_proc.3 diff --git a/doc/cap_get_bound.3 b/doc/cap_get_bound.3 new file mode 100644 index 0000000..65ea3e4 --- /dev/null +++ b/doc/cap_get_bound.3 @@ -0,0 +1 @@ +.so man3/cap_get_proc.3 diff --git a/doc/cap_get_proc.3 b/doc/cap_get_proc.3 index 18564e5..123ab3d 100644 --- a/doc/cap_get_proc.3 +++ b/doc/cap_get_proc.3 @@ -3,8 +3,8 @@ .\" .TH CAP_GET_PROC 3 "2008-05-11" "" "Linux Programmer's Manual" .SH NAME -cap_get_proc, cap_set_proc, capgetp \- capability manipulation on -processes +cap_get_proc, cap_set_proc, capgetp, cap_get_bound, cap_drop_bound \- +capability manipulation on processes .SH SYNOPSIS .B #include <sys/capability.h> .sp @@ -12,6 +12,12 @@ processes .sp .BI "int cap_set_proc(cap_t " cap_p ); .sp +.BI "int cap_get_bound(cap_value_t " cap ); +.sp +.BI "CAP_IS_SUPPORTED(cap_value_t " cap ); +.sp +.BI "int cap_drop_bound(cap_value_t " cap ); +.sp .B #include <sys/types.h> .sp .BI "cap_t cap_get_pid(pid_t " pid ); @@ -52,6 +58,28 @@ with the process capabilities of the process indicated by This information can also be obtained from the .I /proc/<pid>/status file. +.PP +.BR cap_get_bound () +with a +.I cap +as an argument returns the current value of this bounding set +capability flag in effect for the current process. This operation is +unpriveged. Note, a macro function +.BI "CAP_IS_SUPPORTED(cap_value_t " cap ) +is provided that evaluates to true (1) if the system supports the +specified capability, +.IR cap . +If the system does not support the capability, this function returns +0. This macro works by testing for an error condition with +.BR cap_get_bound (). +.PP +.BR cap_drop_bound () +can be used to lower the specified bounding set capability, +.BR cap , +To complete successfully, the prevailing +.I effective +capability set must have a raised +.BR CAP_SETPCAP . .SH "RETURN VALUE" The functions .BR cap_get_proc () @@ -60,7 +88,15 @@ and return a non-NULL value on success, and NULL on failure. .PP The function +.BR cap_get_bound () +returns -1 if the requested capability is unknown, otherwise the +return value reflects the current state of that capability in the +prevailing bounding set. Note, a macro function, +.PP +The functions .BR cap_set_proc () +and +.BR cap_drop_bound () return zero for success, and \-1 on failure. .PP On failure, @@ -140,6 +176,9 @@ effective capabilities for the caller: cap_t caps; cap_value_t cap_list[2]; + if (!CAP_IS_SUPPORTED(CAP_SETFCAP)) + /* handle error */ + caps = cap_get_proc(); if (caps == NULL) /* handle error */; diff --git a/doc/capsh.1 b/doc/capsh.1 index 4f9273d..e68df2c 100644 --- a/doc/capsh.1 +++ b/doc/capsh.1 @@ -1,7 +1,7 @@ .\" .\" capsh.1 Man page added 2009-12-23 Andrew G. Morgan <morgan@kernel.org> .\" -.TH CAPSH 1 "2009-12-24" "libcap 2" "User Commands" +.TH CAPSH 1 "2011-04-24" "libcap 2" "User Commands" .SH NAME capsh \- capability shell wrapper .SH SYNOPSIS @@ -150,6 +150,15 @@ this effective set is 0x0100. By running: we observe that the missing capability is: .BR cap_setpcap . +.TP +.BI --supports= xxx +As the kernel evolves, more capabilities are added. This option can be used +to verify the existence of a capability on the system. For example, +.BI --supports= cap_syslog +will cause capsh to promptly exit with a status of 1 when run on +kernel 2.6.27. However, when run on kernel 2.6.38 it will silently +succeed. +.TP .SH "EXIT STATUS" Following successful execution the tool exits with status 0. Following an error, the tool immediately exits with status 1. diff --git a/doc/libcap.3 b/doc/libcap.3 index 827ce60..0e76b4e 100644 --- a/doc/libcap.3 +++ b/doc/libcap.3 @@ -111,3 +111,4 @@ and .BR cap_init (3), .BR capabilities (7), .BR getpid (2) +.BR capsh (1) diff --git a/libcap/cap_proc.c b/libcap/cap_proc.c index 7a6af39..6040c02 100644 --- a/libcap/cap_proc.c +++ b/libcap/cap_proc.c @@ -1,7 +1,7 @@ /* - * Copyright (c) 1997-8,2007 Andrew G Morgan <morgan@kernel.org> + * Copyright (c) 1997-8,2007,2011 Andrew G Morgan <morgan@kernel.org> * - * This file deals with setting capabilities on processes. + * This file deals with getting and setting capabilities on processes. */ #include "libcap.h" @@ -103,3 +103,22 @@ int capsetp(pid_t pid, cap_t cap_d) return error; } +/* get a capability from the bounding set */ + +int cap_get_bound(cap_value_t cap) +{ + int result; + + result = prctl(PR_CAPBSET_READ, cap); + return result; +} + +/* drop a capability from the bounding set */ + +int cap_drop_bound(cap_value_t cap) +{ + int result; + + result = prctl(PR_CAPBSET_DROP, cap); + return result; +} diff --git a/libcap/include/sys/capability.h b/libcap/include/sys/capability.h index c749327..4b54acc 100644 --- a/libcap/include/sys/capability.h +++ b/libcap/include/sys/capability.h @@ -93,6 +93,11 @@ extern cap_t cap_get_proc(void); extern cap_t cap_get_pid(pid_t); extern int cap_set_proc(cap_t); +extern int cap_get_bound(cap_value_t); +extern int cap_drop_bound(cap_value_t); + +#define CAP_IS_SUPPORTED(cap) (cap_get_bound(cap) >= 0) + /* libcap/cap_extint.c */ extern ssize_t cap_size(cap_t); extern ssize_t cap_copy_ext(void *, cap_t, ssize_t); diff --git a/progs/capsh.c b/progs/capsh.c index b1eb549..4c32279 100644 --- a/progs/capsh.c +++ b/progs/capsh.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Andrew G. Morgan <morgan@kernel.org> + * Copyright (c) 2008-11 Andrew G. Morgan <morgan@kernel.org> * * This is a simple 'bash' wrapper program that can be used to * raise and lower both the bset and pI capabilities before invoking @@ -80,11 +80,15 @@ int main(int argc, char *argv[], char *envp[]) if (strcmp("all", argv[i]+7) == 0) { unsigned j = 0; - while (prctl(PR_CAPBSET_READ, j) >= 0) { - if (prctl(PR_CAPBSET_DROP, j) != 0) { + while (CAP_IS_SUPPORTED(j)) { + if (cap_drop_bound(j) != 0) { + char *name_ptr; + + name_ptr = cap_to_name(j); fprintf(stderr, "Unable to drop bounding capability [%s]\n", - cap_to_name(j)); + name_ptr); + cap_free(name_ptr); exit(1); } j++; @@ -445,11 +449,12 @@ int main(int argc, char *argv[], char *envp[]) for (cap=0; (cap < 64) && (value >> cap); ++cap) { if (value & (1ULL << cap)) { - const char *ptr; + char *ptr; ptr = cap_to_name(cap); if (ptr != NULL) { printf("%s%s", sep, ptr); + cap_free(ptr); } else { printf("%s%u", sep, cap); } @@ -457,6 +462,19 @@ int main(int argc, char *argv[], char *envp[]) } } printf("\n"); + } else if (!memcmp("--supports=", argv[i], 11)) { + cap_value_t cap; + + if (cap_from_name(argv[i] + 11, &cap) < 0) { + fprintf(stderr, "cap[%s] not recognized by library\n", + argv[i] + 11); + exit(1); + } + if (!CAP_IS_SUPPORTED(cap)) { + fprintf(stderr, "cap[%s=%d] not supported by kernel\n", + argv[i] + 11, cap); + exit(1); + } } else if (!strcmp("--print", argv[i])) { unsigned cap; int set, status, j; @@ -476,17 +494,18 @@ int main(int argc, char *argv[], char *envp[]) printf("Bounding set ="); sep = ""; - for (cap=0; (set = prctl(PR_CAPBSET_READ, cap)) >= 0; cap++) { - const char *ptr; + for (cap=0; (set = cap_get_bound(cap)) >= 0; cap++) { + char *ptr; if (!set) { continue; } ptr = cap_to_name(cap); - if (ptr == 0) { + if (ptr == NULL) { printf("%s%u", sep, cap); } else { printf("%s%s", sep, ptr); + cap_free(ptr); } sep = ","; } @@ -542,6 +561,7 @@ int main(int argc, char *argv[], char *envp[]) " --help this message (or try 'man capsh')\n" " --print display capability relevant state\n" " --decode=xxx decode a hex string to a list of caps\n" + " --supports=xxx exit 1 if capability xxx unsupported\n" " --drop=xxx remove xxx,.. capabilities from bset\n" " --caps=xxx set caps as per cap_from_text()\n" " --inh=xxx set xxx,.. inheritiable set\n" |