Author: mjg
Date: Mon Feb  3 17:08:11 2020
New Revision: 357452
URL: https://svnweb.freebsd.org/changeset/base/357452

Log:
  capsicum: faster cap_rights_contains
  
  Instead of doing a 2 iteration loop (determined at runeimt), take advantage
  of the fact that the size is already known.
  
  While here provdie cap_check_inline so that fget_unlocked does not have to
  do a function call.
  
  Verified with the capsicum suite /usr/tests.

Modified:
  head/sys/kern/kern_descrip.c
  head/sys/kern/subr_capability.c
  head/sys/kern/sys_capability.c
  head/sys/sys/capsicum.h

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c        Mon Feb  3 17:06:21 2020        
(r357451)
+++ head/sys/kern/kern_descrip.c        Mon Feb  3 17:08:11 2020        
(r357452)
@@ -2724,7 +2724,7 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights
                if (fp == NULL)
                        return (EBADF);
 #ifdef CAPABILITIES
-               error = cap_check(&haverights, needrightsp);
+               error = cap_check_inline(&haverights, needrightsp);
                if (error != 0)
                        return (error);
 #endif

Modified: head/sys/kern/subr_capability.c
==============================================================================
--- head/sys/kern/subr_capability.c     Mon Feb  3 17:06:21 2020        
(r357451)
+++ head/sys/kern/subr_capability.c     Mon Feb  3 17:08:11 2020        
(r357452)
@@ -394,25 +394,3 @@ cap_rights_remove(cap_rights_t *dst, const cap_rights_
 
        return (dst);
 }
-
-bool
-cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little)
-{
-       unsigned int i, n;
-
-       assert(CAPVER(big) == CAP_RIGHTS_VERSION_00);
-       assert(CAPVER(little) == CAP_RIGHTS_VERSION_00);
-       assert(CAPVER(big) == CAPVER(little));
-
-       n = CAPARSIZE(big);
-       assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
-
-       for (i = 0; i < n; i++) {
-               if ((big->cr_rights[i] & little->cr_rights[i]) !=
-                   little->cr_rights[i]) {
-                       return (false);
-               }
-       }
-
-       return (true);
-}

Modified: head/sys/kern/sys_capability.c
==============================================================================
--- head/sys/kern/sys_capability.c      Mon Feb  3 17:06:21 2020        
(r357451)
+++ head/sys/kern/sys_capability.c      Mon Feb  3 17:08:11 2020        
(r357452)
@@ -179,6 +179,17 @@ cap_check(const cap_rights_t *havep, const cap_rights_
        return (_cap_check(havep, needp, CAPFAIL_NOTCAPABLE));
 }
 
+int
+cap_check_failed_notcapable(const cap_rights_t *havep, const cap_rights_t 
*needp)
+{
+
+#ifdef KTRACE
+       if (KTRPOINT(curthread, KTR_CAPFAIL))
+               ktrcapfail(CAPFAIL_NOTCAPABLE, needp, havep);
+#endif
+       return (ENOTCAPABLE);
+}
+
 /*
  * Convert capability rights into VM access flags.
  */

Modified: head/sys/sys/capsicum.h
==============================================================================
--- head/sys/sys/capsicum.h     Mon Feb  3 17:06:21 2020        (r357451)
+++ head/sys/sys/capsicum.h     Mon Feb  3 17:08:11 2020        (r357452)
@@ -342,8 +342,37 @@ bool __cap_rights_is_set(const cap_rights_t *rights, .
 bool cap_rights_is_valid(const cap_rights_t *rights);
 cap_rights_t *cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
 cap_rights_t *cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
-bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
 void __cap_rights_sysinit(void *arg);
+
+
+/*
+ * We only support one size to reduce branching.
+ */
+_Static_assert(CAP_RIGHTS_VERSION == CAP_RIGHTS_VERSION_00,
+    "unsupported version of capsicum rights");
+
+static inline bool
+cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little)
+{
+
+        if (__predict_true(
+            (big->cr_rights[0] & little->cr_rights[0]) == little->cr_rights[0] 
&&
+            (big->cr_rights[1] & little->cr_rights[1]) == 
little->cr_rights[1]))
+                return (true);
+        return (false);
+}
+
+int cap_check_failed_notcapable(const cap_rights_t *havep,
+    const cap_rights_t *needp);
+
+static inline int
+cap_check_inline(const cap_rights_t *havep, const cap_rights_t *needp)
+{
+
+        if (__predict_false(!cap_rights_contains(havep, needp)))
+               return (cap_check_failed_notcapable(havep, needp));
+        return (0);
+}
 
 __END_DECLS
 struct cap_rights_init_args {
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to