diff options
author | davidxu <davidxu@FreeBSD.org> | 2010-10-27 09:59:43 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2010-10-27 09:59:43 +0000 |
commit | 8475a5bf0d0c2eb65826e418682db2e01b87a478 (patch) | |
tree | d34701ed68d42c5b53f25b0ccc685835410c25b1 /lib/libthr/thread | |
parent | f8f25f57e2a01fbe6cab451733e71580e5353a4e (diff) | |
download | FreeBSD-src-8475a5bf0d0c2eb65826e418682db2e01b87a478.zip FreeBSD-src-8475a5bf0d0c2eb65826e418682db2e01b87a478.tar.gz |
Check small set and reject it, this is how kernel did. Always use the
size kernel is using.
Diffstat (limited to 'lib/libthr/thread')
-rw-r--r-- | lib/libthr/thread/thr_attr.c | 69 |
1 files changed, 32 insertions, 37 deletions
diff --git a/lib/libthr/thread/thr_attr.c b/lib/libthr/thread/thr_attr.c index bc8eabb..c2969e7 100644 --- a/lib/libthr/thread/thr_attr.c +++ b/lib/libthr/thread/thr_attr.c @@ -141,19 +141,14 @@ _pthread_attr_get_np(pthread_t pthread, pthread_attr_t *dstattr) struct pthread *curthread; struct pthread_attr attr, *dst; int ret; - size_t cpusetsize; + size_t kern_size; if (pthread == NULL || dstattr == NULL || (dst = *dstattr) == NULL) return (EINVAL); - cpusetsize = _get_kern_cpuset_size(); - if (dst->cpusetsize < cpusetsize) { - char *newset = realloc(dst->cpuset, cpusetsize); - if (newset == NULL) - return (errno); - memset(newset + dst->cpusetsize, 0, cpusetsize - - dst->cpusetsize); - dst->cpuset = (cpuset_t *)newset; - dst->cpusetsize = cpusetsize; + kern_size = _get_kern_cpuset_size(); + if (dst->cpuset == NULL) { + dst->cpuset = calloc(1, kern_size); + dst->cpusetsize = kern_size; } curthread = _get_curthread(); if ((ret = _thr_find_thread(curthread, pthread, /*include dead*/0)) != 0) @@ -606,27 +601,25 @@ _pthread_attr_setaffinity_np(pthread_attr_t *pattr, size_t cpusetsize, } return (0); } - - if (cpusetsize > attr->cpusetsize) { - size_t kern_size = _get_kern_cpuset_size(); - if (cpusetsize > kern_size) { - size_t i; - for (i = kern_size; i < cpusetsize; ++i) { - if (((char *)cpusetp)[i]) - return (EINVAL); - } + size_t kern_size = _get_kern_cpuset_size(); + /* Kernel rejects small set, we check it here too. */ + if (cpusetsize < kern_size) + return (ERANGE); + if (cpusetsize > kern_size) { + /* Kernel checks invalid bits, we check it here too. */ + size_t i; + for (i = kern_size; i < cpusetsize; ++i) { + if (((char *)cpusetp)[i]) + return (EINVAL); } - void *newset = realloc(attr->cpuset, cpusetsize); - if (newset == NULL) - return (ENOMEM); - attr->cpuset = newset; - attr->cpusetsize = cpusetsize; - } else { - memset(((char *)attr->cpuset) + cpusetsize, 0, - attr->cpusetsize - cpusetsize); - attr->cpusetsize = cpusetsize; } - memcpy(attr->cpuset, cpusetp, cpusetsize); + if (attr->cpuset == NULL) { + attr->cpuset = calloc(1, kern_size); + if (attr->cpuset == NULL) + return (errno); + attr->cpusetsize = kern_size; + } + memcpy(attr->cpuset, cpusetp, kern_size); ret = 0; } return (ret); @@ -642,16 +635,18 @@ _pthread_attr_getaffinity_np(const pthread_attr_t *pattr, size_t cpusetsize, if (pattr == NULL || (attr = (*pattr)) == NULL) ret = EINVAL; - else if (attr->cpuset != NULL) { - memcpy(cpusetp, attr->cpuset, MIN(cpusetsize, attr->cpusetsize)); - if (cpusetsize > attr->cpusetsize) - memset(((char *)cpusetp) + attr->cpusetsize, 0, - cpusetsize - attr->cpusetsize); - } else { + else { + /* Kernel rejects small set, we check it here too. */ size_t kern_size = _get_kern_cpuset_size(); - memset(cpusetp, -1, MIN(cpusetsize, kern_size)); + if (cpusetsize < kern_size) + return (ERANGE); + if (attr->cpuset != NULL) + memcpy(cpusetp, attr->cpuset, MIN(cpusetsize, + attr->cpusetsize)); + else + memset(cpusetp, -1, kern_size); if (cpusetsize > kern_size) - memset(((char *)cpusetp) + kern_size, 0, + memset(((char *)cpusetp) + kern_size, 0, cpusetsize - kern_size); } return (ret); |