Author: pjd
Date: Sat Sep  7 19:03:16 2013
New Revision: 255372
URL: http://svnweb.freebsd.org/changeset/base/255372

Log:
  Fix panic in cap_rights_is_valid() when invalid rights are provided -
  the right_to_index() function should assert correctness in this case.
  
  Improve other assertions.
  
  Reported by:  pho
  Tested by:    pho

Modified:
  head/sys/kern/subr_capability.c

Modified: head/sys/kern/subr_capability.c
==============================================================================
--- head/sys/kern/subr_capability.c     Sat Sep  7 18:55:52 2013        
(r255371)
+++ head/sys/kern/subr_capability.c     Sat Sep  7 19:03:16 2013        
(r255372)
@@ -51,7 +51,10 @@ __FBSDID("$FreeBSD$");
 #define        assert(exp)     KASSERT((exp), ("%s:%u", __func__, __LINE__))
 #endif
 
-static __inline unsigned int
+#define        CAPARSIZE_MIN   (CAP_RIGHTS_VERSION_00 + 2)
+#define        CAPARSIZE_MAX   (CAP_RIGHTS_VERSION + 2)
+
+static __inline int
 right_to_index(uint64_t right)
 {
        static const int bit2idx[] = {
@@ -61,23 +64,20 @@ right_to_index(uint64_t right)
        int idx;
 
        idx = CAPIDXBIT(right);
-       assert(idx == 1 || idx == 2 || idx == 4 || idx == 8 || idx == 16);
-
-       idx = bit2idx[idx];
-       assert(idx >= 0 && idx <= 4);
-
-       return ((unsigned int)idx);
+       assert(idx >= 0 && idx < sizeof(bit2idx) / sizeof(bit2idx[0]));
+       return (bit2idx[idx]);
 }
 
 static void
 cap_rights_vset(cap_rights_t *rights, va_list ap)
 {
-       unsigned int i, n;
        uint64_t right;
+       int i, n;
 
        assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
 
        n = CAPARSIZE(rights);
+       assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
 
        for (;;) {
                right = (uint64_t)va_arg(ap, unsigned long long);
@@ -85,6 +85,7 @@ cap_rights_vset(cap_rights_t *rights, va
                        break;
                assert(CAPRVER(right) == 0);
                i = right_to_index(right);
+               assert(i >= 0);
                assert(i < n);
                assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
                rights->cr_rights[i] |= right;
@@ -95,12 +96,13 @@ cap_rights_vset(cap_rights_t *rights, va
 static void
 cap_rights_vclear(cap_rights_t *rights, va_list ap)
 {
-       unsigned int i, n;
        uint64_t right;
+       int i, n;
 
        assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
 
        n = CAPARSIZE(rights);
+       assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
 
        for (;;) {
                right = (uint64_t)va_arg(ap, unsigned long long);
@@ -108,6 +110,7 @@ cap_rights_vclear(cap_rights_t *rights, 
                        break;
                assert(CAPRVER(right) == 0);
                i = right_to_index(right);
+               assert(i >= 0);
                assert(i < n);
                assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
                rights->cr_rights[i] &= ~(right & 0x01FFFFFFFFFFFFFFULL);
@@ -118,12 +121,13 @@ cap_rights_vclear(cap_rights_t *rights, 
 static bool
 cap_rights_is_vset(const cap_rights_t *rights, va_list ap)
 {
-       unsigned int i, n;
        uint64_t right;
+       int i, n;
 
        assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
 
        n = CAPARSIZE(rights);
+       assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
 
        for (;;) {
                right = (uint64_t)va_arg(ap, unsigned long long);
@@ -131,6 +135,7 @@ cap_rights_is_vset(const cap_rights_t *r
                        break;
                assert(CAPRVER(right) == 0);
                i = right_to_index(right);
+               assert(i >= 0);
                assert(i < n);
                assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
                if ((rights->cr_rights[i] & right) != right)
@@ -149,6 +154,7 @@ __cap_rights_init(int version, cap_right
        assert(version == CAP_RIGHTS_VERSION_00);
 
        n = version + 2;
+       assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
        memset(rights->cr_rights, 0, sizeof(rights->cr_rights[0]) * n);
        CAP_NONE(rights);
        va_start(ap, rights);
@@ -201,10 +207,14 @@ bool
 cap_rights_is_valid(const cap_rights_t *rights)
 {
        cap_rights_t allrights;
-       unsigned int i, j;
+       int i, j;
 
        if (CAPVER(rights) != CAP_RIGHTS_VERSION_00)
                return (false);
+       if (CAPARSIZE(rights) < CAPARSIZE_MIN ||
+           CAPARSIZE(rights) > CAPARSIZE_MAX) {
+               return (false);
+       }
        CAP_ALL(&allrights);
        if (!cap_rights_contains(&allrights, rights))
                return (false);
@@ -233,6 +243,7 @@ cap_rights_merge(cap_rights_t *dst, cons
        assert(cap_rights_is_valid(dst));
 
        n = CAPARSIZE(dst);
+       assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
 
        for (i = 0; i < n; i++)
                dst->cr_rights[i] |= src->cr_rights[i];
@@ -253,6 +264,7 @@ cap_rights_remove(cap_rights_t *dst, con
        assert(cap_rights_is_valid(dst));
 
        n = CAPARSIZE(dst);
+       assert(n >= CAPARSIZE_MIN && n <= CAPARSIZE_MAX);
 
        for (i = 0; i < n; i++) {
                dst->cr_rights[i] &=
@@ -273,6 +285,7 @@ cap_rights_contains(const cap_rights_t *
        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]) !=
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to