`IPC::Untrusted<T>` wrapper for renderer-supplied values
Component: WebKit IPC | bafcdb2
WebKit은 UI process나 Networking process처럼 권한이 높은 process의 입장에서, WebContent process가 이미 장악되었을 수 있다고 전제합니다. WebContent에서 올라오는 메시지에는 origin, site, registrable domain, URL처럼 보안에 직결되는 값이 실려 있는데, 악의적이거나 버그가 있는 renderer라면 이런 값을 얼마든지 위조할 수 있습니다. 그런데 지금까지의 방어 수단은 MESSAGE_CHECK 매크로 하나뿐이었고, 그마저도 해당 값을 다루는 모든 code path에 개발자가 잊지 않고 직접 넣어야 했습니다.
이번 시리즈의 첫 commit으로, Source/WebKit/Platform/IPC/Untrusted.h에 IPC::Untrusted<T>가 추가되었습니다. 이 wrapper는 값에 직접 접근하는 accessor를 아예 제공하지 않습니다. 값에 닿는 경로는 두 가지뿐입니다. 선언된 검증 절차를 실행하는 validate()를 거치거나, UnvalidatedReason을 명시해야만 하는 unsafeExtractWithoutValidation()을 사용하는 방법입니다. 아직 연결된 validator는 없습니다.
Significance
검증 누락은 더 이상 빠진 runtime assert가 아니라 컴파일 에러가 됩니다. 값을 검증하거나 검증하지 않는 이유를 명시하는 것 외에는, wrapper가 값을 읽을 방법을 전혀 제공하지 않기 때문입니다. 타입 자체에 accessor가 없는 만큼, ArgumentCoder의 decode 경로는 raw T 대신 Untrusted<T>를 반환할 수 있습니다. 그 결과 보호되지 않은 경로가 빠진 assert 속에 묻히는 대신 타입 시스템 위로 드러나게 됩니다.
Audit directions
앞으로 눈여겨볼 패턴은, wrapper에 감싸여 들어오는 값의 집합만큼만 정확히 적용되는 타입 수준의 guard입니다. Narrow: 정작 읽어볼 가치가 있는 표면은 escape hatch 쪽입니다. unsafeExtractWithoutValidation에 붙는 reason 하나하나가 문서로 남겨진 신뢰 가정이며, 실제로 사용 중인 reason 목록은 현재 경계가 강제되지 않는 지점을 압축해 놓은 지도에 해당합니다. Wider: 이 guard가 보호하는 대상은 Untrusted<T> 타입으로 decode된 값뿐입니다. 그래서 origin을 담고 있으면서도 여전히 raw로 decode되는 값이 없는지 ArgumentCoder specialization을 점검할 필요가 있습니다. struct 안에 중첩되어 있거나, URL 형태로 실려 오거나, generator 차원의 강제가 닿지 않는 메시지 경로로 들어오는 경우가 그 대상입니다. Widest: 같은 형태의 wrapper는 권한이 높은 process가 낮은 쪽으로부터 받는 모든 값으로 일반화됩니다. 그러면 앞으로의 질문은, cross-process로 오가는 값 중 어떤 종류가 동일한 처리를 받아야 하는가로 넘어갑니다. file path, frame·page identifier, sandbox extension handle 등이 후보입니다. 리뷰에서 포착할 신호는 분명합니다. 권한 있는 쪽의 handler가 decode된 파라미터를 같은 식 안에서 validate()나 reason 없이 곧바로 읽고 있는 경우입니다.