diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -190,8 +190,21 @@ if (regset == NULL) return (EINVAL); + if (regset->get == NULL) + return (EINVAL); + + size = regset->size; + /* + * The regset is dynamically sized, e.g. the size could change + * depending on the hardware, or may have a per-thread size. + */ + if (size == 0) { + if (!regset->get(regset, td, NULL, &size)) + return (EINVAL); + } + if (iov->iov_base == NULL) { - iov->iov_len = regset->size; + iov->iov_len = size; if (iov->iov_len == 0) return (EINVAL); @@ -199,14 +212,10 @@ } /* The length is wrong, return an error */ - if (iov->iov_len != regset->size) - return (EINVAL); - - if (regset->get == NULL) + if (iov->iov_len != size) return (EINVAL); error = 0; - size = regset->size; p = td->td_proc; /* Drop the proc lock while allocating the temp buffer */ @@ -218,7 +227,7 @@ if (!regset->get(regset, td, buf, &size)) { error = EINVAL; } else { - KASSERT(size == regset->size, + KASSERT(size == regset->size || regset->size == 0, ("%s: Getter function changed the size", __func__)); iov->iov_len = size; @@ -245,14 +254,23 @@ if (regset == NULL) return (EINVAL); + size = regset->size; + /* + * The regset is dynamically sized, e.g. the size could change + * depending on the hardware, or may have a per-thread size. + */ + if (size == 0) { + if (!regset->get(regset, td, NULL, &size)) + return (EINVAL); + } + /* The length is wrong, return an error */ - if (iov->iov_len != regset->size) + if (iov->iov_len != size) return (EINVAL); if (regset->set == NULL) return (EINVAL); - size = regset->size; p = td->td_proc; /* Drop the proc lock while allocating the temp buffer */