ping On 01-12-15 13:52, Arnout Vandecappelle (Essensium/Mind) wrote: > The non-fancy version of the from_cpuset uses CPU_SETSIZE as if it > represents the number of bytes in the cpuset, while it is actually > the number of bits. This leads to out-of-bounds accesses on the > cpu_set_t in the big-endian case. Basically all uses of CPU_SETSIZE > have to be divided by 8. This is done correctly in the fancy version > of from_cpuset. > > In addition, the big-endian case is completely wrong to begin with. > All standard C libraries that I know of implement cpu_set_t as an > unsigned long array, so both for big and little endian, the least > significant bits are in the beginning of the array. Therefore, the > approach taken for the little endian case is equally valid. We only > need special handling for big endian when CPU_SETSIZE is large and > we use an unsigned long long to get more bits out. > > Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <[email protected]> > --- > miscutils/taskset.c | 35 ++++++++++++++++++----------------- > 1 file changed, 18 insertions(+), 17 deletions(-) > > diff --git a/miscutils/taskset.c b/miscutils/taskset.c > index 100b1d9..18a4b67 100644 > --- a/miscutils/taskset.c > +++ b/miscutils/taskset.c > @@ -75,27 +75,28 @@ static char *from_cpuset(cpu_set_t *mask) > #define TASKSET_PRINTF_MASK "%llx" > static unsigned long long from_cpuset(cpu_set_t *mask) > { > - char *p = (void*)mask; > + BUILD_BUG_ON((CPU_SETSIZE/8) < sizeof(int)); > > - BUILD_BUG_ON(CPU_SETSIZE < sizeof(int)); > - > - /* Take the least significant bits. Careful! > - * Consider both CPU_SETSIZE=4 and CPU_SETSIZE=1024 cases > + /* Take the least significant bits. Assume cpu_set_t is > + * implemented as an array of unsigned long or unsigned > + * int. > */ > + if ((CPU_SETSIZE/8) < sizeof(long)) > + return *(unsigned*)mask; > + if ((CPU_SETSIZE/8) < sizeof(long long)) > + return *(unsigned long*)mask; > #if BB_BIG_ENDIAN > - /* For big endian, it means LAST bits */ > - if (CPU_SETSIZE < sizeof(long)) > - p += CPU_SETSIZE - sizeof(int); > - else if (CPU_SETSIZE < sizeof(long long)) > - p += CPU_SETSIZE - sizeof(long); > - else > - p += CPU_SETSIZE - sizeof(long long); > + if (sizeof(unsigned long long) > sizeof(unsigned long)) { > + /* We can put two long in the long long, but they have to > + * be swapped: the least significant word comes first in the > + * array */ > + unsigned long *p = (void*)mask; > + return (unsigned long long)*p + > + ((unsigned long long)*(p+1) << (8*sizeof(unsigned > long))); > + } > +#else > + return *(unsigned long long*)mask; > #endif > - if (CPU_SETSIZE < sizeof(long)) > - return *(unsigned*)p; > - if (CPU_SETSIZE < sizeof(long long)) > - return *(unsigned long*)p; > - return *(unsigned long long*)p; > } > #endif > >
-- Arnout Vandecappelle arnout dot vandecappelle at essensium dot com Senior Embedded Software Architect . . . . . . +32-478-010353 (mobile) Essensium, Mind division . . . . . . . . . . . . . . http://www.mind.be G.Geenslaan 9, 3001 Leuven, Belgium . . . . . BE 872 984 063 RPR Leuven LinkedIn profile: http://www.linkedin.com/in/arnoutvandecappelle GPG fingerprint: 7493 020B C7E3 8618 8DEC 222C 82EB F404 F9AC 0DDF _______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
