summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew G. Morgan <morgan@kernel.org>2021-08-27 10:20:21 -0700
committerAndrew G. Morgan <morgan@kernel.org>2021-08-27 10:27:04 -0700
commitb56400f81ddd42e0e57372c957e668e6d5a72834 (patch)
tree982208eb0c9a22b013bcb702a8cfc22b26d2ab35
parent552db8f4116df3fad4e4ebf90a9a05a77b9486fd (diff)
downloadlibcap2-b56400f81ddd42e0e57372c957e668e6d5a72834.tar.gz
Implement libcap:cap_proc_root() function.
This is needed to locally configure libcap to find the pid data if the proc filesystem is not mounted at "/proc" (rare). Currently libcap only uses this info to implement cap_iab_get_pid(). This brings libcap back to parity with the Go "cap" package. Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
-rw-r--r--libcap/cap_alloc.c9
-rw-r--r--libcap/cap_test.c26
-rw-r--r--libcap/cap_text.c27
-rw-r--r--libcap/include/sys/capability.h16
4 files changed, 74 insertions, 4 deletions
diff --git a/libcap/cap_alloc.c b/libcap/cap_alloc.c
index df1a275..5733e2f 100644
--- a/libcap/cap_alloc.c
+++ b/libcap/cap_alloc.c
@@ -8,19 +8,22 @@
#include "libcap.h"
/*
- * This gets set via the pre-main() executed constructor function below it.
+ * These get set via the pre-main() executed constructor function below it.
*/
static cap_value_t _cap_max_bits;
-__attribute__((constructor (300))) static void _initialize_libcap(void) {
+__attribute__((constructor (300))) static void _initialize_libcap(void)
+{
if (_cap_max_bits) {
return;
}
cap_set_syscall(NULL, NULL);
_binary_search(_cap_max_bits, cap_get_bound, 0, __CAP_MAXBITS, __CAP_BITS);
+ cap_proc_root("/proc");
}
-cap_value_t cap_max_bits(void) {
+cap_value_t cap_max_bits(void)
+{
return _cap_max_bits;
}
diff --git a/libcap/cap_test.c b/libcap/cap_test.c
index 41192b7..9fa7300 100644
--- a/libcap/cap_test.c
+++ b/libcap/cap_test.c
@@ -118,6 +118,7 @@ static int test_alloc(void)
cap_t c;
cap_iab_t iab;
cap_launch_t launcher;
+ char *old_root;
c = cap_init();
if (c == NULL) {
@@ -153,6 +154,31 @@ static int test_alloc(void)
goto drop_launcher;
}
+ old_root = cap_proc_root("blah");
+ if (old_root == NULL || strcmp(old_root, "/proc") != 0) {
+ printf("bad initial proc_root [%s]\n", old_root);
+ retval = -1;
+ }
+ if (cap_free(old_root)) {
+ perror("unable to free old proc root");
+ retval = -1;
+ }
+ if (retval) {
+ goto drop_launcher;
+ }
+ old_root = cap_proc_root("/proc");
+ if (strcmp(old_root, "blah") != 0) {
+ printf("bad proc_root value [%s]\n", old_root);
+ retval = -1;
+ }
+ if (cap_free(old_root)) {
+ perror("unable to free replacement proc root");
+ retval = -1;
+ }
+ if (retval) {
+ goto drop_launcher;
+ }
+
drop_launcher:
if (cap_free(launcher)) {
perror("failed to free launcher");
diff --git a/libcap/cap_text.c b/libcap/cap_text.c
index a0857bc..013eb1e 100644
--- a/libcap/cap_text.c
+++ b/libcap/cap_text.c
@@ -667,6 +667,31 @@ static __u32 _parse_vec_string(__u32 *vals, const char *c, int invert)
return ~0;
}
+/*
+ * libcap believes this is the root of the mounted "/proc"
+ * filesystem
+ */
+static char *_cap_proc_dir;
+
+/*
+ * cap_proc_root reads and (optionally: when root != NULL) changes
+ * libcap's notion of where the "/proc" filesystem is mounted. It
+ * defaults to the value "/proc". Note, this is a global value and not
+ * considered thread safe to write - so the client should take
+ * suitable care when changing it. Further, libcap will allocate
+ * memory for storing the replacement root, and it is this memory that
+ * is returned. So, when changing the value, the caller should
+ * cap_free(the-return-value) when done with it.
+ */
+char *cap_proc_root(const char *root)
+{
+ char *old = _cap_proc_dir;
+ if (root != NULL) {
+ _cap_proc_dir = _libcap_strdup(root);
+ }
+ return old;
+}
+
#define PROC_LINE_MAX (8 + 8*_LIBCAP_CAPABILITY_U32S + 100)
/*
* cap_iab_get_pid fills an IAB tuple from the content of
@@ -680,7 +705,7 @@ cap_iab_t cap_iab_get_pid(pid_t pid)
FILE *file;
char line[PROC_LINE_MAX];
- if (asprintf(&path, "/proc/%d/status", pid) <= 0) {
+ if (asprintf(&path, "%s/%d/status", _cap_proc_dir, pid) <= 0) {
return NULL;
}
file = fopen(path, "r");
diff --git a/libcap/include/sys/capability.h b/libcap/include/sys/capability.h
index f98da5a..59f9377 100644
--- a/libcap/include/sys/capability.h
+++ b/libcap/include/sys/capability.h
@@ -54,6 +54,22 @@ typedef int cap_value_t;
extern cap_value_t cap_max_bits(void);
/*
+ * cap_proc_root reads and (optionally: when root != NULL) changes
+ * libcap's notion of where the "/proc" filesystem is mounted. It
+ * defaults to the value "/proc".
+ *
+ * Note, this is a global value and not considered thread safe to
+ * write - so the client should take suitable care when changing
+ * it.
+ *
+ * Further, libcap will allocate a memory copy for storing the
+ * replacement root, and it is this kind of memory that is returned.
+ * So, when changing the value, the caller should
+ * cap_free(the-return-value) when done with it.
+ */
+extern char *cap_proc_root(const char *root);
+
+/*
* Set identifiers
*/
typedef enum {