mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
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
This commit is contained in:
parent
4ad3423bc2
commit
869199d992
|
@ -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[] = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue