Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

8179
1390
307630


[Arm프로세서] 하이퍼바이저: wfe/wfi 명령어

많은 개발자들은 hvc 명령어를 통해서만 EL1에서 EL2로 진입할 수 있다고 알고 있습니다. 사실 그렇지는 않습니다. 게스트 OS에서 하이퍼바이저로 진입하는 다른 방법은 wfe와 wfi 명령어를 실행하는 것입니다.

원래 wfe와 wfi 명령어는 Arm 코어가 저전력 모드(low-power mode)으로 실행될 수 있게 동작합니다. HCR_EL2 레지스터의 TWE 혹은 TWI 비트를 1로 설정하면 EL2 트랩이 유발되어, EL2로 진입합니다.

시스템에 하나의 운영체제가 존재하는 환경에서는 wfe, wfi 명령어는 저전력 모드용으로 실행되나, 하이퍼바이저와 같이 시스템에 2개 이상의 운영체제가 실행되는 환경에서, HCR_EL2 레지스터의 TWE 혹은 TWI 비트를 1로 설정하면 hvc 명령어처럼 EL2로 진입합니다.

이어서 arm 아키텍처 문서를 보면서 관련 내용을 설명하겠습니다.

---
EL2 provides the following traps for WFE and WFI instructions:

• HCR_EL2.TWE:
1: Any attempt to execute a WFE instruction at Non-secure EL1 or EL0 is trapped to 
EL2, if the instruction would otherwise have caused the PE to enter a low-power 
state.
  0: Non-secure EL1 or EL0 execution of WFE instructions is not trapped to EL2.

• HCR_EL2.TWI
1: Any attempt to execute a WFI instruction at Non-secure EL1 or EL0 is trapped to 
EL2, if the instruction would otherwise have caused the PE to enter a low-power 
state.
  0: Non-secure EL1 or EL0 execution of WFI instructions is not trapped to EL2.
---

위에서 명시된 Arm 스팩 문서는 중요한 내용을 담고 있어 원문을 그대로 소개합니다.

스팩 문서의 내용은 다음과 같이 해석할 수 있습니다.

   * EL2는 wfe와 wfi 명령어에 대한 트랩을 지원한다. 
   * 하이퍼바이저 콘트롤 레지스터(HCR_EL2)의 TWE와 TWI 비트가 1로 설정된 경우, 
    wfe 혹은 wfi 명령어를 실행하면 EL2로 트랩이 되는 것이다.
   * 만약 하이퍼바이저 콘트롤 레지스터(HCR_EL2)의 TWE와 TWI 비트가 0으로 설정됐으면 기존의 
     저전력 모드로 진입하는 동작을 수행한다.

일반적으로 wfe와 wfi 명령어가 실행되면 Arm 코어가 저전력 모드로 구동됩니다. 하이퍼바이저 콘트롤 레지스터(HCR_EL2)의 TWE와 TWI 비트가 1으로 설정됐으면 EL2로 진입합니다.

정리하면 hvc, wfe, wfi와 같은 명령어를 실행하면 EL1에서 EL2로 진입됩니다. 이 부분까지 읽으면 다음과 같은 의문이 생길 수 있습니다.

    "hvc, wfe, wfi와 같은 명령어를 실행하면 어떤 익셉션이 유발되어 EL2에 진입할까?"

hvc, wfe, wfi와 같은 명령어를 실행하면 Arm 코어는 Synchrnous 익셉션을 유발하며, 다음과 같은 규칙에 따라 프로그램 카운터를 업데이트합니다.

    "프로그램 카운터: VBAR_EL2 + 0x400"

VBAR_EL2는 EL2에 정의된 익셉션 벡터 테이블의 베이스 주소이고 0x400은 Synchronous 익셉션의 오프셋 정보입니다. 

[정보]
하이퍼바이저가 실행되는 EL2 관점에서 해석한 익셉션 벡터 테이블의 세부 내용은 12.4절을 참고하면 됩니다.


이를 달리 설명하면 hvc, wfe, wfi와 같은 명령어를 실행하면 같은 익셉션 벡터 핸들러에서 처리된다고 볼 수 있습니다. 그렇다면 EL1에서 hvc 명령어가 실행돼 EL2에서 진입됐는지 혹은 wfe와 같은 명령어를 실행해 EL2에 진입했는지 어떻게 알 수 있을까요?

Armv8 아키텍처에서는 익셉션이 유발된 세부 원인을 익셉션 클래스(Exception Class)로 정의하는데, 다음 표와 같은 익셉션 클래스로 업데이트됩니다.

   hvc: 0x16(Exception Class)
   wfe, wfi: 0x01(Exception Class)


위에 소개된 익셉션 클래스 비트 정보는 ESR_EL2 레지스터의 [31:26] 비트에서 확인할 수 있습니다. 이 정보를 참고하면 hvc, wfe, wfi 명령어에 따라 하이퍼바이저는 다른 방식으로 처리할 수 있습니다.

Arm 아키텍처 관점으로 하이퍼바이저의 세부 동작을 설정하려면 하이퍼바이저 콘트롤 레지스터의 비트를 설정해야 하는데, 이어지는 절에서 살펴보겠습니다.

[Arm프로세서] 하이퍼바이저: hvc 명령어(하이퍼바이저 콜) 하이퍼바이저(Hypervisor)

먼저 Arm 스팩 문서에서 HVC 명령어를 설명한 부분을 소개합니다. 

<출처: DDI0487G_b_armv8_arm.pdf>

C6.2.94 HVC
Hypervisor Call causes an exception to EL2. Software executing at EL1 can use this instruction to call the hypervisor to request a service.

스팩 문서의 내용은 다음과 같이 해석할 수 있습니다.

하이퍼바이저 콜은 EL2로의 익셉션을 유발한다.
EL1에서 실행되는 소프트웨어는 이 명령어(hvc)를 사용해 하이퍼바이저에게 어떤 서비스를 요청한다.

EL1에서 hvc 명령어를 실행해 하이퍼바이저가 구동되는 EL2로 진입하는 동작을 하이퍼바이저 콜이라고 합니다. 여기서 hvc 명령어를 실행해 하이퍼바이저 콜을 유발하는 소프트웨어는 EL1에서 실행되는 리눅스 커널이나 RTOS 커널입니다. 

[정보]
arm 스팩 문서는 "Software executing at EL1"(EL1에서 실행되는 소프트웨어)와 같이 포괄적인 의미를 내포하는 표현을 많이 사용합니다. 운영체제라고 부를 수 없는 간단한 시스템 시스템 소프트웨어(e.g: 베어메탈)까지 포괄하는 내용을 기술해야 하기 때문입니다. Arm 프로세서는 다양한 소프트웨어 실행될 수 있습니다. 


EL2에서 실행되는 하이퍼바이저 위에서 구동되는 여러 게스트 OS(EL1)들이 있는데, 하이퍼바이저에게 어떤 서비스를 요청하기 위해 통신을 할 때 hvc 명령어를 실행합니다. 이런 동작을 게스트 Exit이라고도 합니다.

hvc 명령어 다음에 #imm와 같이 상수형 인자를 지정할 수 있는데 “hvc 0x1”와 같은 명령어를 실행할 수 있습니다. 대부분 어셈블리 명령어를 범용 레지스터의 값을 시스템 레지스터에 설정하는 방식으로 구성돼 있는데 하이퍼바이저 콜 명령어는 간단하게 구성돼 있습니다.

그런데 hvc 명령어를 실행하면 항상 EL2로 진입할까요? 항상 그렇지는 않습니다. hvc 명령어가 실행되려면 HCR_EL2와 같은 관련 레지스터가 설정되어야 하는데, 이 내용은 Arm 스팩 문서에서 확인할 수 있습니다. 

<출처: DDI0487G_b_armv8_arm.pdf>

The HVC instruction is UNDEFINED:

When EL3 is implemented and SCR_EL3.HCE is set to 0.
When EL3 is not implemented and HCR_EL2.HCD is set to 1.
When EL2 is not implemented.
At EL1 if EL2 is not enabled in the current Security state.
At EL0.

위 스팩의 내용은 다음과 같이 요약할 수 있습니다.

HVC 명령어는 다음과 같은 조건에서 Undefined(정의되지 않는) 명령어로 간주된다:

EL3이 구현됐는데 SCR_EL3 레지스터의 HCE 비트가 0으로 설정된 경우
EL3이 구현돼 있지 않고 HCR_EL2 레지스터의 HCD 비트가 1로 설정된 경우
EL2(하이퍼바이저)가 구현되지 않는 경우
현재 Security 상태에서 EL2가 활성화되지 않는 경우에 실행되는 EL1
EL0 익셉션 레벨

hvc 명령어를 실행했는데 EL2로 진입하지 않는 경우 당황하지 말고 위에서 명시된 레지스터가 설정됐는지 체크해야 할 필요가 있습니다.


[Arm프로세서] 하이퍼바이저는 어디에 사용될까? 하이퍼바이저(Hypervisor)

클라우드 아키텍처로 하이퍼바이저를 적용하는 제품이 점검 늘어나는 추세입니다. 이번 절에서는 하이퍼바이저는 어느 제품군에 활용되는지 소개하겠습니다.

오토모티브(Automotive): 전기 자동차

먼저 오토모티브 분야에서 하이퍼바이저는 많이 활용됩니다. 특히 자동차의 계기판과 네비게이션 부품으로 구성되는 인포테이먼트 분야에서는 자동차 고객사가 하이퍼바이저를 소프트웨어 아키텍처로 선택하고 있습니다.

그렇다면 하이퍼바이저는 인포테이먼트 분야에서 어떻게 활용될까요? 다음 그림과 같이 운전자 입장에서 높은 안정성이 요구되는 계기판은 보안성이 높은 RTOS을 실행하고, 네비게이션은 범용적인 안드로이드나 네이티브 리눅스를 실행할 수 있습니다.

 
그림 12.2 하이퍼바이저가 사용되는 사례

다양한 시장 조사 보고서에서 "자동차용 하이퍼바이저 시장의 저변이 확대될 것이다"라고 예측하고 있습니다.

* 출처: 세계의 자동차용 하이퍼바이저 시장 2020-2027
https://www.globalresearch.kr/report/global-automotive-hypervisor-market-size-bzw20oc140

[중요]
기존의 하이퍼바이저는 인텔의 x86 CPU위에서 실행됐으나, 오토모티브 분야의 하이퍼바이저는 Armv8 아키텍처 기반 CPU에서 실행됩니다.


클라우드 서버

이미 유닉스 기반으로 서버를 개발했던 메이저 업체(e.g: 선 마이크로시스템즈, HP, IBM)는 2000년 이전부터 하이퍼바이저 기반으로 구동되는 서버를 개발해 판매해왔습니다.

사실 클라우드 서버는 x86_64의 인텔 CPU에서 실행되므로 하이퍼바이저도 이 조건에서 구동됐습니다. 최근에 Armv8 아키텍처 기반의 Arm 코어가 클라우드 서버에 많이 적용되면서, Arm 아키텍처 기반에서 실행되는 하이퍼바이저를 채택하는 비율이 점진적으로 늘어나는 추세입니다. 


[Arm프로세서] 하이퍼바이저를 왜 알아야 할까? 하이퍼바이저(Hypervisor)

하이퍼바이저가 무엇인지 알고 나면 "하이퍼바이저를 왜 배워야 할까?"라는 의문이 생길 가능성이 높습니다. 사실 하이퍼바이저는 x86 기반 CPU에서 Vmware나 IBM과 같은 업체에서 50년전 부터 꾸준히 개발돼 왔습니다. 그래서 x86 CPU에서 데스트 탑이나 서버에서 개발됐던 기술인데, Armv8 아키텍처에서 하이퍼바이저를 왜 알아야 하는지 궁금할 것입니다.

하이퍼바이저를 배워야 하는 가장 큰 이유는 시스템 소프트웨어에서 하이퍼바이저 기법을 많이 활용하는 추세이기 때문입니다. 2020년 이후 소프트웨어 업계를 이끄는 기술은 AI와 Big Data와 클라우드인데, 3가지 기술들이 다양한 제품군의 생태계에 영향을 끼치고 있습니다. 하이퍼바이저는 클라우드 분야에서 활발히 적용되고 있는 아키텍처 중 하나입니다.

또한 시스템 소프트웨어 업계에서는 하이퍼바이저의 기능을 활용해 하나의 운영체제가 실행되는 환경에서 디버깅 정보를 확보하거나 보안과 관련된 기능을 적용하고 있습니다. 하이퍼바이저는 멀티 운영체제를 실행하는 소프트웨어로 알려져 있는데, 하이퍼바이저를 이루는 기능을 확장해 하나의 운영체제만 존재하는 환경에 적용할 수 있습니다.

이와 더불어 전기 자동차 업계에서 하이퍼바이저는 아주 많이 활용되고 있습니다. 2020년 이후 미래를 이끈 제품군으로 떠오르고 있는 전기자동차(자율 주행, 인포테이먼트)에 Armv8 기반 Arm 프로세서가 많이 사용되고 있는데, 전기 자동차의 인포테이트먼트 분야에서는 Armv8 기반 프로세서와 함께 하이퍼바이저가 많이 활용됩니다.

전기 자동차를 개발하는 시스템 소프트웨어 개발자는 Armv8 아키텍처에서 어떤 방식으로 하이퍼바이저를 지원하는지 반드시 알아야 하는 시대입니다.

[정보]
2020년 이후부터 시스템 반도체 분야에 100조 이상의 R&D 투자가 한다는 기사를 쉽게 볼 수 있습니다. 시스템 반도체 업계를 이끄는 주요 제품군은 전기자동차(자율 주행, 인포테이먼트)인데 전기 자동차에 Arm 프로세서가 많이 사용되고 있습니다.


만약 시스템 소프트웨어 개발자로 하이퍼바이저의 기본 개념이나 관련 Armv8 아키텍처의 기능을 모른다면 '시대에 뒤쳐진다'라는 이야기를 들 수 있습니다.

[Arm프로세서] 하이퍼바이저를 구성하는 요소 하이퍼바이저(Hypervisor)

2개 이상의 멀티 운영체제를 동시다발적으로 실행할 수 있는 플렛폼이나 아키텍처를 하이퍼바이저라고 소개했습니다. 이어서 다음 그림을 보면서 하이퍼바이저 아키텍처를 구성하는 주요 기능에 대해 알아봅시다. 

 
그림 12.1 하이퍼바이저 아키텍처의 전체 구조

위 그림의 가운데 윗 부분을 보면 게스트 OS1, 게스트 OS2라고 표시된 부분은 하이퍼바이저에서 실행되는 운영체제입니다. 게스트 OS1이 안드로이드, 게스트 OS2는 리눅스가 될 수 있습니다. 

그런데 게스트 OS1와 게스트 OS2에서 실행되는 운영체제는 각각 독립적인 EL0와 EL1에서 실행됩니다. 게스트 OS1의 커널은 EL1, 게스트 OS1의 애플리케이션은 EL0에서 실행됩니다. 마찬가지로 게스트 OS2의 커널은 EL1, 게스트 OS2의 애플리케이션은 EL0에서 실행됩니다.

[정보]
게스트 OS는 가상 머신(Virtual Machine: VM)이라고도 부르는데, 게스트 OS와 같은 의미입니다. 하이퍼바이저를 설명하는 기술 문서는 Virtual Machine이라고 표기하는데, Arm 스팩 문서에서 주로 게스트 OS라고 표기합니다.


이어서 그림의 아랫 부분에 Hypervisor라고 표기된 부분을 보겠습니다. 이는 이번 장에서 설명할 하이퍼바이저를 나타내며 EL2에서 실행됩니다. 하이퍼바이저는 여러 게스트 OS가 동시다발적으로 실행될 수 있게 게스트 OS의 리소스를 관리하는, 다음과 같은 역할을 수행합니다. 

각각 게스트 OS를 로딩(부팅 과정)
게스트 OS과의 통신
게스트 OS의 리소스(vcpu, virtual 인터럽트)를 관리

이어서 그림에서 ②로 표시된 부분을 보겠습니다. 게스트 OS의 EL1에서 실행되는 커널에서 hvc 명령어를 실행하면 EL1에서 EL2로 진입하는 동작인데, 이는 ①로 표시된 "EL0에서 svc 명령어를 실행해 EL1으로 진입하는 과정"과 유사합니다.

누군가 "게스트 OS(가상 머신)와 하이퍼바이저는 어떻게 통신할까"라고 질문을 하면 다음과 같이 답할 수 있습니다.  

    "EL0에서 svc 명령어를 실행하면 슈퍼바이저 콜이 실행돼 EL1로 진입하듯이, 
     EL1에서 hvc 명령어를 실행해 하이퍼바이저 콜이 실행돼 하이퍼바이저가 구동되는 
     EL2로 진입한다."

사실 ②로 표시된 부분이 하이퍼바이저를 이해하기 위해 가장 먼저 알아야 하는 동작입니다. 

여기까지 하이퍼바이저를 구성하는 요소를 소개했습니다. 이어서 하이퍼바이저를 왜 알아야 하는지 설명하겠습니다. 

[정보]
그림 12.1는 하이퍼바이저의 예시 중 하나입니다. 하이퍼바이저에는 하나의 시스템에 2개 이상의 게스트 OS가 구동될 수 있는데, 개발하려는 제품의 스팩에 따라 3~5개의 운영체제가 게스트 OS로 실행될 수 있습니다.

[Arm프로세서] 하이퍼바이저란 하이퍼바이저(Hypervisor)

여러분들이 사용하는 데스트 탑 PC에는 어떤 운영체제가 설치돼 있나요? 대부분 윈도우나 리눅스가 깔려 있을 겁니다. 그렇다면 윈도우나 리눅스와 같은 운영체제를 설치하는 이유는 무엇일까요? '운영체제 위에서 실행 중인 프로그램을 사용하기 위해서'라고 답할 것입니다. 운영체제를 설치하는 이유는 운영체제에서 실행되는 워드나 스타크래프트와 같은 프로그램을 사용하기 위해서입니다. 그래서 가끔은 2개의 데스크 탑 PC에 각각 윈도우와 리눅스를 따로 설치해 사용하곤 합니다.

만약 한 대의 데스크탑 PC에서 윈도우와 리눅스를 같이 사용할 수 있다면 어떨까요? 윈도우와 리눅스에서 실행되는 애플리케이션을 1대의 데스크탑 PC에서 사용할 수 있는 상황입니다. 윈도우와 리눅스에서 실행되는 프로그램을 하나의 데스크 탑 PC에서 실행할 수 있으니 훨씬 이득일 것입니다. 이렇게 2개의 운영체제를 하나의 데스크탑 PC에서 사용할 수 있는 것은 하이퍼바이저와 기술이 도입됐기 때문입니다.

하이퍼바이저(Hypervisor)는 데스크 탑 PC에서 윈도우와 리눅스를 사용하듯이, 2개 이상의 운영체제를 동시에 실행할 수 있는 아키텍처 혹은 플렛폼입니다.

사실 하이퍼바이저는 그 동안 가상 컴퓨터 기법으로 x86 계통의 CPU에서 개발됐는데, 가장 대표적인 예로 KVM(Kernel-based Virtual Machine)을 들 수 있습니다. 최근 떠오르고 있는 전기 자동차의 인포테이먼트 분야에서 Armv8 기반의 하이퍼바이저가 많이 활용되고 있는데 자동차 고객사는 자사의 운영체제와 더불어 하이퍼바이저를 개발 중입니다.

[Tech-Writing] local variable expression ① IT 개발자 책쓰기_글쓰기

지역 변수(로컬 변수)를 표현하는 예문입니다.

We will assume the prev local variable refers to the process descriptor of the process.

문장을 번역하겠습니다;

    ;prev 로컬 변수는 프로세스의 속성 정보를 나타내는 프로세스 디스크립터 타입입니다.

prev는 로컬 변수 이름이고 local variable는 로컬 변수라는 의미입니다.

다른 예시입니다.

Thus, the ticks local variable denotes the number of ticks that
occurred since the bottom half was activated.

위 문장은 다음과 같이 번역할 수 있습니다.

   ; ticks 로컬 변수는 Bottom-half가 활성화된 후 시점에 발생한 틱의 횟수를 나타냅니다.

이번에는 소스와 함께 영어 문장을 보겠습니다.

void kmem_slab_destroy(kmem_cache_t *cachep, kmem_slab_t *slabp)
{
  if (cachep->c_dtor) {
      unsigned long num = cachep->c_num;
      void *objp = slabp->s_mem;

objp local variable keeps track of the currently examined object.

objp 로컬 변수는 가장 최근에 사용된 오브젝트의 값을 저장한다.

로컬 변수를 저장하는 표현

소스와 영어 문장을 보겠습니다.

   current->mm->total_vm += len >> PAGE_SHIFT;
   flags = vma->vm_flags;
   addr = vma->vm_start;
   insert_vm_struct(current->mm, vma);
   merge_segments(current->mm, vma->vm_start, vma->vm_end);

the values of vm_flags and vm_start, which may be needed later, are saved in the flags and addr local variables:

'which may be needed later'라는 내용을 빼고 다음과 같이 번역할 수 있습니다.

    "vm_flags와 vm_start 값은 flags와 addr 로컬 변수에 저장된다." 

[Arm프로세서][Armv8] 트러스트존(TrustZone): 시큐어 RTOS 구현 사례: QSEE 트러스트존(TrustZone)

각 SoC 칩 벤더와 보안 업체들은 arm 아키텍처의 트러스트존을 활용해 독자적인 보안 RTOS(Trusted OS)를 개발했습니다. 이번에는 퀄컴에서 설계한 QSEE를 소개하면서 시큐어 RTOS는 어떤 방식으로 구현됐는지 알아보겠습니다. QSEE는 Qualcomm's Secure Execution Environment의 약자로 Arm 아키텍처의 트러스트존을 활용해 퀄컴에서 제작한 Trusted OS 아키텍처입니다.

다음은 QSEE을 구성하는 구성도입니다.
(출처: https://www.qualcomm.com/media/documents/files/guard-your-data-with-the-qualcomm-snapdragon-mobile-platform.pdf)

 

그림 11.10 QSEE의 구성도

실제 퀄컴에서 배포된 문서에서 확인된 내용인데 이번 장에서 다뤘던 개념을 이해했다면 바로 이해할만한 내용입니다. 

그림의 가장 왼쪽 부분은 논 시큐어 상태, 오른쪽 부분은 시큐어 상태를 나타냅니다. 위 문서에서는 Non-secure world와 Secure world라는 문구로 표기했는데, 문구는 다르나 비슷한 개념입니다.

이어서 가장 윗 부분에 있는 'QTEE releated services'와 'QTEE libraries/service'는 보안과 관련된 기능이 구현된 데몬이나 서비스를 뜻합니다. 'QTEE releated services'는 논 시큐어 상태의 EL0에서 존재하고, 'QTEE libraries/service'는 시큐어 상태의 EL0에 각각 존재합니다.

'QTEE releated services'와 'QTEE libraries/service'에 퀄컴이 제작한 보안과 관련된 기능이 구현돼 있는 것입니다.

가운데 EL1에 보이는 'Anrdoid Kernel'은 운영체제 커널과 같은 의미이고, QTEE Kernel은 퀄컴이 제작한 시큐어 RTOS를 뜻합니다. 

이처럼 칩셋 벤더들은 Arm 아키텍처에서 지원하는 트러스트존을 활용해 자신만의 Trusted OS를 제작합니다. 이런 칩셋을 탑재한 제품 개발 업체들은 칩셋 업체에서 제공하는 Trusted OS를 활용해 다음과 같은 보안용 모듈이나 애플리케이션을 제작할 수 있습니다.

모바일 페이(삼성 페이)
공인 인증서 애플리케이션

다음 표는 각 SoC 업체와 솔류션 업체들이 개발한 보안 운영체제(Trusted RTOS)입니다.

표 11.2 IT 업체에서 개발된 Trusted OS 이름

각각 IT 업체에서 구현된 Trusted RTOS는 오픈 소스로 공개돼 있어, 해당 업체에서 관리하는 깃 허브에 접근해 소스를 내려받아 빌드해 볼 수 있습니다.

[중요]

최근의 보안 관련 애플리케이션의 동향을 보면 조금만 안전하게 처리되야 할 데이터라도 트러스트존에 구현하려는 움직임을 많이 볼 수 있습니다. 트러스트존하면 데이터를 안전하게 보호할 수 있고 심지어 해커의 공격을 방지할 수 있다고 믿기 때문입니다. 안타깝지만 트러스트존의 아키텍처를 활용해 Trusted OS를 구성해도 100% 해커의 공격으로부터 안전한 시스템은 존재하지 않습니다. 해킹을 하는데 시간이 아주 오래 걸리거나 복잡한 경로로 해킹을 하게 유도할 수 할 뿐이지 해커의 모든 공격을 막을 수는 없습니다.

트러스트존을 활용하면 100% 데이터를 온전히 보호할 수 있다는 것은 사실 상 거짓말과 다름 없습니다.

#Reference: 트러스트존(TrustZone) 

트러스트존 소개
Armv7 아키텍처의 트러스트존
트러스트존의 실제 구현 방식

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자
* 2021년 대한민국 학술원 선정 우수도서


---


[에세이] 조직을 이동한 개발자에게 저지르는 관리자의 만행 ① 임베디드 에세이

2~3년 정도 개발을 하면 프로젝트를 3~4개 정도 마무리합니다. 그런데 어느 시점이 되면 이런 느낌이 들 수 있어요.

    "이 팀은 정말 맞지 않네!"

시간이 더 지나면 나중에 "이 팀을 꼭 떠나야 겠다" 확신이 듭니다. 개발자가 회사나 팀을 떠나고 싶어하는 이유는 뭘까요? 예를 들까요?

    "조직 책임자가 자신의 성과를 인정해주지 않는다."
    "개발자로써 연량이 전혀 늘지 않는다."
    "연봉이 현저히 낮다!"

연봉이 너무 낮아 불만이 심하면 이직을 시도합니다. 그런데 팀장과 사이가 좋지 않거나 역량이 늘지 않는다는 느낌을 받으면 조직을 옮길 수 있습니다. 어느 정도 규모가 있는 회사에서는 팀을 옮길 수 있는 기회를 주기도 합니다. 대기업에서는 '사내 공모'라는 통해 개발자가 조직을 이동할 수 있는 기회를 주죠.

가끔 조직 이동을 고민하거나 꼭 조직 이동을 희망하는 개발자들이 있는데요. 이 분들이 참고하면 좋을 것 같아 "팀은 이동한 개발자에게 저지르는 관리자의 만행"에 대한 글을 포스팅합니다. 이런 정보를 모르고 당하면 정말 힘이 쭉 빠지거든요.

고과 바닥 깔기

팀(조직)을 이동한 개발자(새로운 팀원)가 가장 많이 받는 피해는 뭘까요? 고과를 낮게 받는 겁니다.

쓰레기 관리자들이 가장 많이 하는 짓거리는 최근에 조직을 옮긴 개발자의 고과를 바닥으로 까는 겁니다. 다른 조직에서 왔던 개발자를 희생양으로 삼는 거죠. 새로운 조직으로 가셨는데 고과를 깔지 않았다고요? 이 분은 그나마 운이 좋은 편입니다. 

한 가지 예를 들까요? 7월에 조직 이동을 했다고 칩시다. 어렵게 조직을 이동한 후, 이동한 조직의 책임자와 첫 면담을 합니다. 업무의 방향이나 목표를 이야기하면서 조직 책임자는 다음과 같이 말합니다.

   "우리 팀으로 이동하기 전에 했던 일은 올해 평가에서 제외하는게 낫지 않을까요?"

조직을 옮긴 개발자는 이 말을 처음 듣고는 그려려니 합니다. 속으로 "맞아, 예전에 내가 했던 개발 업무는 중요한게 아니지. 새로운 조직에서 해야 할 업무가 중요하지"라고 생각합니다. 이 말은 한 조직 책임자의 속마음을 모른채 말이죠. 그럼 이런 말을 한 조직 책임자의 속마음을 컴파일해볼까요?

   "이 새끼! 고과를 까야 겠네. 7월 이전에 아예 한 일이 없다고 하면 되겠구나"
   "7월까지 한 일이 없으니, 연말에 평가할 때 니가 한 일은 1/2 밖에 안된다고 해야 겠다!"

개발자가 조직을 옮긴 다음에 바로 Performance를 낼까요? 새로운 방향의 개발을 하면 어느 정도 적응하는 시간이 필요한 경우가 많습니다. 축구 선수 중에 분데스리가에서 프리미어 리그, 혹은 프리미어 리그에서 스페인 라리가 리그로 이적한 선수들도 적응 시간이 필요한 경우가 많죠. 그래서 새로 이동한 조직의 다른 팀원들 보다 Performance를 내지 못할 수도 있습니다.

그런데 가끔 이동한 조직에서 열심히 해 다른 동료만큼 일을 해내는 분들도 있습니다. 그런데 조직을 옮긴 개발자는 "내가 하는 일이 Performance를 제대로 내는 수준인가"라고 스스로를 의심하는 경우도 있습니다.

개발자가 새로운 팀에서 적응을 하던 말던, 관리자 입장에서 누군가 고과를 바닥으로 깔아야 하는 상황이면 팀에 새롭게 이동한 개발자를 희생양으로 삼는 경우가 있습니다.  

원래 조직 책임자는 고과 때문에 항상 골치입니다. 오랫동안 같이 일했던 팀원에게 고과를 잘 챙겨주지 못하는 상황이 많죠. 그런데 새롭게 팀으로 이동한 멤버도 잘 챙겨줄까요? 그렇지 않은 경우가 많습니다. 대부분 아주 좋은 희생양입니다. 그래서 조직을 옮긴 개발자는 고과를 좋게 받을 가능성이 아주 낮습니다.

새로운 팀원을 또 다른 조직으로 버리기

쓰레기 관리자가 저지르는 만행은 "팀에 새롭게 합류한 개발자를 다른 조직으로 보내버리는 겁니다". "팀에 새롭게 왔는데 왜 다른 팀으로 보내?"란 의문이 들 수 있는데요. 설명을 조금 더 읽어주세요.

회사의 운영 방식마다 다르지만 신생 조직이 자주 생기는 경우가 있습니다. 종종 신생 조직이 생기면 다른 팀에 있는 개발자를 착출합니다. 신입 사원이나 경력 사원으로 새로운 조직을 구성하는게 아니라 기존 조직에 있던 개발자로 팀을 꾸리는 것이죠. 

팀장(관리자) 입장에서는 신생 조직이 생겨서 팀원 중에 누군가를 보내 달라는 요청을 받게 됩니다. 이럴 때 쓰레기 관리자들이 저지르는 만행은 다음과 같습니다. 

    "최근에 자신의 팀으로 이동한 인원을 다른 신생 조직으로 보냅니다." 

기존에 같이 데리고 있던 인원은 보내기 싫고. 최근에 이동한 개발자를 다른 조직에 보내니 마음이 덜 불편합니다.

관리자(팀장) 입장에서, 다른 팀에서 자신의 팀으로 어떤 개발자가 오고 싶다고 하면 일단 받아 줍니다. 나중에 혹시 버리기 위한 카드로 남겨주는 것이죠. 

개발자가 팀을 옮기려는 결정을 할 때 많은 고민을 합니다. 선배를 만나 조언을 구하기도 하죠. 그런데 새로운 팀원을 버리는 카드로 받아주는 관리자가 있다니! 정말 안타까운 현실이죠.

설겆이 업무 할당

만행 정도는 아니지만, 쓰레기 관리자들이 하는 악습은 새로온 팀원에게 설겆이 업무를 할당하는 겁니다. 

프로젝트를 하다보면 누군가는 해야 할 꼭 필요한 업무인데, 다들 꺼려하는 일이 있습니다. 시료 샘플을 조립하거나 꾸준히 이미지를 빌드해서 배포하는 업무가 그 중 하나입니다. 혹은 팀의 총무나 자산을 관리하는 업무도 이 중 하나죠. 쓰레기 관리자는 새로운 팀원에게 이런 일을 시킵니다. 팀을 이동한 개발자는 새롭게 옮긴 팀에서 잘 적응하려고 이런 설겆이 업무를 할당 받아도 일단 열심히 하려는 경우가 많습니다. 이런 개발자를 이용해 먹는 겁니다.

팀 내에서 중요한 플래그 십 프로젝트에 아예 투입시키지 않습니다. 기존에 일을 잘하는 개발자들이 있는데 구지 팀에 새로온 멤버에게 시킬 필요가 없다고 생각합니다. 조직을 이동한 개발자에게 개발 난이도가 낮지만 업무량은 많은 프로젝트를 할당하는 경우가 많습니다.

[오제이튜브] 인터뷰#1: 오픈 소스 배포하면 뭐가 남나요? 임베디드 에세이

오제이 튜브(유튜브)에서 인터뷰한 동영상(인터뷰#1)이 올라 왔습니다. 리눅스 커널이 오픈 소스로 어떻게 진행되는지 궁금하신 분은 참고하세요.





[Arm프로세서][트러스트존] Armv8: 시큐어 월드에서 Trusted OS는 어떻게 구동할까?

논 시큐어 월드에는 우리가 알고 있는 운영체제의 커널이 구동됩니다. 예를 들어 리눅스 커널이나 윈도우 커널이 논 시큐어 월드에서 실행됩니다. 그렇다면 시큐어 월드에는 어떤 소프트웨어가 구동될까요? 바로 RTOS가 실행됩니다.

여기서 기억해야 할 사실은 트러스트 존의 RTOS는 독자적으로 스케줄링하면서 시스템을 제어하는게 아니라, 논 시큐어 월드에 의존적으로 동작한다는 점입니다. 대부분의 경우 논 시큐어 월드에서 실행 중인 커널에서 smc(Secure Monitor Call) 명령어를 실행하면, 이에 반응해 시큐어 월드의 RTOS는 동작하게 됩니다. 

쉽게 설명드리면 시큐어 월드의 RTOS는 마치 시스템 콜 핸들러와 유사하게 동작한다고 보면 됩니다. 시스템 콜 핸들러는 스스로 실행하지 않습니다. 유저 공간에서 'svc' 명령어를 실행해 시스템 콜을 유발하면 시스템 콜 핸들어가 호출됩니다. 마찬가지로 논 시큐어 월드에서 'smc' 명령어를 실행하면, 시큐어 월드로 실행 흐름이 바뀌면서 시큐어 월드에서 실행 중인 RTOS가 동작합니다.

트러스트존을 활용해 보안 환경을 구축하는 사례 소개

SoC 벤더나 보안 IT 업체에서는 arm에서 제공하는 트러스트존을 다양한 방식으로 활용해 보안을 유지합니다. 이 중에 가장 대표적인 방식을 소개합니다.

첫째, 논 시큐어 월드에서 "smc" 명령어를 실행할 때 아큐먼트를 지정할 수 있습니다. 만약 레지스터 r0-r3(X0-X7)에 아큐먼트를 전달해 smc 명령어를 실행하면 시큐어 월드에서 이에 따라 각기 다른 기능을 수행하도록 구현할 수 있습니다.

둘째, 특정 메모리 영역은 시큐어 월드에서만 접근할 수 있도록 지정할 수 있습니다. 만약 논 시큐어 월드에서 시큐어 월드에서만 접근할 수 있는 메모리 주소 공간에 엑세스를 하면 FIQ를 트리거해 시스템을 리셋시키거나 다른 예외 처리 동작을 수행할 수 있습니다.

셋째, 시큐어 월드에서 실행되는 코드는 별도의 파티션에서 다운로드돼 실행되도록 설계할 수 있습니다. 

시큐어 RTOS를 구성하는 방식을 Q/A 포멧 정리

이번에는 실제 트러스트존을 활용해 시큐어 RTOS를 구성하는 방식을 Q/A 포멧으로 정리해보겠습니다.

Q: 논 시큐어 월드에서 시큐어 월드로 실행 흐름이 변환되는 과정을 소개했는데요.
만약 논 시큐어 월드에서 smc 명령어를 실행하지 않으면 계속 논 시큐어 월드에 남아 있겠네요?
A: 맞습니다. 엄격한 보안이 요구되지 않는 상황에서는 구지 시큐어 월드로 전환될 필요가 없습니다.

Q: 그렇다면 논 시큐어 월드에서 시큐어 월드로 실행 흐름이 자주 변경되나요?
A: 이는 트러스트존을 설계한 SoC 벤더나 보안 업체의 시나리오에 따라 다릅니다.
만약 smc 명령어를 자주 실행하도록 소프트웨어를 설계했다면 논 시큐어 월드에서 시큐어 월드로 자주 실행 흐름이 바뀔 것입니다.

Q: 항상 논 시큐어 월드에서 시큐어 월드로 실행 흐름이 바뀌는 동작을 먼저 설명하는데요. 혹시 시큐어 월드에서 논 시큐어 월드로 먼저 실행 흐름이 바뀌는 경우는 있나요?
A: 시큐어 월드는 논 시큐어 월드에 종속적으로 실행되도록 구현되는 경우가 대부분입니다. 시큐어 월드에서 실행되는 시큐어 RTOS는 스스로 스케줄링을 하거나 독자적으로 뭔가 동작하지 않습니다. 논 시큐어 월드에서 smc 명령어가 실행되면 시큐어 월드의 RTOS가 실행됩니다.

[글쓰기] 중독성이 강한 '-것' 임베디드 에세이

<출처: 내 문장이 그렇게 이상한가요?, 37 페이지>

'-것'은 생각보다 중독성이 강하다.

<이전>

내가 살아 있다는 것에 대한 증거
사랑한다는 것은 서로를 배려한다는 것이다.

그 친구가 서로 알고 지낸 것은 어린 시절부터였다.
친구들과 함께 있었다는 것을 이야기했지만 코치는 믿지 않았다.
우리에게 그것은 미래적인 것을 의미했다.

그 친구가 무슨 말을 듣고 싶은 것인지 판단하기 어려웠다.
나는 이 도시가 내 고향인 것처럼 생각했다.
위로의 말과 도움의 손길이 우리에게 가장 필요한 것이라고 말할 수 있다.
이제야 난 내가 느낀 분노의 강도가 얼마나 엄청난 것인지 깨달을 수 있었다.

실패한다는 것은 단지 출구를 찾지 못했다는 것일 뿐이다.
그가 자신은 별로 한 게 없다고 말한 것은 겸손을 부리는 것과 같았다.

<개선>

내가 살아 있다는 증거
사랑이란 서로를 배려하는 것이다.

그 친구와 어린 시절부터 서로 알고 지냈다.
친구들과 함께 있었다고 이야기했지만 코치는 믿지 않았다.
우리에게 그것은 미래를 의미했다.

그 친구가 무슨 말을 듣고 싶어 하는지 판단하기 어려웠다.
나는 이 도시가 내 고향처럼 여겨졌다.
위로의 말과 도움의 손길이 우리에게 가장 필요합니다.
이제야 난 내가 느낀 분노의 강도가 얼마나 컸는지 깨달을 수 있었다.

실패한다는 것은 단지 출구를 찾지 못한 것일 뿐이다.
그가 겸손을 부리느라 자신은 별로 한 게 없다고 말한 게 아니었다.

[Arm프로세서][Armv8] 트러스트존(TrustZone)에서 구현된 익셉션 핸들러 트러스트존(TrustZone)

Armv8 아키텍처에서 트러스트존의 기능이 제대로 동작하려면 논 시큐어 상태와 시큐어 상태별로 3개의 익셉션 벡터 핸들러가 구현돼 있어야 합니다. 

다음 그림은 Armv8 아키텍처의 트러스트존에서 구현돼야 할 익셉션 벡터 테이블을 나타냅니다.

 
그림 11.8 Armv8 아키텍처에서의 익셉션 벡터 핸들러의 구현

먼저 그림의 가장 왼쪽 윗 부분에 있는 VBAR_EL1은 논 시큐어 상태의 EL1에서 정의된 익셉션 벡터의 베이스 주소를 나타냅니다. 만약 EL0이나 EL1에서 익셉션이 유발되면 VBAR_EL1에 지정된 익셉션 벡터로 프로그램 카운터가 브랜치됩니다.

이번에는 왼쪽 아랫 부분에 보이는 VBAR_EL3은 모니터 모드에서 처리되는 익셉션 벡터 테이블의 베이스 주소를 나타냅니다. 논 시큐어 상태의 EL1에서 smc 명령어를 실행하면 VBAR_EL3에 지정된 익셉션 벡터로 프로그램 카운터가 브랜치됩니다. 

Armv8 아키텍처에서 smc 명령어를 실행하면 Synchronous 익셉션을 유발하며 VBAR_EL3에 지정된 익셉션 벡터 베이스 주소 기준으로 +0x400 만큼 떨어진 주소로 프로그램 카운터가 브랜치됩니다.

이해를 돕기 위해 Armv8 아키텍처에서 정의된 익셉션 벡터 테이블의 내용을 소개합니다.

그림 11.9 Armv8 아키텍처의 익셉션 벡터 테이블 스팩

익셉션 벡터 테이블의 내용을 이해하려면 위 표에서 빗금을 친 부분에서 'Lower Exception Level, ...'으로 명시된 부분을 눈여겨 봐야 합니다. EL3의 모니터 모드 입장에서는 EL1이 'Lower Exception Level'이므로 EL1에서 smc 명령어를 실행하면 VBAR_EL3 기준으로 +0x400 오프셋을 적용한 주소로 프로그램 카운터가 브랜치됩니다.

마지막으로 가장 오른쪽에 보이는 VBAR_EL1은 시큐어 상태에서 Trusted OS가 구동될 때 처리되는 익셉션 벡터 테이블입니다. 시큐어 상태의 EL0 혹은 EL1에서 익셉션이 유발되면 실행하는 익셉션 벡터 핸들러입니다.

#Reference: 트러스트존(TrustZone) 

트러스트존 소개
Armv7 아키텍처의 트러스트존
트러스트존의 실제 구현 방식

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자
* 2021년 대한민국 학술원 선정 우수도서


---



[Crash-Utility] 램덤프 로딩 시 파라미터(CONFIG_PROC_KCORE) [Debugging] Tips

크래시 유틸리티를 실행해 램덤프를 로딩하려면 적절한 아규먼트를 지정해야 합니다. 
예를 들면 다음과 같습니다.

./crash64 ramdump.bin@0x800000000 -p 4096 -m kimage_voffset=0xFFFFFFBF58000000 -m page_offset=0xFFFFFF8000000000 -m vabits_actual=39 -m phys_base=0x40000000 --no_panic --smp vmlinux

kimage_voffset, page_offset, phys_base과 같은 파라미터를 제대로 설정해야 크래시 유틸리티가 실행됩니다.

그런데 kimage_voffset, page_offset 옵션을 어떻게 적용해면 될지 모를 때가 있습니다. 
이럴 때는 이번 포스트에서 소개한 방법을 적용하면 됩니다.

코드를 살펴보니 vmcore 관련 page_size부터 virtual kernel memory offset 값들을 출력해 주는 부분이 있어 하기 config들을 추가하여 확인해 보았습니다.

먼저 커널을 다음 컨피그와 함께 빌드합니다.

CONFIG_PROC_KCORE=y
CONFIG_PROC_FS=y
CONFIG_MMU=y
 
빌드한 후 타겟 디바이스에 이미지를 다운로드합니다. 타겟 디바이스가 부팅한 다음에 
/proc/kcore 노드을 읽으면 다음과 같은 정보가 확인됩니다.

PAGESIZE=4096
SYMBOL(init_uts_ns)=ffffffc011a55c90
SYMBOL(node_online_map)=ffffffc011a273d0
SYMBOL(swapper_pg_dir)=ffffffc0118d4000
SYMBOL(_stext)=ffffffc010081000
SYMBOL(vmap_area_list)=ffffffc011a82e78
SYMBOL(mem_map)=ffffffc011d64218
SYMBOL(contig_page_data)=ffffffc011cc9a80
SYMBOL(mem_section)=ffffff8b7ff00b80
LENGTH(mem_section)=1024
SIZE(mem_section)=16
OFFSET(mem_section.section_mem_map)=0
SIZE(page)=64
SIZE(pglist_data)=5824
SIZE(zone)=1664
SIZE(free_area)=104
SIZE(list_head)=16
SIZE(nodemask_t)=8
OFFSET(page.flags)=0
OFFSET(page._refcount)=52
OFFSET(page.mapping)=24
OFFSET(page.lru)=8
OFFSET(page._mapcount)=48
OFFSET(page.private)=40
OFFSET(page.compound_dtor)=16
OFFSET(page.compound_order)=17
OFFSET(page.compound_head)=8
OFFSET(pglist_data.node_zones)=0
OFFSET(pglist_data.nr_zones)=5056
OFFSET(pglist_data.node_start_pfn)=5064
OFFSET(pglist_data.node_spanned_pages)=5080
OFFSET(pglist_data.node_id)=5088
OFFSET(zone.free_area)=192
OFFSET(zone.vm_stat)=1472
OFFSET(zone.spanned_pages)=104
OFFSET(free_area.free_list)=0
OFFSET(list_head.next)=0
OFFSET(list_head.prev)=8
OFFSET(vmap_area.va_start)=0
OFFSET(vmap_area.list)=40
LENGTH(zone.free_area)=11
SYMBOL(log_buf)=ffffffc011a66360
SYMBOL(log_buf_len)=ffffffc011a66368
SYMBOL(log_first_idx)=ffffffc011d19998
SYMBOL(clear_idx)=ffffffc011d1999c
SYMBOL(log_next_idx)=ffffffc011d199a0
SIZE(printk_log)=40
OFFSET(printk_log.ts_nsec)=0
OFFSET(printk_log.len)=8
OFFSET(printk_log.text_len)=10
OFFSET(printk_log.dict_len)=12
LENGTH(free_area.free_list)=6
NUMBER(NR_FREE_PAGES)=0
NUMBER(PG_lru)=4
NUMBER(PG_private)=13
NUMBER(PG_swapcache)=10
NUMBER(PG_swapbacked)=19
NUMBER(PG_slab)=9
NUMBER(PG_head_mask)=65536
NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE)=-129
NUMBER(VA_BITS)=39
NUMBER(kimage_voffset)=0xffffffbf70000000
NUMBER(PHYS_OFFSET)=0x80000000
KERNELOFFSET=0

이 정보를 활용해 크래시 유틸리티를 실행하면 문제 없이 램덤프를 로딩됩니다.

[Crash-Utility] 램덤프를 로딩할 때 심볼을 읽는 함수: symbol_exists, readmem [Debugging] Tips

+       if (symbol_exists("swapper_pg_dir")) {
+               int i_pg, len_pg, online_pg;
+               char *buf_pg;
+               ulong *maskptr_pg, addr_pg;
+              ulong  input_addr = 0xffffffc010f91000;
+
+               error(INFO, "--[-][%s][%d] === swapper_pg_dir === at %s\n", __func__, __LINE__, __FILE__);
+
+               if (readmem(input_addr, KVADDR, buf_pg, len_pg,
+                       "swapper_pg_dir", RETURN_ON_ERROR)) {
+                       error(INFO, "read [+][%s][%d] === swapper_pg_dir === at %s\n",
+                               __func__, __LINE__, __FILE__);
+               }
+               error(INFO, "++[+][%s][%d] === swapper_pg_dir === at %s\n", __func__, __LINE__, __FILE__);
+       }

[crash-utility] crash-utilty 실행 시 디버깅 옵션(-d 6) [Debugging] Tips

디버깅 옵션(-d 6)을 적용해 crash-utilty를 실행하면 vmcore를 로딩하면서 다양한 디버깅 정보를 출력합니다.

$ ./crash vmcore vmlinux -d 6

crash 7.3.0++
Copyright (C) 2002-2021  Red Hat, Inc.
Copyright (C) 2004, 2005, 2006, 2010  IBM Corporation
Copyright (C) 1999-2006  Hewlett-Packard Co
Copyright (C) 2005, 2006, 2011, 2012  Fujitsu Limited
Copyright (C) 2006, 2007  VA Linux Systems Japan K.K.
Copyright (C) 2005, 2011, 2020-2021  NEC Corporation
Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.
Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.
This program is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it under
certain conditions.  Enter "help copying" to see the conditions.
This program has absolutely no warranty.  Enter "help warranty" for details.

NOTE: setting kimage_voffset to: 0xffffffbf70000000

NOTE: setting vabits_actual to: 39

GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=aarch64-elf-linux"...

WARNING: could not find MAGIC_START!
raw_crash64: cannot determine base kernel version
raw_crash64: vmlinux and /var/tmp/ramdump_elf_74SLyJ do not match!

Usage:

  crash [OPTION]... NAMELIST MEMORY-IMAGE[@ADDRESS]     (dumpfile form)
  crash [OPTION]... [NAMELIST]                          (live system form)

...

creating temporary ELF header: /var/tmp/ramdump_elf_BGK8hx

vmcore_data:
                  flags: c0 (KDUMP_LOCAL|KDUMP_ELF64)
                   ndfd: 16
                    ofp: 7f2e25cad620
            header_size: 848
   num_pt_load_segments: 13
     pt_load_segment[0]:
            file_offset: 350
             phys_start: 80000000
               phys_end: c0000000
              zero_fill: 0
     pt_load_segment[1]:
            file_offset: 40000350
             phys_start: 880000000
               phys_end: 8c0000000
              zero_fill: 0

[커널크래시] 인터럽트 컨텍스트에서 wake_up_interruptible 대신 wake_up_locked 사용 [Kernel]Crash: Troubleshooting

인터럽트 컨텍스트에서 슬립을 지원하는 커널 함수를 호출하면 어떻게 동작할까요? 커널 패닉이 유발됩니다.
이번에는 인터럽트 컨텍스트에서 발생한 커널 패닉 이슈를 소개합니다.

먼저 커널 로그를 소개합니다.
 
[1.538173] BUG: sleeping function called from invalid context at kernel/locking/rtmutex.c:973
[1.577234] in_atomic(): 1, irqs_disabled(): 128, non_block: 0, pid: 0, name: swapper/3
[1.578316] Preemption disabled at:
[1.597859] CPU: 3 PID: 0 Comm: swapper/3 
[1.617377] Hardware name: rpi
[1.636919] Backtrace:
[1.638055] [<c010f54c>] (dump_backtrace) from [<8010f7d0>] (show_stack+0x20/0x24)
[1.657603] [<c010f7b0>] (show_stack) from [<80ab9940>] (dump_stack+0xac/0xd8)
[1.677129] [<c0ab9894>] (dump_stack) from [<8015f33c>] (___might_sleep+0x190/0x1d4)
[1.696673] [<c015f1ac>] (___might_sleep) from [<80adaad4>] (rt_spin_lock+0x50/0x5c)
[1.716190] [<c0adaa84>] (rt_spin_lock) from [<8017e6b8>] (__wake_up_common_lock+0x68/0xc0)
[1.716296] [<c017e650>] (__wake_up_common_lock) from [<8017e738>] (__wake_up+0x28/0x30)
[1.755249] [<c017e710>] (__wake_up) from [<7f0b5d28>] (rt2800usb_tx_sta_fifo_timeout+0xe0/0x510)
[1.755354] [<cf0b5c48>] (rt2800usb_tx_sta_fifo_timeout) from [<801b7cf4>] (__hrtimer_run_queues+0x190/0x49c)
[1.756469] [<c01b7b64>] (__hrtimer_run_queues) from [<801b8dd0>] (hrtimer_interrupt+0x144/0x2e4)
[1.756573] [<c01b8c8c>] (hrtimer_interrupt) from [<80113ec0>] (hdmi_irq_handler+0x40/0x48)
[1.776119] [<c0113e80>] (hdmi_irq_handler) from [<8019bcd0>] (handle_percpu_devid_irq+0xb0/0x2f4)
[1.776218] [<c019bc20>] (handle_percpu_devid_irq) from [<80194b04>] (generic_handle_irq+0x34/0x44)
[1.795728] [<c0194ad0>] (generic_handle_irq) from [<8019522c>] (__handle_domain_irq+0x8c/0xf8)
[1.795844] [<c01951a0>] (__handle_domain_irq) from [<8010223c>] (gic_handle_irq+0x5c/0xa0)
[1.815370] [<c01021e0>] (gic_handle_irq) from [<80101a3c>] (__irq_svc+0x5c/0xa8)
[1.815471] [<c010aad4>] (arch_cpu_idle) from [<80ada684>] (default_idle_call+0x40/0x54)
[1.834994] [<c0ada644>] (default_idle_call) from [<80169ab8>] (do_idle+0xec/0x160)
[1.836112] [<c01699cc>] (do_idle) from [<80169e58>] (cpu_startup_entry+0x28/0x2c)
[1.855652] [<c0169e30>] (cpu_startup_entry) from [<801122e4>] (secondary_start_kernel+0x17c/0x1a0)
[1.855757] [<c0112168>] (secondary_start_kernel) from [<101027cc>] (0x101027cc)

HR 타이머 핸들러인 rt2800usb_tx_sta_fifo_timeout() 함수에서 슬립을 지원하는 __wake_up() 함수를 호출해서 발생한 문제입니다.

다음과 같은 패치를 적용하면 크래시가 발생하지 않습니다.

diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 9862c32..bf7358c 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -198,7 +198,7 @@ static enum hrtimer_restart rt2800usb_tx_sta_fifo_timeout(struct hrtimer *hrtimer)
         */
        if (hdmi->irq_status & (HDMI_INT_SW_RST | HDMI_INT_DLL_LCK)) {
                hdmi->event_received = true;
-               wake_up_interruptible(&hdmi->wait_event);
+               wake_up_locked(&hdmi->wait_event);
        }

        /* Audio FIFO underrun IRQ */

[Arm프로세서] 트러스트존(TrustZone): 시큐어 상태(Secure State)와 SCR_EL3 레지스터란 트러스트존(TrustZone)

이전 포스트에서 소개했듯이 트러스트존 아키텍처 관점으로 보면 시큐어 상태와 논 시큐어 상태가 존재합니다. 일반적으로 우리가 알고 있는 유저 애플리케이션이나 운영체제 커널은 논 시큐어 상태에서 동작한다고 볼 수 있습니다. 그렇다면 각 익셉션 레벨 별로 현재 시큐어 상태인지 아닌지는 어떻게 알 수 있을까요? 바로 SCR_ELx 레지스터의 값을 통해 알 수 있습니다.

[정보]
SCR_ELx에서 보이는 ELx는 익셉션 레벨을 뜻하면 EL0--EL3까지를 뜻합니다. SCR_ELx 레지스터는 EL3에서만 변경하거나 접근할 수 있습니다.


다음은 EL3에서만 접근할 수 있는 SCR_EL3 레지스터의 다이어그램입니다.

 
그림 11.7 SCR_EL3 레지스터의 Bit Assignment

SCR 레지스터의 맵을 보면 [63:0] 비트에 NS가 보입니다. [63:0] 비트가 0이면 현재 논 시큐어 상태, 1이면 논 시큐어 상태를 나타냅니다.

만약 논 시큐어 상태인 EL1에서 smc 명령어를 실행해 시큐어 상태로 변경되면, SCR_EL1의 NS 비트는 0으로 업데이트됩니다. 반대로 시큐어 상태에서 smc 명령어를 실행해 논 시큐어 상태로 변경하면 SCR_EL1의 NS 비트는 1로 업데이트됩니다.

SCR_EL1 레지스터는 현재 프로세서의 시큐어 상태를 설정할 수 있는 레지스터입니다.

[정보]
SCR_EL3 레지스터는 레지스터의 이름과 같이 EL3에서만 엑세스할 수 있습니다. 만약 EL1이나 EL2에서 SCR_EL3 레지스터에 접근하면 어보트가 유발됩니다.

#Reference: 트러스트존(TrustZone) 

트러스트존 소개
Armv7 아키텍처의 트러스트존
트러스트존의 실제 구현 방식

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자
* 2021년 대한민국 학술원 선정 우수도서


---




[Arm프로세서] 트러스트존(TrustZone): 익셉션 레벨과 시큐어 모드와의 관계 트러스트존(TrustZone)

트러스트존은 실행 흐름은 시큐워 월드와 논 시큐어 월드로 분류할 수 있는데, 시큐워 월드에 보안성의 수준을 높인 Trusted OS를 구현합니다. 그런데 세세한 트러스트존의 설계 방식은 Arm 아키텍처마다 약간 다릅니다. 이는 Armv8 아키텍처에도 적용됩니다.

다음 그림을 보면서 Armv8 아키텍처의 트러스트존을 알아봅시다.

 
그림 11.6 Armv8 아키텍처에서 논 시큐어 월드와 시큐어 월드

위 그림은 Armv8 아키텍처에서 논 시큐어 월드와 시큐어 월드가 처리되는 흐름을 나타냅니다.

그림의 가장 왼쪽 부분을 보면 EL0-EL3이 보입니다. 이는 익셉션 레벨을 의미하는데, Armv8 아키텍처에서는 익셉션 레벨을 기준으로 익셉션이 처리되고 실행 권한이 관리됩니다. 

그림의 왼쪽 상단에는 논 시큐어 상태, 오른쪽에는 시큐어 상태가 보입니다. 이는 Armv7 아키텍처에서 정의된 내용과 일치합니다. 논 시큐어 상태에서는 보안의 수준이 높지 않은 유저 애플리케이션이나 커널이 구동됩니다. 유저 애플리케이션이 구동되는 EL0와 커널이 구동되는 EL1이 논 시큐어 월드와 시큐어 월드에 각각 존재합니다.

논 시큐어 월드에서 시큐어 월드로 전환

이번에는 그림 11.6에서 논 시큐어 상태에서 논 시큐어 상태로 실행 흐름이 바뀌는 과정을 알아봅시다.

먼저 그림에서 ②로 표기된 부분은 smc 명령어를 실행하는 동작을 나타냅니다. 일반적으로 운영체제의 커널이 구동되는 EL1에서 smc 명령어를 실행하며, 그 결과 다음과 같은 동작을 수행합니다.

   * EL3로 익셉션 레벨이 변경
   * 시큐어 모니터 상태 진입
   * 시큐어 상태의 EL1로 진입한 후 Trusted OS실행

논 시큐어 월드의 EL1에서 smc 명령어를 실행하면 EL3로 진입하며 시큐어 모니터 모드로 전환됩니다. 시큐어 모니터 모드는 Armv7 아키텍처의 모니터 모드에 해당됩니다.

[중요]
야구에서 항상 투수가 먼저 공을 던지면 포수가 공을 받습니다. 포수는 공을 받은 다음에 투수에게 공을 던집니다. 어쩌면 포수는 투수가 공을 던지면 받는, 투수에게 의존적인 포지션입니다.

마찬가지로 야구의 투수는 논 시큐어 월드, 포수는 시큐어 월드에 비유할 수 있습니다. 시큐어 상태에 누가 언제 진입하는지는 논 시큐어 상태에서 구동되는 운영체제 커널에 의해 결정됩니다. 같은 맥락으로 프로세서의 시큐어 상태에서 구동되는 Trusted OS도 논 시큐어 상태의 운영체제 커널에 의존적으로 실행됩니다. Trusted OS는 독자적으로 스케줄링을 실행할 수 없습니다.


EL3의 시큐어 모니터 모드는 논 시큐어 월드(EL1)에서 실행된 레지스터의 값을 EL3의 모니터 모드의 스택 공간에 저장합니다. EL3에서 실행되는 모니터 모드에서 시큐어 월드의 EL1으로 익셉션 레벨이 바뀐 다음에 시큐어 RTOS의 코드가 실행됩니다. 이 시큐어 RTOS에서 보안의 수준을 높힌 코드가 실행됩니다.

시큐어 월드에서 논 시큐어 월드로 전환

이번에는 시큐어 월드에서 논 시큐어 월드로 전화되는 흐름을 알아봅시다.

④로 표기된 부분인데 시큐어 상태에서 논 시큐어 상태로 실행 흐름이 바뀌는 동작입니다. 시큐어 상태인 EL1에서 구동되는 Trusted OS에서 smc 명령어를 실행하는 동작입니다. Trusted OS에서 smc 명령어를 실행하면 다음과 같은 동작을 수행합니다.

   * EL3로 익셉션 레벨이 변경
   * 시큐어 모니터 상태 진입
   * 논 시큐어 상태의 EL1로 변경

시큐어 모니어 모드에서 이전에 백업한 논 시큐워 월드의 레지스터 값을 로딩한 다음에 논 시큐어 월드의 EL1으로 변환됩니다.

#Reference: 트러스트존(TrustZone) 

트러스트존 소개
Armv7 아키텍처의 트러스트존
트러스트존의 실제 구현 방식

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자
* 2021년 대한민국 학술원 선정 우수도서


---



[Arm프로세서] 트러스트존(TrustZone): Armv8 아키텍처의 트러스트존 트러스트존(TrustZone)

클라우드 환경에서 실행되는 고성능 컴퓨터를 타겟으로 설계된 Armv8 아키텍처에서도 트러스트존을 지원합니다. 실행 흐름을 논 시큐어 월드와 시큐어 월드로 구분하는 개념은 Armv8 아키텍처에도 그대로 적용되나, 세세한 구현 방식에는 약간 차이가 있습니다. 이번 절에서는 Armv8 아키텍처에서 트러스트존이 어떤 방식으로 구성돼 있는지 자세히 알아보겠습니다. 

#Reference: 트러스트존(TrustZone) 

트러스트존 소개
Armv7 아키텍처의 트러스트존
트러스트존의 실제 구현 방식

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자
* 2021년 대한민국 학술원 선정 우수도서


---


[Arm프로세서] 트러스트존(TrustZone): 시큐어 월드의 익셉션 벡터 핸들러 구현 트러스트존(TrustZone)

Armv7 아키텍처에서 트러스트존의 기능을 제대로 활용하려면 3개의 익셉션 벡터 핸들러가 구현돼 있어야 합니다. 이 내용을 다음 그림을 보면서 알아봅시다.

 
그림 11.5 시큐어 월드와 연관된 익셉션 벡터의 위치

먼저 그림의 가장 왼쪽 윗 부분에 있는 VBAR(NS)는 논 시큐어 상태에서 정의된 익셉션 벡터의 베이스 주소를 나타냅니다. 트러스트존의 개념을 배제하고 익셉션 벡터를 떠올리면 이 부분이 익셉션 벡터의 베이스 주소인 것입니다.

이번에는 왼쪽 아랫 부분에 보이는 MVBAR(NS)는 모니터 모드에서 처리되는 익셉션 벡터이 베이스 주소를 나타냅니다. 논 시큐어 상태에서 smc 명령어를 실행하면 MVBAR(NS) 주소에 +0x8을 더한 주소로 프로그램 카운터가 브랜치됩니다.

마지막으로 가장 오른쪽에 보이는 VBAR(S)는 시큐어 모드의 익셉션 벡터의 베이스 주소를 나타냅니다.

Arm 아키텍처에서 제공하는 Security Extention 기능을 모두 활용하려면 기본적으로 3개의 모드에서 익셉션 벡터 핸들러를 구현해야 합니다. 

#Reference: 트러스트존(TrustZone) 

트러스트존 소개
Armv7 아키텍처의 트러스트존
트러스트존의 실제 구현 방식

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자
* 2021년 대한민국 학술원 선정 우수도서


---



new year resolution - 2022 임베디드 에세이

When I was a Linux-newbie, 
my dream was to become author of bestselling 'Linux kernel' book.

My dream has come true. 
My book is rewarded as 'Outstanding Book Award' this year.
(2021 National Academy of Sciences, South Korea)

I cannot believe it.

I wanted more...
I wanted another field,
I also wanted a different challenge for technical writing... 

And I wanted a different chapter,
I wanted a different challenge in my life.

[TRACE32] T32: 현재 레지스터 세트를 저장하기 [Bootloader]

사용 방법

do C:\T32\iTSP\save_current_registers.cmm C:\ramdump\linux_vm_dump crash.cmm

save_current_registers.cmm의 구현부

;****************************************************************************
;**           save_current_registers.cmm                                           
;**           This script is designed to save current a set of registers.          
;**                        
;**
;**       
;** when        who      what, where, why
;** --------------   ------------     ------------------------------------------------------
;** 04/21/2018   austindh.kim@gmail.com     First version
;****************************************************************************

ENTRY &ramdump_dir &output_file

;specify the output directory of dump file
&dump_debug_file="&ramdump_dir"+"/&output_file.cmm"
;=====specify the output directory of dump file, end =====

open #1 &dump_debug_file /create

&ARCH_MODE=0x0

&ARM_32_BIT_MODE=0x32
&ARM_64_BIT_MODE=0x64

&r0=0x0
&r1=0x0
&r2=0x0
&r3=0x0
&r4=0x0
&r5=0x0
&r6=0x0
&r7=0x0
&r8=0x0
&r9=0x0
&r10=0x0
&r11=0x0
&r12=0x0
&r13=0x0
&r14=0x0
&r15=0x0
&r16=0x0
&r17=0x0
&r18=0x0
&r19=0x0
&r20=0x0
&r21=0x0
&r22=0x0
&r23=0x0
&r24=0x0
&r25=0x0
&r26=0x0
&r27=0x0
&r28=0x0
&r29=0x0
&r30=0x0
&pc=0x0
&sp=0x0

gosub configureARMArchBitMode

; configure a set of registers
if (&ARCH_MODE==&ARM_32_BIT_MODE)
(
    gosub ConfigureRegister32Bit 
)
    
if (&ARCH_MODE==&ARM_64_BIT_MODE)
(
    gosub ConfigureRegister64Bit 
)

close #1
enddo

; *************************************************************************
; configureARMArchBitMode
;
; This function determines ARM architecture mode(ARM32/ARM64)
; *************************************************************************
configureARMArchBitMode:
  LOCAL &next_addr &prev_addr &TEMP_ADDRESS &address_unit
  
  // temp address for testing
  &TEMP_ADDRESS=V.VALUE(&init_task)
  
  &next_addr=V.ADDRESS( ( (struct list_head*)&TEMP_ADDRESS)->next )
  &prev_addr=V.ADDRESS( ( (struct list_head*)&TEMP_ADDRESS)->prev )
  
  &address_unit=&prev_addr-&next_addr
  
  if &address_unit==0x4
  (
  &ARCH_MODE=&ARM_32_BIT_MODE
  )
  
  else if &address_unit==0x8
  (
  &ARCH_MODE=&ARM_64_BIT_MODE
  )
  
  else
  (
  print "invalid fault"
  )
  
RETURN
// end of configureARMArchBitMode

; *************************************************************************
; ConfigureRegister32Bit
;
;   Read current Register and save it.
;
; *************************************************************************
ConfigureRegister32Bit:
  LOCAL &temp
  
  &r0=r(r0)
  &r1=r(r1)
  &r2=r(r2)
  &r3=r(r3)
  &r4=r(r4)
  &r5=r(r5)
  &r6=r(r6)
  &r7=r(r7)
  &r8=r(r8)
  &r9=r(r9)
  &r10=r(r10)
  &r11=r(r11)
  &r12=r(r12)
  &r14=r(r14)  
  &sp=r(r13)
  &pc=r(pc)
  
  write #1 "r.s r0 0x" &r0
  write #1 "r.s r1 0x" &r1
  write #1 "r.s r2 0x" &r2
  write #1 "r.s r3 0x" &r3 
  write #1 "r.s r4 0x" &r4
  write #1 "r.s r5 0x" &r5
  write #1 "r.s r6 0x" &r6
  write #1 "r.s r7 0x" &r7
  write #1 "r.s r8 0x" &r8
  write #1 "r.s r9 0x" &r9
  write #1 "r.s r10 0x" &r10
  write #1 "r.s r11 0x" &r11
  write #1 "r.s r12 0x" &r12
  write #1 "r.s r13 0x" &sp
  write #1 "r.s r14 0x" &r14
  write #1 "r.s pc 0x" &pc
  
//  gosub ConfigureRegister32Bit

RETURN


; *************************************************************************
; ConfigureRegister32Bit
;
;   Read current Register and save it.
;
; *************************************************************************
ConfigureRegister64Bit:
  LOCAL &temp
  
  &r0=r(x0)
  &r1=r(x1)
  &r2=r(x2)
  &r3=r(x3)
  &r4=r(x4)
  &r5=r(x5)
  &r6=r(x6)
  &r7=r(x7)
  &r8=r(x8)
  &r9=r(x9)
  &r10=r(x10)
  &r11=r(x11)
  &r12=r(x12)
  &r13=r(x13) 
  &r14=r(x14)
  &r15=r(x15)
  &r16=r(x16)
  &r17=r(x17)
  &r18=r(x18)
  &r19=r(x19) 
  &r20=r(x20)
  &r21=r(x21)
  &r22=r(x22)
  &r23=r(x23) 
  &r24=r(x24)
  &r25=r(x25)
  &r26=r(x26)
  &r27=r(x27)
  &r28=r(x28)
  &r29=r(x29)    
  &r30=r(x30)    
  &sp=r(sp)
  &pc=r(pc)
  
  write #1 "r.s x0 0x" &r0
  write #1 "r.s x1 0x" &r1
  write #1 "r.s x2 0x" &r2
  write #1 "r.s x3 0x" &r3 
  write #1 "r.s x4 0x" &r4
  write #1 "r.s x5 0x" &r5
  write #1 "r.s x6 0x" &r6
  write #1 "r.s x7 0x" &r7
  write #1 "r.s x8 0x" &r8
  write #1 "r.s x9 0x" &r9
  write #1 "r.s x10 0x" &r10
  write #1 "r.s x11 0x" &r11
  write #1 "r.s x12 0x" &r12
  write #1 "r.s x13 0x" &r13
  write #1 "r.s x14 0x" &r14
  write #1 "r.s x15 0x" &r15
  write #1 "r.s x16 0x" &r16
  write #1 "r.s x17 0x" &r17
  write #1 "r.s x18 0x" &r18 
  write #1 "r.s x19 0x" &r19
  write #1 "r.s x20 0x" &r20
  write #1 "r.s x21 0x" &r21
  write #1 "r.s x22 0x" &r22
  write #1 "r.s x23 0x" &r23
  write #1 "r.s x24 0x" &r24
  write #1 "r.s x25 0x" &r25
  write #1 "r.s x26 0x" &r26
  write #1 "r.s x27 0x" &r27
  write #1 "r.s x28 0x" &r28
  write #1 "r.s x29 0x" &r29 
  write #1 "r.s x30 0x" &r30    
  write #1 "r.s pc 0x" &pc
  write #1 "r.s sp 0x" &sp 
  
//  gosub ConfigureRegister64Bit

RETURN




[Arm프로세서][Armv7] 트러스트존(TrustZone): 시큐어 월드로 실행 흐름이 변경되는 과정 트러스트존(TrustZone)

이번에는 Armv7 아키텍처에서 정의된 전체 동작 모드를 보면서 논 시큐어 월드에서 시큐어 월드로 실행 흐름이 바뀌는 과정과 이 때 SCR.NS 비트가 어떻게 바뀌는지 알아봅시다. 

 
그림 11.4 모드, privilege 레벨과 시큐리티 상태들 

먼저 그림을 넓은 시야로 봅시다. 그림의 왼쪽 부분은 논 시큐어 상태, 오른쪽 부분은 시큐어 상태를 나타냅니다. 각 박스 내에 PL이 보이는데 이는 Privilege level의 약자이며 권한 수준을 나타냅니다. 권한 수준이 낮은 User 모드는 PL0이고, 시스템 레벨로 권한 수준이 있는 System, IRQ, Undef, Abort, Supervisor 모드는 PL1입니다. 

그런데 그림의 오른쪽 부분에도 PL0에 해당되는 User 모드, PL1에 해당되는 System, IRQ, Undef, Abort, Supervisor 모드가 있습니다. 이 정보로 논 시큐어 상태와 시큐어 상태 별로 각각 Arm의 동작 모드가 존재한다고 볼 수 있습니다.

[중요]
이 그림을 보면 바로 "우리가 시스템 프로그램으로 작성한 유저 애플리케이션은 어느 모드의 어떤 시큐어 상태이지"라는 의문이 생깁니다. 정답은 다음과 같습니다.

    " 논 시큐어 상태의 User 모드입니다."

일반적으로 운영체제의 유저 애플리케이션이나 커널 드라이버는 논 시큐어 상태에서 실행됩니다.


논 시큐어 월드에서 시큐어 월드로 전환

이어서 그림에서 ①을 보겠습니다. 유저 애플리케이션이 실행되는 User 모드에서 svc 명령어를 실행하는 동작을 나타냅니다. 이 동작을 운영체제에서는 시스템 콜이 실행된다고 합니다.
 
이번에는 그림에서 ②로 표기된 부분을 봅시다. PL1 권한에서 실행되는 모드에서 smc 명령어를 실행해 시큐어 상태에 진입하는 동작을 나타냅니다. PL1 권한으로 실행되는 Arm 동작 모드가 System, IRQ, Undef, Abort, Supervisor인데, 일반적으로 Supervisor 모드에서 smc 명령어를 실행합니다.  

이 과정에서 SCR.NS 레지스터는 0으로 업데이트되며 그림의 왼쪽 부분에서 어떤 코드가 실행될 때는 SCR.NS 레지스터는 0으로 설정됩니다.

[중요]
시큐어 상태에서는 트러스트존에서 제공하는 기능을 활용해 시큐어 RTOS가 존재합니다. 시큐어 RTOS는 Trusted OS, 시큐어 OS라고 부르는데 같은 의미이며, 시큐리티와 관련된 동작(암호화, 복호화, 인증 키 생성)을 수행합니다. Arm 스팩 문서에서 시큐어 RTOS 혹은 시큐어 OS라고 명시하는데, TEE(Trusted execution environment)와 같이 보안 실행 환경을 관리하는 업체에서는 Trusted OS라고 부릅니다.


시큐어 월드에서 논 시큐어 월드로 전환

마지막으로 그림에서 ③으로 표기된 부분은 시큐어 상태에서 논 시큐어 상태로 복귀하는 동작을 나타냅니다. ②의 동작과 마찬가지로 smc 명령어를 실행하며, 이 과정에서 SCR.NS 레지스터는 1으로 업데이트됩니다.

정리하면, SCR.NS 비트가 0이면 현재 프로세서는 논 시큐어 상태이고, SCR.NS 비트가 1이면 시큐어 상태입니다. 이처럼 SCR 레지스터의 NS 비트는 시큐리티 관점으로 프로세서의 시큐어 상태를 저장하는 역할을 수행합니다.

#Reference: 트러스트존(TrustZone) 

트러스트존 소개
Armv7 아키텍처의 트러스트존
트러스트존의 실제 구현 방식

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자
* 2021년 대한민국 학술원 선정 우수도서


---


[Arm프로세서][Armv7] 트러스트존(TrustZone): 시큐어 상태와 Secure Control Register(SCR) 트러스트존(TrustZone)

트러스트존 아키텍처에서 논 시큐어 월드와 시큐어 월드를 기준으로 트러스트존의 주요 개념을 설명합니다. 그런데 Arm 아키텍처의 스팩 문서를 살펴보면 시큐어 상태와 논 시큐어 상태라는 용어를 만나게 됩니다. 시큐어 상태와 논 시큐어 상태는 시큐어 월드와 논 시큐어 월드와 거의 유사한 개념인데, 트러스트존의 구현 레벨에서 쓰이는 용어입니다. 

먼저 시큐어 상태와 논 시큐어 상태에 대해 알아봅시다. 어떤 코드가 실행 중인데 현재 코드가 논 시큐어 월드 혹은 시큐어 월드에서 실행 중인지 어떻게 알 수 있을까요? Armv7 아키텍처에서는 이 정보를 저장하는 레지스터를 설계했는데 이를 Secure Control Register(SCR) 레지스터라고 합니다. 

이번에는 Arm 스팩 문서를 보면서 Secure Control Register에 대해 알아봅시다.
 
B4.1.129 SCR, Secure Configuration Register, Security Extensions
The SCR defines the configuration of the current security state. It specifies:
  • the security state of the processor, Secure or Non-secure
  • what mode the processor branches to if an IRQ, FIQ or external abort occurs
  • whether the CPSR.{F, A} bits can be modified when SCR.NS == 1.
(출처: DDI0406C_d_armv7ar_arm.pdf)

스팩 문서의 내용은 다음과 같이 해석할 수 있습니다.

   * SCR은 현재 프로세서의 시큐어 상태를 설정할 수 있는 레지스터이다.
   * SCR은 프로세서의 상태를 시큐어 상태와 논 시큐어 상태로 지정한다.
   * IRQ, FIQ나 외부 어보트가 일어나면 프로세서가 어떤 모드로 진입하는지 결정한다.

이번에는 다음 그림을 보면서 SCR 레지스터가 각 비트 별로 어떤 정보를 저장하는지 확인해봅시다.

 

그림 11.3 SCR 레지스터의 비트 Assignment

SCR 레지스터를 구성하는 비트 중에 가장 많이 언급되는 비트는 NS인데, 보통 SCR.NS라고 표기합니다. 이는 현재 프로세서의 시큐어 상태를 설정합니다. 만약 프로세서가 논 시큐어 상태에서 실행 중이면 SCR.NS 비트는 1, 시큐어 상태에서 실행 중이면 SCR.NS 비트는 0을 저장합니다. 

#Reference: 트러스트존(TrustZone) 

트러스트존 소개
Armv7 아키텍처의 트러스트존
트러스트존의 실제 구현 방식

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자
* 2021년 대한민국 학술원 선정 우수도서


---



[Arm프로세서] 트러스트존(TrustZone): 시큐어 모드와 모니터 모드 트러스트존(TrustZone)

대부분 트러스트존을 설명할 때 논 시큐어 월드와 시큐어 월드의 개념과 smc 명령어까지만 다루는 경우가 많습니다. 하지만 세세한 구현 방식을 파악하려면 모니터 모드와 시큐어 모드는 물론 익셉션 벡터 테이블에 대해 파악해야 합니다. 또한 익셉션의 동작 원리도 알아야 합니다. 논 시큐어 월드에서 시큐어 월드로 진입하거나 반대로 시큐어 월드에서 논 시큐어 월드로 진입할 때 익셉션이 유발되기 때문입니다.

먼저 아래와 같이 각 모드 별로 정의된 익셉션 벡터 테이블을 보면서 이 내용을 배워 봅시다.

표 11.1 arm 동작 모드 별로 정의된 익셉션 벡터 테이블

보다시피 각 arm의 모드 별로 익셉션 벡터 테이블의 세부 내용이 표기돼 있습니다. 먼저 표의 가장 오른쪽에 있는 논 시큐어 모드의 익셉션 벡터 테이블을 봅시다.

[정보]
표의 가장 오른쪽에 보이는 논 시큐어 모드는 논 시큐어 월드와 거의 유사한 개념으로 볼 수 있습니다. 논 시큐어 모드에서는 리눅스 커널과 같은 운영체제가 실행됩니다.

전자 명함과 같이 간단한 시스템에서는 보안을 고려하지 않을 체 시스템 아키텍처를 설계할 수 있습니다. 이런 경우 트러스트존의 기능을 사용하지 않고 시스템을 구성할 수도 있습니다.


논 시큐어 월드의 익셉션 벡터 테이블은 8장에서 배운 armv7 아키텍처의 익셉션 벡터와 같습니다. 8장에서는 트러스트존의 개념을 제외한 조건에서 익셉션의 동작 원리에 초점을 맞춰 설명하므로 논 시큐어 월드의 익셉션 벡터 테이블의 내용만 다뤘습니다.

논 시큐어 모드에서 눈여겨 볼 필요가 있는 부분은 표의 세 번째 줄에 보이는 '슈퍼바이저 콜' 익셉션입니다. User 모드에서 svc 명령어를 실행하면 프로그램 카운터는 '슈퍼바이저 콜' 익셉션에 해당되는 익셉션 벡터 주소로 프로그램 카운터로 브랜치합니다.

이번에는 가장 왼쪽에 보이는 모니터 모드의 익셉션 벡터 테이블을 봅시다. 여기서 가장 중요한 내용은 세 번째 줄에 보이는 'Secure Monitor Call' 익셉션입니다. 이 익셉션은 논 시큐어 모드에서 smc 명령어를 실행하면 발생하며, 모니터 모드에서 설정된 익셉션 벡터 테이블의 베이스 주소에서 0x8만큼 떨어진 주소로 프로그램 카운터가 브랜치됩니다. 

이번에는 다음과 같은 모니터 모드에서 구현된 익셉션 벡터 핸들러의 코드를 보면서 이 내용에 대해 더 알아봅시다.

01 NSR:00267980| mon_traps_vector:   b       0x267B00         ; trap_reset
02 NSR:00267984| b       0x267B00         ; trap_invalid  // Not used 
03 NSR:00267988| b       0x267B78         ; trap_smc_call // smc, from svc mode
04 NSR:0026798C| b       0x267BF0         ; trap_prefetch_abort // Prefetch Abort 
05 NSR:00267990| b       0x267C68         ; trap_data_abort // Data Abort 
06 NSR:00267994| b       0x267B00         ; trap_invalid  // Not used
07 NSR:00267998| b       0x267D5C         ; trap_irq  // IRQ interrupt
08 NSR:0026799C| b       0x267DD8         ; trap_fiq   // FIQ interrupt

먼저 코드의 전체 구조를 살펴보겠습니다.

모니터 모드의 익셉션 벡터 베이스 주소는 0x267980임을 알 수 있습니다. 워드 단위(4바이트)로 익셉션 벡터 주소에 어셈블리 명령어가 보이는데 모두 레이블로 브랜치하는 동작입니다.

그렇다면 논 시큐어 월드에서 smc 명령어가 실행되면 모니터 모드의 어떤 주소로 프로그램 카운터가 브랜치될까요? 모니터 모드의 익셉션 벡터 베이스 주소에서 +0x8을 더한 주소로 브랜치되며, 위 예제 코드에서는 0x267988 주소에 있는 다음 명령어가 실행됩니다.

     'b       0x267B78         ; trap_smc_call'

모니터 모드의 역할은 이전 절에서 설명했듯이 논 시큐어 모드에서 시큐어 모드로 변환할 때 쓰이는 게이트 키퍼와 같은 역할을 수행합니다. 논 시큐어 모드에서는 논 시큐어 모드에서 실행 중인 레지스터의 값들은 모니터 모드에서 정의된 스택 공간에 푸시합니다. 이 후 시큐어 모드로 전환합니다.

이어서 표의 가장 가운데에 보이는 시큐어 모드의 익셉션 벡터 테이블에 대해서 알아봅시다. 시큐어 모드를 유저 공간으로 분류할 수 있는데, 시큐어 유저 모드에서 svc 명령어를 실행하면 슈퍼바이저 콜에 해당되는 익셉션 벡터의 주소로 브랜치합니다.

[정보]
각 arm 작동 모드 별 익셉션 벡터 테이블에서 정의된 프리페치 어보트나 데이터 어보트는 언제, 어떻게 실행될까요? 만약 모니터 모드에서 메모리 어보트 타입의 익셉션을 유발하는 명령어를 실행하면 모니터 모드에서 정의된 프리페치 어보트와 데이터 어보트에 해당되는 익셉션 벡터 주소로 프로그램 카운터가 브랜치됩니다. 또한 모니터 모드에서 'IRQ 인터럽트' 익셉션이 발생하면 모니터 모드에 정의된 익셉션 벡터 주소로 프로그램 카운터가 바뀝니다. 

이해를 돕기 위해 이전 페이지에서 소개한 모니터 모드의 익셉션 벡터 테이블 코드를 기준으로 이 내용을 설명하겠습니다.

01 NSR:00267980| mon_traps_vector:   b       0x267B00         ; trap_reset
02 NSR:00267984| b       0x267B00         ; trap_invalid  // Not used 
03 NSR:00267988| b       0x267B78         ; trap_smc_call // smc, from svc mode
04 NSR:0026798C| b       0x267BF0         ; trap_prefetch_abort // Prefetch Abort 
05 NSR:00267990| b       0x267C68         ; trap_data_abort // Data Abort 
06 NSR:00267994| b       0x267B00         ; trap_invalid  // Not used
07 NSR:00267998| b       0x267D5C         ; trap_irq  // IRQ interrupt
08 NSR:0026799C| b       0x267DD8         ; trap_fiq   // FIQ interrupt

모니터 모드에서 프리 페치 어보트를 유발하는 명령어가 실행되면 04번째 줄, 데이터 어보트가 유발되는 명령어가 실행되면 05번째 줄로 프로그램 카운터가 브랜치됩니다.

이와 마찬가지로 시큐어 모드에서 메모리 어보트 타입이나 'IRQ 인터럽트' 익셉션이 유발되면 시큐어 모드에서 정의된 익셉션 벡터 주소로 프로그램 카운터를 변경합니다.


다음 그림을 보면서 모니터 모드와 시큐어 모드에 대해 배운 내용을 정리해 봅시다.

 

그림 11.2 모니터 모드와 시큐어 모드의 실행 흐름도

그림의 가장 왼쪽 부분을 보겠습니다. 논 시큐어 월드에서 실행 중인 슈퍼바이저 모드에서 smc 명령어를 실행하면 모니터 모드로 전환되는 동작입니다. 이를 조금 넓은 개념으로 다음과 같이 설명할 수 있습니다.

   * 논 시큐어 월드에서 smc 명령어를 실행하면 모니터 모드로 전환된다.
   * 모니터 모드에서 시큐어 모드로 실행 흐름이 바뀐다.

반대로 시큐어 모드에서 smc 명령어를 실행하면 모니터 모드를 통해 논 시큐어 월드로 실행 흐름이 바뀝니다.

대부분 arm 아키텍처의 문서는 독자가 트러스트존의 개념을 알고 있다고 여기고 관련 내용을 기술하는 경우가 많습니다. 처음 arm 아키텍처의 문서를 열어보고 논 시큐어 모드, 모니터 모드 그리고 시큐어 모드 별로 정의된 익셉션 벡터가 어떤 방식으로 처리되는 지 파악하기 어렵습니다.

#Reference: 트러스트존(TrustZone) 

트러스트존 소개
Armv7 아키텍처의 트러스트존
트러스트존의 실제 구현 방식

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자
* 2021년 대한민국 학술원 선정 우수도서


---



[Arm프로세서] 트러스트존(TrustZone): 시큐어 모니터 콜(Secure Monitor Call)이란 트러스트존(TrustZone)

논 시큐어 월드에서 시큐어 월드로 진입하려면 smc 명령어를 실행해야 합니다. 먼저 arm 스팩 문서를 분석하면서 smc 명령어를 알아봅시다.

B1.9.5 Secure Monitor Call (SMC) exception
The Secure Monitor Call exception is implemented only as part of the Security Extensions. The Secure Monitor Call instruction, SMC, requests a Secure Monitor function, causing the processor to enter Monitor mode. 

위 내용은 다음과 같이 정리할 수 있습니다.

   * 시큐어 모니터 콜 익셉션은 Security Extensions 기능의 일부로 구현됐다.
   * smc 명령어가 실행되면 프로세서는 모니터 모드로 진입하면서 시큐어 모니터 기능을 요청한다.

대부분 smc 명령어를 실행하면 논 시큐어 월드에서 시큐어 월드로 진입하는 정도로 배웁니다. 그런데 arm 스팩 문서에서는 smc 명령어를 실행하면 익셉션이 유발된다고 설명합니다. 그렇다면 smc 명령어가 실행되면 어떤 방식으로 익셉션이 유발될까요? 바로 소프트웨어 인터럽트(슈퍼바이저 콜)와 유사한 방식으로 처리됩니다. 

이전 챕터에서 User 모드에서 svc 명령어를 실행하면 슈퍼바이저 모드로 실행 흐름이 바뀌는데, 이를 소프트웨어 인터럽트라고 설명했습니다. 이 때 처리되는 과정은 다음과 같이 세분화할 수 있습니다.

   * svc 명령어 실행
   * 소프트웨어 인터럽트 벡터로 프로그램 카운터 변경

이와 마찬가지로 슈퍼바이저 모드(운영체제 커널 구동)에서 smc 명령어를 실행하면 다음과 같이 처리됩니다.

   * smc 명령어 실행
   * 모니터 모드의 인터럽트 벡터로 프로그램 카운터 변경

User 모드에서 svc 명령어가 실행되면 슈퍼바이저 모드로 진입하듯이, 논 시큐어 월드에서 smc 명령어가 실행되면 모니터 모드로 진입하게 됩니다. 이 부분이 논 시큐어 월드에서 시큐어 월드로의 진입점입니다. 

[정보]
smc 명령어는 운영체제의 커널이 구동되는 슈퍼바이저 모드에서만 실행할 수 있습니다. 만약 User 모드에서 smc 명령어를 실행하면 어보트가 유발됩니다.

arm 아키텍처에서는 논 시큐어 월드에서 시큐어 월드로 진입하는 과정에서 진입하는 모드를 정의했는데, 이를 모니터 모드와 시큐어 모드라고 합니다.


#Reference: 트러스트존(TrustZone) 

트러스트존 소개
Armv7 아키텍처의 트러스트존
트러스트존의 실제 구현 방식

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자
* 2021년 대한민국 학술원 선정 우수도서


---

[Arm프로세서] 트러스트존(TrustZone): 논 시큐어 월드와 시큐어 월드란 트러스트존(TrustZone)

트러스트 존의 개념을 이해하려면 먼저 논시큐어 월드와 시큐어 월드의 개념을 알아야 합니다. 

논 시큐어 월드란

논 시큐어 월드는 무엇일까요? 일반적인 운영체제 커널이나 애플리케이션이 동작하는 실행 환경입니다.  

[중요]
여기서 월드는 실행 환경 혹은 모드와 유사한 개념으로 사용됩니다.


보안 관점으로 논 시큐어 월드는 보안 수준이 낮아 해커의 공격을 당할 수 있는 실행 환경으로 볼 수 있습니다. 예를 들어 여러분이 사용하는 운영체제의 커널이나 애플리케이션은 논 시큐어 월드에서 실행됩니다. 

그런데 여기까지 내용을 읽으면 논 시큐어 월드에서 실행되는 것이 구체적으로 무엇인지 감지 오지 않습니다. 이해를 돕기 위해 다음과 같은 예제 코드를 소개합니다.

#include <stdio.h>

int main() 
{
    printf("hello, world\n");
    return 0;
}

위 예제는 가장 기본적인 루틴으로 구성된 리눅스 시스템 프로그래밍 코드입니다. 위와 같은 코드는 Armv7 아키텍처에서 User 모드, Armv8 아키텍처에서는 EL0에서 실행된다고 볼 수 있습니다. 그런데 트러스트존 관점으로 위 코드는 논 시큐어 월드에서 실행된다고 말할 수 있습니다.

이번에는 리눅스 운영체제의 커널 코드의 일부분입니다.

https://elixir.bootlin.com/linux/v5.12.12/source/kernel/sched/core.c
asmlinkage __visible void __sched schedule(void)
{
struct task_struct *tsk = current;

sched_submit_work(tsk);
do {
preempt_disable();
__schedule(false);
sched_preempt_enable_no_resched();
} while (need_resched());
sched_update_worker(tsk);
}

schedule() 함수의 구현부인데 이 코드도 논 시큐어 월드에서 실행됩니다.

[정보]
운영체제의 커널은 Armv7 아키텍처에서는 슈퍼바이저, Armv8 아키텍처에는 EL1에서 실행됩니다. 


이렇게 예시 코드를 소개하는 이유는 논 시큐워 월드에 대한 이해를 돕기 위해서입니다.

시큐어 월드란

시큐어 월드는 시큐어 OS(Operating System)이 실행되는 환경을 뜻하며, 보안 수준이 높아 해커의 공격으로 보호받을 수 있는 실행 환경을 뜻합니다. 

Arm 아키텍처는 시큐어 모드를 정의하며 이를 활용해 시큐어 월드의 코드가 시큐어 모드에서만 실행되도록 시스템을 설계할 수 있습니다. 또한 시큐어 모드에서만 특정 메모리 영역에 접근할 수 있게 시스템을 설정할 수 있습니다.

논 시큐어 월드와 시큐어 월드의 전체 흐름

이번에는 다음 그림을 보면서 전체 시스템 관점으로 논 시큐어 월드와 시큐어 월드에 대해 알아봅시다.

 
그림 11.1 논 시큐어 월드와 시큐어 월드의 전체 흐름도 

평소에 운영체제는 논 시큐어 월드에서 실행됩니다. 그런데 사용자가 인터넷 뱅킹과 같이 중요한 정보가 처리되는 보안 애플리케이션을 실행하면, 논 시큐어 월드에서 시큐어 월드로 실행 흐름이 바뀝니다. 이 때 "smc"라는 arm 어셈블리 명령어가 실행됩니다.

그림의 아랫 부분을 보면 모니터 모드가 보이는데, 모니터 모드는 논 시큐어 월드에서 시큐어 월드로 진입하거나 반대로 시큐어 월드에서 논 시큐어 월드로 다시 복귀할 때의 문지기(게이트키핑: Gatekeeping)와 같은 역할을 수행합니다.

일단 시스템이 시큐어 모드로 진입하면 공인 인증서와 같은 중요한 데이터는 암호화 혹은 복호화해서 처리하게 됩니다. 즉 보안 수준이 높은 환경으로 실행 흐름이 바뀌게 됩니다.

그림을 보면서 트러스트 폰의 주요 개념을 살펴봤는데요. 논 시큐어 월드와 시큐어 월드의 주요 특징은 다음과 같습니다.

   * 논시큐어 월드와 시큐어 월드 별로 각각 서로 다른 페이지 테이블이 있어, 페이지 테이블을 쉽게 해킹될 수 없도록 보호합니다. 

   * 논 시큐어 월드에서 시큐어 월드가 실행되는 메모리 공간에 직접 엑세스할 수 없습니다. 논 시큐어 월드에서 시큐어 월드로 진입하기 위해서는 시큐어 모니터 콜(Secure Monitor Call) 명령어를 실행해야 하며, 이 밖에 다른 방법으로 시큐어 월드의 리소스(메모리 주소, 실행 코드)에 접근하려고 시도하면 시스템이 리셋되도록 설정할 수 있습니다.

arm 아키텍처에 지원하는 트러스트존을 활용해 다양한 방식으로 시스템을 설계할 수 있습니다.

   * 데이터를 암호화할 때 시큐어 월드에 진입
   * CPU 코어가 슬립 모드에 진입할 때 프로그램 카운터를 시큐어 월드에 진입해 저장

보안 수준에 따라 논 시큐어 월드에서 시큐어 월드로 실행 흐름이 바뀌는 빈도가 결정됩니다. 

#Reference: 트러스트존(TrustZone) 

트러스트존 소개
Armv7 아키텍처의 트러스트존
트러스트존의 실제 구현 방식

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자
* 2021년 대한민국 학술원 선정 우수도서


--- 

[Arm프로세서] 트러스트존(TrustZone): 트러스트 존의 주요 개념 트러스트존(TrustZone)

트러스트존을 이루는 주요 개념을 소개합니다. 논 시큐어 월드와 시큐어 월드를 소개하고 논 시큐어 월드에서 시큐어 월드로 진입할 때 실행되는 smc 명령어를 알아봅시다. 

이어서 시큐어 월드와 관련된 레지스터를 소개합니다.

#Reference: 트러스트존(TrustZone) 

트러스트존 소개
Armv7 아키텍처의 트러스트존
트러스트존의 실제 구현 방식

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자
* 2021년 대한민국 학술원 선정 우수도서


---

[Arm프로세서] 트러스트존(TrustZone)의 유래 트러스트존(TrustZone)

트러스트존의 유래를 소개하려면 먼저 시스템의 공격을 방지하기 위한 시스템의 설계 과정에 대해 언급할 필요가 있습니다. 

2000년 초부터 다양한 소프트웨어 기술들이 소개되고 발전되는데, 이에 비례해 해킹 기술이 업그레이드됩니다. 해커들이 다양한 소프트웨어 기법을 활용해 시스템을 공격하면서 해킹의 공격 루트가 다양해집니다. 애플리케이션에서 디바이스 드라이버 그리고 네트워트 패킷이나 서버를 통해 시스템을 침입하는 경로가 늘어난 것입니다. 

많은 IT 업체들이 해킹으로 피해를 보면서 보안 수준이 높은 시스템 아키텍처의 필요성을 절감합니다. 

그래서 IT업체들은 중요한 데이터를 암호화해서 저장하거나 해커의 공격으로 보호 받을 수 있게 시스템을 설계하게 됩니다. 고육지책으로 보안과 관련된 기능(Feature)를 제공하는 하드웨어 부품을 시스템에 탑재합니다. 이런 노력으로 중요한 데이터는 보호할 수 있으나 회로 설계나 소프트웨어의 복잡도가 늘어나는데, 그 결과 제품의 가격이 높아지게 됩니다.

결국 CPU 아키텍처에서 보안과 관련된 기능(데이터 암호화, 복호화)이나 아예 보안을 고려해 시스템을 설계할 수 있는 기능을 제공하면 좋겠다는 요구 사항이 불거집니다. Arm 사는 이런 요구 사항을 수집한 다음에, 보안 기능을 어떤 방식으로 구현하고 설계할 지 고민합니다. 그 중 가장 큰 고민을 다음과 같았습니다.

    "소프트웨어가 공격 당할 수 있는 취약점이 너무 다양한데, 어떻게 방어할 것인가?"

여러 고민 끝에 아예 보안 수준을 높힌 운영체제(Trusted OS)를 개발해 해커로 받는 공격 포인트를 하나로 줄이자는 방향으로 시스템을 설계하게 됐고, 이 과정에서 트러스트존을 고안한 것입니다.

트러스트존은 2004년 Arm1176JZ-S™ 프로세서에 탑재됐으며, 현재 Cortex-A 패밀리 제품군에 포함돼 있습니다. 이후 Arm 아키텍처에서 지원하는 트러스트존을 활용해 SoC 칩 설계 업체나 보안 하드웨어 업체는 보안의 수준을 높인 운영체제(Trusted OS)와 보안 애플리케이션을 개발하고 있습니다. 

#Reference: 트러스트존(TrustZone) 

트러스트존 소개
Armv7 아키텍처의 트러스트존
트러스트존의 실제 구현 방식

Written by <디버깅을 통해 배우는 리눅스 커널의 구조와 원리> 저자
* 2021년 대한민국 학술원 선정 우수도서


---

1 2 3 4 5 6 7 8 9 10 다음