[하루한줄] CVE-2021-30660: macOS 및 iOS의 커널 메모리 유출 취약점

URL

CVE-2021-30660 - XNU Kernel Memory Disclosure

Target

Explain

Apple사의 macOS 및 iOS의 XNU 시스템에서 커널 메모리를 유출할 수 있는 취약점이 발견되어 세부 정보가 공개되었습니다.

XNU의 syscall SYS_msgsnd_nocancel 의 핸들러인 sysv_msg.c/msgrcv_nocancel() 는 유저 공간의 메시지 크기를 msgsz로 받습니다. 만약 유저 공간에서 요청된 크기가 초기에 커널에 전송된 크기 msghdr→msg_ts보다 크면 아래와 같이 msghdr→msg_ts로 자릅니다.

if (msgsz > msghdr->msg_ts) {
		msgsz = msghdr->msg_ts;
	}

이후 아래의 반복문을 돌며 커널 msgpool의 데이터를 유저 공간으로 복사합니다.

1		// msg.h
2		#define MSGSSZ	8		/* Each segment must be 2^N long */
3	
4		static int msginit(__unused void *dummy){
5			if (i != msginfo.msgssz) {
6				printf("msginfo.msgssz=%d (0x%x) not a small power of 2; resetting to %d\\n", msginfo.msgssz, msginfo.msgssz, MSGSSZ); 
7				msginfo.msgssz = MSGSSZ;
8			}
9		...
10	
11	int msgsnd_nocancel(struct proc *p, struct msgsnd_nocancel_args *uap, int32_t *retval){
12	...
13		for (len = 0; len < msgsz; len += msginfo.msgssz) {
14			size_t tlen;
15			/* compare input (size_t) value against restrict (int) value */
16			if (msgsz > (size_t)msginfo.msgssz) {
17				tlen = msginfo.msgssz;
18			} else {
19				tlen = msgsz;
20			}
21			if (next <= -1) {
22				panic("next too low #3");
23			}
24			if (next >= msginfo.msgseg) {
25				panic("next out of range #3");
26			}
27			SYSV_MSG_SUBSYS_UNLOCK();
28			eval = copyout(&msgpool[next * msginfo.msgssz], user_msgp, tlen);
29		...

반복문의 증가 값인 msginfo.msgsszmsginit()에서 #define MSGSSZ 8 로 선언된 MSGSSZ로 초기화되어 특정 조건을 만족하면 8 bytes 단위로 커널 메모리를 유저 공간에 복사하는데, 이때 요청된 크기가 8의 배수가 아닐 경우 초기화되지 않은 1~7 bytes 크기의 커널 메모리가 유출될 수 있습니다.

9 bytes 크기의 SYS_msgsnd_nocancel syscall을 보낼 경우 취약점은 다음과 같이 트리거 됩니다.

  1. msghdr→msg_tsmsgsz가 9로 설정됩니다.
  2. line 16의 조건문에 의해 tlen이 8이 됩니다.
  3. 8 bytes 단위로 복사하는 반복문을 두 번 수행합니다.
  4. 16 bytes의 커널 메모리가 유저 공간으로 복사되어 초기화되지 않은 7 bytes 크기의 커널 메모리가 유출됩니다.