DF-5678 / fix.diff
--- a/sys/libprop/prop_array.c +++ b/sys/libprop/prop_array.c @@ -645,7 +645,15 @@ goto out; } - _PROP_ASSERT(idx < pa->pa_count); + /* + * Real bounds check, not just an INVARIANTS-only assert: with the + * assert compiled out (kernel built without INVARIANTS), an + * idx > pa->pa_count used to fall through to an out-of-bounds + * read/write of pa_array[] plus prop_object_release() of the OOB + * value. prop_array_get() already real-checks; mirror it here. + */ + if (idx > pa->pa_count) + goto out; opo = pa->pa_array[idx]; _PROP_ASSERT(opo != NULL); @@ -698,7 +706,16 @@ _PROP_RWLOCK_WRLOCK(pa->pa_rwlock); - _PROP_ASSERT(idx < pa->pa_count); + /* + * Same as prop_array_set(): enforce the index bound for real -- + * the old assert-only check left an OOB read of pa_array[idx] + * followed by prop_object_release() of the garbage pointer on + * kernels built without INVARIANTS. + */ + if (idx >= pa->pa_count) { + _PROP_RWLOCK_UNLOCK(pa->pa_rwlock); + return; + } /* XXX Should this be a _PROP_ASSERT()? */ if (prop_array_is_immutable(pa)) { |