[Skiboot] [PATCH 2/8] fsp/leds: improve string operations bounds checking

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Tue May 7 16:48:37 AEST 2019


On 04/27/2019 08:14 PM, Nicholas Piggin wrote:
> The current code has a few possible issues with string handling, and
> the compiler really doesn't like it when enabling more warnings.
> 
> Issues:
> 
> - Mixing of NUL terminated arrays (in most cases), and non-NUL in the

s/NUL/NULL/

>    input/output buffer format. memcpy generally should be used when the
>    length is known.
> - Lack of input data length bounds checking. Malformed input could
>    cause overruns.
> - String copying from same sized source and destination array sizes,
>    where the source is a NUL terminated string, so the strncpy copies
>    the string without its NUL terminator, which becomes NUL terminated
>    at the zeroed destination array. Compiler does not like this, and
>    it only works if the destination has been zeroed, so not a great
>    pattern.
> - Attemping to NUL terminate string using strcat, which will overwrite
>    a byte past the end of the array if the string length is at maximum,
>    or worse if the input was malformed.
> 
> This patch tries to fix up a few, and ends up silencing the compiler
> warnings I'm looking at, but in general the file probably wants an
> audit and rework of the string handling.
> 
> *** Untested ***

Patch looks good to me.

Reviewed-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
Tested-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>

-Vasant

> 
> Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
> ---
>   hw/fsp/fsp-leds.c | 31 +++++++++++++++++--------------
>   1 file changed, 17 insertions(+), 14 deletions(-)
> 
> diff --git a/hw/fsp/fsp-leds.c b/hw/fsp/fsp-leds.c
> index 9040c0a4d..edfda51da 100644
> --- a/hw/fsp/fsp-leds.c
> +++ b/hw/fsp/fsp-leds.c
> @@ -534,8 +534,11 @@ static int fsp_msg_set_led_state(struct led_set_cmd *spcn_cmd)
>   	u32 cmd = FSP_RSP_SET_LED_STATE;
>   	int rc = -1;
> 
> +	memset(sled.lc_code, 0, LOC_CODE_SIZE);
>   	sled.lc_len = strlen(spcn_cmd->loc_code);
> -	strncpy(sled.lc_code, spcn_cmd->loc_code, sled.lc_len);
> +	if (sled.lc_len >= LOC_CODE_SIZE)
> +		sled.lc_len = LOC_CODE_SIZE - 1;
> +	strncpy(sled.lc_code, spcn_cmd->loc_code, LOC_CODE_SIZE - 1);
> 
>   	lock(&led_lock);
> 
> @@ -604,8 +607,8 @@ static int fsp_msg_set_led_state(struct led_set_cmd *spcn_cmd)
>   	}
> 
>   	/* Write into SPCN TCE buffer */
> -	buf_write(buf, u8, sled.lc_len);	 /* Location code length */
> -	strncpy(buf, sled.lc_code, sled.lc_len); /* Location code */
> +	buf_write(buf, u8, sled.lc_len);	/* Location code length */
> +	memcpy(buf, sled.lc_code, sled.lc_len);	/* Location code */
>   	buf += sled.lc_len;
>   	buf_write(buf, u16, sled.state);	/* LED state */
> 
> @@ -780,7 +783,7 @@ static u32 fsp_push_data_to_tce(struct fsp_led_data *led, u8 *out_data,
>   	/* Location code */
>   	memset(lcode.loc_code, 0, LOC_CODE_SIZE);
>   	lcode.raw_len = strlen(led->loc_code);
> -	strncpy(lcode.loc_code, led->loc_code, lcode.raw_len);
> +	strncpy(lcode.loc_code, led->loc_code, LOC_CODE_SIZE - 1);
>   	lcode.fld_sz = sizeof(lcode.loc_code);
> 
>   	/* Rest of the structure */
> @@ -1631,6 +1634,8 @@ static void fsp_process_leds_data(u16 len)
>   	 */
>   	buf = led_buffer;
>   	while (len) {
> +		size_t lc_len;
> +
>   		/* Prepare */
>   		led_data = zalloc(sizeof(struct fsp_led_data));
>   		assert(led_data);
> @@ -1643,14 +1648,18 @@ static void fsp_process_leds_data(u16 len)
>   		buf_read(buf, u8, &led_data->lc_len);
>   		len -= sizeof(led_data->lc_len);
> 
> -		if (led_data->lc_len == 0) {
> +		lc_len = led_data->lc_len;
> +		if (lc_len == 0) {
>   			free(led_data);
>   			break;
>   		}
> 
> +		if (lc_len >= LOC_CODE_SIZE)
> +			lc_len = LOC_CODE_SIZE - 1;
> +
>   		/* Location code */
> -		strncpy(led_data->loc_code, buf, led_data->lc_len);
> -		strcat(led_data->loc_code, "\0");
> +		strncpy(led_data->loc_code, buf, lc_len);
> +		led_data->loc_code[lc_len] = '\0';
> 
>   		buf += led_data->lc_len;
>   		len -= led_data->lc_len;
> @@ -1673,13 +1682,7 @@ static void fsp_process_leds_data(u16 len)
>   			assert(encl_led_data);
> 
>   			/* copy over the original */
> -			encl_led_data->rid = led_data->rid;
> -			encl_led_data->lc_len = led_data->lc_len;
> -			strncpy(encl_led_data->loc_code, led_data->loc_code,
> -				led_data->lc_len);
> -			encl_led_data->loc_code[led_data->lc_len] = '\0';
> -			encl_led_data->parms = led_data->parms;
> -			encl_led_data->status = led_data->status;
> +			memcpy(encl_led_data, led_data, sizeof(struct fsp_led_data));
> 
>   			/* Add to the list of enclosure LEDs */
>   			list_add_tail(&encl_ledq, &encl_led_data->link);
> 



More information about the Skiboot mailing list