git: 91d3f40d93e3 - stable/13 - libsysdecode: Fix decoding of Capsicum rights
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 22 Apr 2022 15:25:04 UTC
The branch stable/13 has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=91d3f40d93e3cda1a04eb0b36158a74c67c62e37
commit 91d3f40d93e3cda1a04eb0b36158a74c67c62e37
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2022-04-13 14:47:08 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2022-04-22 14:36:22 +0000
libsysdecode: Fix decoding of Capsicum rights
Capsicum rights are a bit tricky since some of them are subsets of
others, and one can have rights R1 and R2 such that R1 is a subset of
R2, but there is no collection of named rights whose union is R2. So,
they don't behave like most other flag sets. sysdecode_cap_rights(3)
does not handle this properly and so can emit misleading decodings.
Try to fix all of these problems:
- Include composite rights in the caprights table.
- Use a constructor to sort the caprights table such that "larger"
rights appear first and thus are matched first.
- Don't print rights that are a subset of rights already printed, so as
to minimize the length of the output.
- Print a trailing message if some of the specific rights are not
matched by the table.
PR: 263165
Reviewed by: pauamma_gundo.com (doc), jhb, emaste
Sponsored by: The FreeBSD Foundation
(cherry picked from commit 869199d9922c7dee92c1c24f95b90f1d1319433e)
---
lib/libsysdecode/flags.c | 53 +++++++++++++++++++++++++++++++--
lib/libsysdecode/mktables | 2 +-
lib/libsysdecode/sysdecode_cap_rights.3 | 23 +++++++++++++-
3 files changed, 73 insertions(+), 5 deletions(-)
diff --git a/lib/libsysdecode/flags.c b/lib/libsysdecode/flags.c
index 35bce1ff77f9..f02c8dd8b339 100644
--- a/lib/libsysdecode/flags.c
+++ b/lib/libsysdecode/flags.c
@@ -1171,7 +1171,8 @@ sysdecode_umtx_rwlock_flags(FILE *fp, u_long flags, u_long *rem)
void
sysdecode_cap_rights(FILE *fp, cap_rights_t *rightsp)
{
- struct name_table *t;
+ cap_rights_t diff, sum, zero;
+ const struct name_table *t;
int i;
bool comma;
@@ -1181,13 +1182,59 @@ sysdecode_cap_rights(FILE *fp, cap_rights_t *rightsp)
return;
}
}
- comma = false;
- for (t = caprights; t->str != NULL; t++) {
+ cap_rights_init(&sum);
+ diff = *rightsp;
+ for (t = caprights, comma = false; t->str != NULL; t++) {
if (cap_rights_is_set(rightsp, t->val)) {
+ cap_rights_clear(&diff, t->val);
+ if (cap_rights_is_set(&sum, t->val)) {
+ /* Don't print redundant rights. */
+ continue;
+ }
+ cap_rights_set(&sum, t->val);
+
fprintf(fp, "%s%s", comma ? "," : "", t->str);
comma = true;
}
}
+ if (!comma)
+ fprintf(fp, "CAP_NONE");
+
+ /*
+ * Provide a breadcrumb if some of the provided rights are not included
+ * in the table, likely due to a bug in the mktables script.
+ */
+ CAP_NONE(&zero);
+ if (!cap_rights_contains(&zero, &diff))
+ fprintf(fp, ",unknown rights");
+}
+
+/*
+ * Pre-sort the set of rights, which has a partial ordering defined by the
+ * subset relation. This lets sysdecode_cap_rights() print a list of minimal
+ * length with a single pass over the "caprights" table.
+ */
+static void __attribute__((constructor))
+sysdecode_cap_rights_init(void)
+{
+ cap_rights_t tr, qr;
+ struct name_table *t, *q, tmp;
+ bool swapped;
+
+ do {
+ for (t = caprights, swapped = false; t->str != NULL; t++) {
+ cap_rights_init(&tr, t->val);
+ for (q = t + 1; q->str != NULL; q++) {
+ cap_rights_init(&qr, q->val);
+ if (cap_rights_contains(&qr, &tr)) {
+ tmp = *t;
+ *t = *q;
+ *q = tmp;
+ swapped = true;
+ }
+ }
+ }
+ } while (swapped);
}
static struct name_table cmsgtypeip[] = {
diff --git a/lib/libsysdecode/mktables b/lib/libsysdecode/mktables
index c9c6830b04aa..5003be201fbd 100644
--- a/lib/libsysdecode/mktables
+++ b/lib/libsysdecode/mktables
@@ -159,7 +159,7 @@ gen_table "msgflags" "MSG_[A-Z_]+[[:space:]]+0x[0-9]+" "sys/
gen_table "sigcode" "SI_[A-Z]+[[:space:]]+0(x[0-9abcdef]+)?" "sys/signal.h"
gen_table "umtxcvwaitflags" "CVWAIT_[A-Z_]+[[:space:]]+0x[0-9]+" "sys/umtx.h"
gen_table "umtxrwlockflags" "URWLOCK_PREFER_READER[[:space:]]+0x[0-9]+" "sys/umtx.h"
-gen_table "caprights" "CAP_[A-Z_]+[[:space:]]+CAPRIGHT\([0-9],[[:space:]]+0x[0-9]{16}ULL\)" "sys/capsicum.h"
+gen_table "caprights" "CAP_[A-Z_]+[[:space:]]+((CAPRIGHT\([0-9],[[:space:]]+0x[0-9]{16}ULL\))|(\(CAP_[A-Z_]+[[:space:]]*\|.*\)))" "sys/capsicum.h"
gen_table "sctpprpolicy" "SCTP_PR_SCTP_[A-Z_]+[[:space:]]+0x[0-9]+" "netinet/sctp_uio.h" "SCTP_PR_SCTP_ALL"
gen_table "cmsgtypesocket" "SCM_[A-Z_]+[[:space:]]+0x[0-9]+" "sys/socket.h"
if [ -e "${include_dir}/x86/sysarch.h" ]; then
diff --git a/lib/libsysdecode/sysdecode_cap_rights.3 b/lib/libsysdecode/sysdecode_cap_rights.3
index 674e12ad3a01..e165e3d43938 100644
--- a/lib/libsysdecode/sysdecode_cap_rights.3
+++ b/lib/libsysdecode/sysdecode_cap_rights.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 24, 2017
+.Dd April 11, 2022
.Dt sysdecode_cap_rights 3
.Os
.Sh NAME
@@ -46,5 +46,26 @@ function outputs a comma-separated list of capability rights at
.Fa rightsp
to the stream
.Fa fp .
+.Pp
+Note that some capability rights are supersets of others; for example,
+.Dv CAP_PREAD
+is the union of
+.Dv CAP_READ
+and
+.Dv CAP_SEEK .
+.Fn sysdecode_cap_rights
+emits a minimal list of rights whose union is equal to
+.Fa *rightsp .
+For example, if both
+.Dv CAP_READ
+and
+.Dv CAP_SEEK
+are set in
+.Fa *rightsp ,
+then
+.Fn sysdecode_cap_rights
+will include only
+.Dv CAP_PREAD
+in the output list.
.Sh SEE ALSO
.Xr sysdecode 3