Linux v6.18.37 · 개념과 코드 읽기

ARMv9 Vector·AI와 메모리·제어 흐름 보안

이 코드는 어떤 문제를 푸나요?

벡터 연산 확장과 메모리·제어 흐름 보호는 목적이 다릅니다. SVE/SME가 계산 폭을 넓히는 동안 MTE·PAC·BTI·GCS는 서로 다른 오류와 흐름을 검사합니다. 대표 소스로 v6.18.37의 사용자 PAC 키 초기화를 읽습니다. 한 함수로 이 모든 기능이 지원된다고 결론 내리지는 않습니다.

읽을 범위: v6.18.37 · arch/arm64/include/asm/pointer_auth.h · ptrauth_keys_init_user 86–99행입니다. 아래에 이 범위의 원문과 각 줄의 설명을 실었습니다. 주제 전체의 흐름과 다른 경로는 기존 분석에서 함께 읽으실 수 있습니다.

먼저 알아둘 개념

PAC 키

포인터 인증값을 만들고 검사할 때 사용하는 비밀 상태입니다. task에 맞는 키가 CPU에 설치되어야 합니다.

명령 주소와 데이터 주소 키

APIA/APIB는 명령 주소, APDA/APDB는 데이터 주소용 키 계열입니다.

서로 다른 보호

PAC는 포인터 인증, BTI는 간접 분기 도착점, MTE는 메모리 태그, GCS는 호출·복귀 기록 보호에 관련됩니다.

처음 읽을 때

원래 복귀 주소, 인증 정보, 키를 별개 항목으로 그려 설명하십시오.

더 깊이 살펴볼 때

키 수명과 fork·exec·context switch·prctl의 관계, 바이너리 계측과 하드웨어 활성화 조건을 추적하십시오.

그림으로 보는 변화

ARMv9 Vector·AI와 메모리·제어 흐름 보안의 단계별 개념 그림
각 단계에 화살표 의미와 생략 범위를 표시했습니다. 주소·숫자 예제는 실제 장치 값을 뜻하지 않습니다.
1단계 설명

1단계 고정

GIF 원본 열기

1. 지원 기능 확인

주소 인증과 일반 인증 지원 여부를 나눠 확인합니다.

조건부 화살표는 기능 구현 차이를 나타냅니다.

2. 사용자 키 생성

지원되는 키 필드를 난수로 채웁니다.

난수는 사용자 계산 데이터가 아니라 보호용 키 상태입니다.

3. 키 설치

생성한 키를 사용자 실행용 상태로 설치합니다.

키 생성과 실제 CPU 반영을 분리한 호출 관계입니다.

ptrauth_keys_init_user를 한 줄씩 읽기

줄 번호는 v6.18.37 원문 기준입니다. 주석·빈 줄을 포함한 함수 전체를 먼저 보고, 그 아래에서 각 줄을 설명합니다.

static inline void ptrauth_keys_init_user(struct ptrauth_keys_user *keys)
{
	if (system_supports_address_auth()) {
		get_random_bytes(&keys->apia, sizeof(keys->apia));
		get_random_bytes(&keys->apib, sizeof(keys->apib));
		get_random_bytes(&keys->apda, sizeof(keys->apda));
		get_random_bytes(&keys->apdb, sizeof(keys->apdb));
	}

	if (system_supports_generic_auth())
		get_random_bytes(&keys->apga, sizeof(keys->apga));

	ptrauth_keys_install_user(keys);
}
static inline void ptrauth_keys_init_user(struct ptrauth_keys_user *keys)

사용자 실행용 포인터 인증 키 구조를 초기화하고 설치하는 함수입니다.

	if (system_supports_address_auth()) {

주소 인증을 시스템에서 사용할 수 있는지 확인합니다. 키 필드가 존재한다고 모든 CPU에서 명령을 사용할 수 있는 것은 아닙니다.

		get_random_bytes(&keys->apia, sizeof(keys->apia));

명령 주소용 A 키 APIA를 난수로 초기화합니다. sizeof로 정확한 키 필드 크기를 지정합니다.

		get_random_bytes(&keys->apib, sizeof(keys->apib));

명령 주소용 B 키 APIB를 별도로 초기화합니다. A와 B를 같은 키로 복사하는 것이 아닙니다.

		get_random_bytes(&keys->apda, sizeof(keys->apda));

데이터 주소용 A 키 APDA를 생성합니다.

		get_random_bytes(&keys->apdb, sizeof(keys->apdb));

데이터 주소용 B 키 APDB를 생성합니다. 네 필드는 서로 다른 인증 용도와 키 선택을 구분합니다.

	if (system_supports_generic_auth())

일반 인증 기능도 지원되는지 별도로 확인합니다. 주소 인증 조건과 분리되어 있습니다.

		get_random_bytes(&keys->apga, sizeof(keys->apga));

지원된다면 일반 인증용 APGA 키도 난수로 초기화합니다.

	ptrauth_keys_install_user(keys);

준비한 키를 사용자 실행용 CPU 상태로 설치하는 helper를 호출합니다. 키 생성과 설치가 다른 작업임을 드러내는 지점입니다.

함께 생각해 볼 질문

PAC가 포인터를 암호화해 주소를 숨깁니까?

주목적은 포인터 인증이며 일반적인 주소 비밀화와 구분합니다.

PAC가 있으면 BTI는 불필요합니까?

보호 대상과 검사 시점이 달라 서로 대체한다고 볼 수 없습니다.

벡터 명령을 사용하면 MTE도 켜집니까?

서로 다른 기능과 활성화 조건입니다.

출처와 읽은 범위

Linux stable v6.18.37 · arch/arm64/include/asm/pointer_auth.h

해당 버전 원본 파일 · 기존 코드 분석 · 설명 원고

맨 위로 ↑