From 3e10f4077a399d53510af0923f7c4183e41a0d45 Mon Sep 17 00:00:00 2001 From: Craig Small Date: Mon, 1 Jul 2024 23:06:22 +1000 Subject: [PATCH] library: Add capability naming The library has a helper function to return a list of capabilities when given the hexadecimal capability mask. Tested/compared to pscap and the agree. Signed-off-by: Craig Small --- Makefile.am | 37 ++++++++++++++ NEWS | 1 + library/capname.c | 106 +++++++++++++++++++++++++++++++++++++++++ library/include/misc.h | 2 + library/libproc2.sym | 1 + library/signames.c | 2 +- local/capnames.h | 57 ++++++++++++++++++++++ man/procps_misc.3 | 22 ++++++++- 8 files changed, 226 insertions(+), 2 deletions(-) create mode 100644 library/capname.c create mode 100644 local/capnames.h diff --git a/Makefile.am b/Makefile.am index d50e0352..c654f1a1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -270,6 +270,8 @@ library_libproc2_la_LDFLAGS = \ -Wl,--version-script=$(top_srcdir)/library/libproc2.sym library_libproc2_la_SOURCES = \ + library/capname.c \ + local/capnames.h \ library/devname.c \ library/include/devname.h \ library/diskstats.c \ @@ -426,6 +428,41 @@ $(top_srcdir)/.version: dist-hook: echo $(VERSION) > $(distdir)/.tarball-version +# Generate capability names - if it needs updating +define capnames_header +/* + * capnames.h : Definition of Capability Names + * + * This is an auto-generated file, do not edit + */ + +#ifndef PROCPS_CAPNAMES_H +#define PROCPS_CAPNAMES_H + +static const char *cap_names[] = { +endef +define capnames_footer + +#endif /* CAPNAMES_H */ +endef +export capnames_header +export capnames_footer +LNX_CAP_HEADER = /usr/include/linux/capability.h + +local/capnames.h: Makefile + @if [ -e $(LNX_CAP_HEADER) ] ; then \ + echo "$$capnames_header" > $@; \ + last_capname=`sed -n -e 's/^#define\s*CAP_LAST_CAP\s*\([A-Z_]*\)$$/\1/p' $(LNX_CAP_HEADER)`; \ + capability_count=`sed -n -e "s/^#define\s*$$last_capname\s*\([0-9]*\)$$/\1/p" $(LNX_CAP_HEADER)`; \ + sed -n -e 's/^#define\s*CAP_\([A-Z_]*\)\s*\([0-9]*\)$$/ [\2] = \"\L\1\",/p' $(LNX_CAP_HEADER) >> $@; \ + echo -e "};\n\n" >> $@; \ + echo "#define CAPABILITY_COUNT $$capability_count" >> $@; \ + echo "$$capnames_footer" >> $@; \ + echo ""; \ + else \ + echo "Header file $(LNX_CAP_HEADER) not found, cannot rebuild $@"; \ + fi + get-trans: echo "Getting the latest translations from translationproject.org..." rsync -Lrtvz translationproject.org::tp/latest/procps-ng/ po diff --git a/NEWS b/NEWS index fc5b9c06..8654aeca 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,7 @@ procps-ng-NEXT external: pids api now provides open file descriptors external: 'info' parm removed from all 'VAL' macros issue #332 external: Add procps_sigmask_names + external: Add procps_capability_names external: Add PIDS_CAP__PRM Permitted Capabilities * pgrep: select process by environment variable issue #167 * pgrep: Rework pidfile reading to include stdin issue #318 diff --git a/library/capname.c b/library/capname.c new file mode 100644 index 00000000..bc612181 --- /dev/null +++ b/library/capname.c @@ -0,0 +1,106 @@ +/* + * capnames.c - Translate capability mask names + * + * Copyright © 2024 Craig Small + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +//#include +//#//include +#include +#include +#include +//#include +//#include +#include +//#include +//#include +//#include +//#include +#include +//#include +//#include +//#include +//#include +//#include + + +#include "procps-private.h" +#include "escape.h" +#include "capnames.h" +#include "misc.h" + +#define FULL_CAP "full" +#define FULL_CAP_MASK 0x1ffffffffff + +static bool capability_isset(const uint64_t mask, const int cnum) +{ + return (mask & ((uint64_t) 1 << (cnum))); +} + +PROCPS_EXPORT int procps_capability_names(char *restrict const buf, const char *restrict const capmask, const size_t buflen) +{ + unsigned int i; + char *c = buf; + size_t len = buflen; + uint64_t mask_in; + + // buffer must be at least 2 for "-\0" + if (buf == NULL || capmask == NULL || buflen < 2) + return -EINVAL; + + if (1 != sscanf(capmask, "%" PRIx64, &mask_in)) + return -EINVAL; + + if (mask_in == 0) { + strcpy(buf, "-"); + return 1; + } + + if (mask_in == FULL_CAP_MASK) { + size_t namelen; + namelen = strlen(FULL_CAP); + if (namelen+1 >= len) { + strcpy(c, "+"); + return 1; + } + strcpy(c,FULL_CAP); + return namelen; + } + + for (i=0; i <= (CAPABILITY_COUNT) ; i++) + { + if (capability_isset(mask_in, i)) { + if (cap_names[i] != NULL) { // We have a name for this capability + int namelen; + namelen = strlen(cap_names[i]); + if (namelen+1 >= len) { + strcpy(c, "+"); + len -= 1; + c += 1; + break; + } else { + namelen = snprintf(c, len, (c==buf)?"%s":",%s", + cap_names[i]); + len -= namelen; + c+= namelen; + } + } + } + } + return (int) (c-buf); +} diff --git a/library/include/misc.h b/library/include/misc.h index b101c044..e464e4ec 100644 --- a/library/include/misc.h +++ b/library/include/misc.h @@ -89,6 +89,8 @@ int procps_ns_read_pid (const int pid, struct procps_ns *nsp); // Signal names int procps_sigmask_names(char *restrict const outbuf, const char *restrict const sigmask, const size_t len); +// Capability names +int procps_capability_names(char *restrict const buf, const char *restrict const capmask, const size_t buflen); #ifdef __cplusplus } #endif diff --git a/library/libproc2.sym b/library/libproc2.sym index 3347c09d..b45b6d2a 100644 --- a/library/libproc2.sym +++ b/library/libproc2.sym @@ -74,4 +74,5 @@ LIBPROC_2.1 { LIBPROC_2.2 { procps_sigmask_names; + procps_capability_names; } LIBPROC_2.1; diff --git a/library/signames.c b/library/signames.c index 8b02be73..8040e699 100644 --- a/library/signames.c +++ b/library/signames.c @@ -148,7 +148,7 @@ PROCPS_EXPORT int procps_sigmask_names(char *restrict const outbuf, const char * return -EINVAL; mask = mask_in; - for (i=1; i < NSIG; i++) { + for (i=0; i < NSIG; i++) { test_val = mask_sig_val_num(i); if (test_val & mask) { n = strlen(sigstat_strsignal_abbrev(i, abbrev, SIGNAME_MAX)); diff --git a/local/capnames.h b/local/capnames.h new file mode 100644 index 00000000..8d36d4ce --- /dev/null +++ b/local/capnames.h @@ -0,0 +1,57 @@ +/* + * capnames.h : Definition of Capability Names + * + * This is an auto-generated file, do not edit + */ + +#ifndef PROCPS_CAPNAMES_H +#define PROCPS_CAPNAMES_H + +static const char *cap_names[] = { + [0] = "chown", + [1] = "dac_override", + [2] = "dac_read_search", + [3] = "fowner", + [4] = "fsetid", + [5] = "kill", + [6] = "setgid", + [7] = "setuid", + [8] = "setpcap", + [9] = "linux_immutable", + [10] = "net_bind_service", + [11] = "net_broadcast", + [12] = "net_admin", + [13] = "net_raw", + [14] = "ipc_lock", + [15] = "ipc_owner", + [16] = "sys_module", + [17] = "sys_rawio", + [18] = "sys_chroot", + [19] = "sys_ptrace", + [20] = "sys_pacct", + [21] = "sys_admin", + [22] = "sys_boot", + [23] = "sys_nice", + [24] = "sys_resource", + [25] = "sys_time", + [26] = "sys_tty_config", + [27] = "mknod", + [28] = "lease", + [29] = "audit_write", + [30] = "audit_control", + [31] = "setfcap", + [32] = "mac_override", + [33] = "mac_admin", + [34] = "syslog", + [35] = "wake_alarm", + [36] = "block_suspend", + [37] = "audit_read", + [38] = "perfmon", + [39] = "bpf", + [40] = "checkpoint_restore", +}; + + +#define CAPABILITY_COUNT 40 + +#endif /* CAPNAMES_H */ diff --git a/man/procps_misc.3 b/man/procps_misc.3 index a4b5847c..c752b18e 100644 --- a/man/procps_misc.3 +++ b/man/procps_misc.3 @@ -52,6 +52,12 @@ Signal mask Particulars .RS 4 .RI "int \fB procps_sigmask_names\fR (char *restrict const " outbuf ", const char *restrict const " sigmask ", const size_t " len ");" .RE +.PP +Capability Particulars +.PP +.RS 4 +.RI "int \fB procps_capability_names\fR (char *restrict const " outbuf ", const char *restrict const " capmask ", const size_t " len ");" +.RE .P Link with \fI\-lproc2\fP. .SH DESCRIPTION @@ -172,7 +178,21 @@ are blocked, ignored or caught (see .BR signal (7)). If the list of signals exceeds \fIlen\fR bytes, the string will be truncated and will end with a '+'. It is up to the calling program to ensure that \fIoutbuf\fR -is correctly allocated with at least \fIlen\fRbytes. +is correctly allocated with at least \fIlen\fR bytes. +.P +.BR procps_capability_names () +Fills \fIoutbuf\fR with a human-readable text string of up to \fIlen\fR +bytes of the capabilites set in the hexadecimal capability mask \fIcapmask\fR. +This is used to provide additional information from the capabilities as returned +by the \fBprocps_pids_*\fR functions for the capabilities given to a process. See +.BR capabilities (7)). +If the list of capabilities exceeds \fIlen\fR bytes, the string will be truncated and +will end with a '+'. It is up to the calling program to ensure that \fIoutbuf\fR +is correctly allocated with at least \fIlen\fR bytes. +.P +For a process that has no capabilities or all capabilities the string will be +"-" and "full" respectively. + .SH RETURN VALUE .SS Functions Returning an \[oq]int\[cq] or \[oq]long\[cq] An error will be indicated by a negative number that