[PATCH] taskset: fix non-fancy cpuset printing on big-endian

Denys Vlasenko vda.linux at googlemail.com
Sun Feb 14 18:05:21 UTC 2016


Applied, thanks!

On Mon, Jan 4, 2016 at 8:10 PM, Arnout Vandecappelle <arnout at mind.be> wrote:
> 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) <arnout at mind.be>
>> ---
>>  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
> busybox at busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox


More information about the busybox mailing list