git: 869199d9922c - main - libsysdecode: Fix decoding of Capsicum rights
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 13 Apr 2022 14:51:47 UTC
The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=869199d9922c7dee92c1c24f95b90f1d1319433e commit 869199d9922c7dee92c1c24f95b90f1d1319433e Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2022-04-13 14:47:08 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2022-04-13 14:51:30 +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 MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D34874 --- 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 66f243eab6e6..6b0b56c3b705 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