래퍼런스

cvedetails.com

git.kernel.org

분석

커밋 메시지

제목: iio: light: veml6075_read_int_time_ms 함수에 배열 경계 확인 추가

배열에는 5개의 요소만 있지만 veml6075_read_int_time_index로 계산된 인덱스는 0에서 7까지의 범위를 가질 수 있어, 배열의 경계를 벗어나는 접근(out-of-bounds access)이 발생할 수 있습니다. 이 확인 코드는 해당 문제를 방지합니다.

Coverity 문제:

CID 1574309: (1/1): 배열 경계를 벗어난 읽기 (OVERRUN)

int_index(값: 7)를 인덱스로 사용하여, 5개의 4바이트 요소로 구성된 veml6075_it_ms 배열의 7번째 요소(바이트 오프셋 31)에 접근하여 오버런이 발생합니다.

이는 잠재적으로 손상된 하드웨어에 대한 보안 강화(hardening) 조치입니다. 적용하는 것이 좋지만, 이전 버전에 백포트(backport)할 필요는 없습니다.

코드

  • /drivers/iio/light/veml6075.c
static int veml6075_read_int_time_index(struct veml6075_data *data)
{
	int ret, conf;

	ret = regmap_read(data->regmap, VEML6075_CMD_CONF, &conf);
	if (ret < 0)
		return ret;

	return FIELD_GET(VEML6075_CONF_IT, conf);
}

문제점

  • OOB 이라고 한다.
  • 함수의 반환 값은 0에서 7까지 인데 veml6075_it_ms 배열은 5 * 4로 구성되었다. 그래서 OOB가 터진다.

증명

  • veml6075_it_ms 가 5*4라는 사실을 증명한다.

    static const int veml6075_it_ms[] = { 50, 100, 200, 400, 800 };
    
    • 전역 변수로 박혀있다.
  • 함수의 반환값이 0에서 7이라는 것을 증명한다.

    	return FIELD_GET(VEML6075_CONF_IT, conf);
    
    #define VEML6075_CONF_IT	GENMASK(6, 4) /* intregration time */
    
    • GENMASK(6, 4)6번째 비트부터 4번째 비트까지 1로 채워진 비트 마스크(bitmask)를 생성하는 매크로이다.
    • FIELD_GET레지스터(register)나 변수 값에서 특정 비트 필드(bit field)의 값을 추출하는 매크로이다.
    • 즉, conf의 값에따라 달라진다는 것이다.
  • conf는 위에서 얻어진다.

    • 대충 특정 레지스터의 값을 가져온다는 이야기
    ret = regmap_read(data->regmap, VEML6075_CMD_CONF, &conf); // 얘가 그냥  VEML6075_CMD_CONF의 값을 읽어오는 것이다.
    
    ret = regmap_read(data->regmap, 0, &conf);
    
    ret = map->reg_read(context, reg, val);
    
    map->reg_read  = _regmap_bus_read;
    map->reg_read = _regmap_bus_reg_read;
    
    static inline void *_regmap_map_get_context(struct regmap *map)
    {
    	return (map->bus || (!map->bus && map->read)) ? map : map->bus_context;
    }
    
    • 결국 configuration register를 16비트로 표현한 값의 범위가 5초과면 문제가 된다.
    #define VEML6075_CMD_CONF	0x00 /* configuration register */
    #define VEML6075_CMD_UVA	0x07 /* UVA channel */
    #define VEML6075_CMD_UVB	0x09 /* UVB channel */
    #define VEML6075_CMD_COMP1	0x0A /* visible light compensation */
    #define VEML6075_CMD_COMP2	0x0B /* infrarred light compensation */
    #define VEML6075_CMD_ID		0x0C /* device ID */
    
    • 그리고 FIELD_GET에서 conf에서 유효한 값을 추출한 다음에 이를 반환한다.
      • 하드웨어가 정상적으로 작동할 때에는 문제가 되지 않지만 하드웨어가 손상될 경우에는 정상적인 작동을 하지 않을 수 있다.

패치

static int veml6075_read_int_time_index(struct veml6075_data *data)
{
	int ret, conf, int_index;

	ret = regmap_read(data->regmap, VEML6075_CMD_CONF, &conf);
	if (ret < 0)
		return ret;

	int_index = FIELD_GET(VEML6075_CONF_IT, conf);
	if (int_index >= ARRAY_SIZE(veml6075_it_ms))
		return -EINVAL;

	return int_index;
}
  • 검증하는 OOB를 검증하는 코드가 추가되었다.
  • 하드웨어가 손상될 때만 이런 OOB가 생길 수 있으므로 이를 위해 오류에 대처하는 코드를 삽입했다.

익스플로잇

  • 하드웨어에 손상을 줘야 익스플로잇이 가능해서 사실상 원격에서 익스플로잇할 수 없다.
  • 익스 불가