Date: Sat, 7 Sep 2013 19:03:17 +0000 (UTC) From: Pawel Jakub Dawidek <pjd@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r255372 - head/sys/kern Message-ID: <201309071903.r87J3H53007918@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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]) !=
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201309071903.r87J3H53007918>