diff --git a/sys/libprop/prop_kern.c b/sys/libprop/prop_kern.c --- a/sys/libprop/prop_kern.c +++ b/sys/libprop/prop_kern.c @@ -388,20 +388,34 @@ { prop_object_t obj = NULL; char *buf; + size_t len = pref->pref_len; int error; /* + * Sanity-check the user-supplied length: it must be non-zero and + * within the declared proplib copy-in limit. Without this guard a + * hostile plistref drives an unbounded kmalloc()+copyin() (kernel + * memory-exhaustion DoS, and pref_len + 1 wraps to 0 when + * pref_len == SIZE_MAX). prop_object_copyin_limit was already + * declared for exactly this purpose but was never consulted. + */ + if (len == 0 || len > (size_t)prop_object_copyin_limit) + return (E2BIG); + + /* * Allocate an extra byte so we can guarantee NUL-termination. * * Allow malloc to fail in case pmap would be exhausted. */ - buf = kmalloc(pref->pref_len + 1, M_TEMP, M_WAITOK); - error = copyin(pref->pref_plist, buf, pref->pref_len); + buf = kmalloc(len + 1, M_TEMP, M_WAITOK | M_NULLOK); + if (buf == NULL) + return (ENOMEM); + error = copyin(pref->pref_plist, buf, len); if (error) { kfree(buf, M_TEMP); return (error); } - buf[pref->pref_len] = '\0'; + buf[len] = '\0'; switch (type) { case PROP_TYPE_ARRAY: