래퍼런스
분석
커밋 메시지
제목: 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가 생길 수 있으므로 이를 위해 오류에 대처하는 코드를 삽입했다.
익스플로잇
- 하드웨어에 손상을 줘야 익스플로잇이 가능해서 사실상 원격에서 익스플로잇할 수 없다.
- 익스 불가