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

Arnout Vandecappelle arnout at mind.be
Mon Jan 4 19:10:33 UTC 2016


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



More information about the busybox mailing list