The branch stable/13 has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=91d3f40d93e3cda1a04eb0b36158a74c67c62e37

commit 91d3f40d93e3cda1a04eb0b36158a74c67c62e37
Author:     Mark Johnston <ma...@freebsd.org>
AuthorDate: 2022-04-13 14:47:08 +0000
Commit:     Mark Johnston <ma...@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

Reply via email to