[ISSUE] 유저 스택 작성 후 hex dump 시 커널 패닉 발생 - Week9-11-team03/Pintos-User-Program GitHub Wiki

Phase 0. 증거

Executing 'args-many a b c d e f g h i j k l m n o p q r s t u v':
000000004747ff00  00 00 00 00 00 00 00 00-ca ff 47 47 00 00 00 00 |..........GG....|
000000004747ff10  d4 ff 47 47 00 00 00 00-d6 ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff20  d8 ff 47 47 00 00 00 00-da ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff30  dc ff 47 47 00 00 00 00-de ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff40  e0 ff 47 47 00 00 00 00-e2 ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff50  e4 ff 47 47 00 00 00 00-e6 ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff60  e8 ff 47 47 00 00 00 00-ea ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff70  ec ff 47 47 00 00 00 00-ee ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff80  f0 ff 47 47 00 00 00 00-f2 ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff90  f4 ff 47 47 00 00 00 00-f6 ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ffa0  f8 ff 47 47 00 00 00 00-fa ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ffb0  fc ff 47 47 00 00 00 00-fe ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ffc0  00 00 00 00 00 00 00 00-00 00 61 72 67 73 2d 6d |..........args-m|
000000004747ffd0  61 6e 79 00 61 00 62 00-63 00 64 00 65 00 66 00 |any.a.b.c.d.e.f.|
000000004747ffe0  67 00 68 00 69 00 6a 00-6b 00 6c 00 6d 00 6e 00 |g.h.i.j.k.l.m.n.|
000000004747fff0  6f 00 70 00 71 00 72 00-73 00 74 00 75 00 76 00 |o.p.q.r.s.t.u.v.|
0000000047480000  Page fault at 0x47480000: not present error reading page in kernel context.
Interrupt 0x0e (#PF Page-Fault Exception) at rip=800421667a
 cr2=0000000047480000 error=               0
rax 0000000047480000 rbx 0000000000000000 rcx 0000000000000020 rdx 0000000000000000
rsp 000000800423fe70 rbp 000000800423fec0 rsi 000000800423f028 rdi 0000000000000001
rip 000000800421667a r8 000000800423fd88  r9 000000800421b446 r10 0000000000004000
r11 0000000000000000 r12 0000000000000000 r13 0000000000000000 r14 0000000000000000
r15 0000000000000000 rflags 00000206
es: 0010 ds: 0010 cs: 0008 ss: 0010

스택 포인터가 주소값을 감소시키며 성장한다는 걸 생각할 때, 가장 큰 주소경계인 474780000에서 문제가 터진다는 것은, hex_dump를 할 때 굳이 볼 필요 없는 부분에 접근하는 것으로 보인다. hex_dump()는 다음과 같이 호출되고 있다.

hex_dump(_if.rsp, _if.rsp, KERN_BASE - _if.rsp, true);

Phase 1. 가설

hex_dump(_if.rsp, _if.rsp, KERN_BASE - _if.rsp, true); 호출에서 문제가 발생했습니다.

이 호출은 사용자 스택 포인터(_if.rsp)부터 시작해서 커널 베이스 주소(KERN_BASE)까지의 모든 메모리를 덤프하려고 시도합니다.

이는 매우 큰 메모리 영역을 덤프하려는 시도로, 대부분의 경우 불필요하고 위험합니다.

Phase 2. 불변식

hex_dump 범위를 KERN_BASE - _if.rsp에서 USER_STACK - _if.rsp로 바꿔주면 hex_dump가 가상 범위를 침범하지 않을 것이다.

Phase 3. OLF

hex_dump(_if.rsp, _if.rsp, USER_STACK - _if.rsp, true);

Phase 4. 불변식 침해

Calibrating timer...  26,188,800 loops/s.
hd0:0: detected 313 sector (156 kB) disk, model "QEMU HARDDISK", serial "QM00001"
hd0:1: detected 20,160 sector (9 MB) disk, model "QEMU HARDDISK", serial "QM00002"
hd1:0: detected 102 sector (51 kB) disk, model "QEMU HARDDISK", serial "QM00003"
Formatting file system...done.
Boot complete.
Putting 'args-many' into the file system...
Executing 'args-many a b c d e f g h i j k l m n o p q r s t u v':
000000004747ff00  00 00 00 00 00 00 00 00-ca ff 47 47 00 00 00 00 |..........GG....|
000000004747ff10  d4 ff 47 47 00 00 00 00-d6 ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff20  d8 ff 47 47 00 00 00 00-da ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff30  dc ff 47 47 00 00 00 00-de ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff40  e0 ff 47 47 00 00 00 00-e2 ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff50  e4 ff 47 47 00 00 00 00-e6 ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff60  e8 ff 47 47 00 00 00 00-ea ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff70  ec ff 47 47 00 00 00 00-ee ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff80  f0 ff 47 47 00 00 00 00-f2 ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ff90  f4 ff 47 47 00 00 00 00-f6 ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ffa0  f8 ff 47 47 00 00 00 00-fa ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ffb0  fc ff 47 47 00 00 00 00-fe ff 47 47 00 00 00 00 |..GG......GG....|
000000004747ffc0  00 00 00 00 00 00 00 00-00 00 61 72 67 73 2d 6d |..........args-m|
000000004747ffd0  61 6e 79 00 61 00 62 00-63 00 64 00 65 00 66 00 |any.a.b.c.d.e.f.|
000000004747ffe0  67 00 68 00 69 00 6a 00-6b 00 6c 00 6d 00 6e 00 |g.h.i.j.k.l.m.n.|
000000004747fff0  6f 00 70 00 71 00 72 00-73 00 74 00 75 00 76 00 |o.p.q.r.s.t.u.v.|
system call!
Execution of 'args-many a b c d e f g h i j k l m n o p q r s t u v' complete.

Comment

사실 아직 완전히 이해되진 않는다. 아래는 가설 정립에 도움을 준 퍼플렉시티의 답변

페이지 폴트 오류 분석

제공된 증거를 분석해보면, 이 문제는 hex_dump() 함수 호출과 관련된 페이지 폴트 예외입니다. 다음과 같은 원인을 유추할 수 있습니다:

1. 메모리 경계 침범

  • 메모리 덤프는 0x4747ff00부터 시작하여 0x4747fff0까지 표시되고, 그 직후 0x47480000 주소에서 페이지 폴트가 발생했습니다.
  • 이 주소(0x47480000)는 정확히 페이지 경계에 위치하며, 이 페이지는 매핑되지 않았거나 접근 권한이 없는 상태입니다.

2. hex_dump() 함수 호출 문제

  • hex_dump(_if.rsp, _if.rsp, KERN_BASE - _if.rsp, true); 호출에서 문제가 발생했습니다.
  • 이 호출은 사용자 스택 포인터(_if.rsp)부터 시작해서 커널 베이스 주소(KERN_BASE)까지의 모든 메모리를 덤프하려고 시도합니다.
  • 이는 매우 큰 메모리 영역을 덤프하려는 시도로, 대부분의 경우 불필요하고 위험합니다.

3. 스택 포인터와 메모리 접근 방향

  • 스택 포인터는 주소값을 감소시키며 성장하지만, hex_dump()는 시작 주소에서부터 증가하는 방향으로 메모리를 읽습니다.
  • 따라서 hex_dump()는 스택의 내용을 표시한 후 스택 이후의 메모리 영역(더 높은 주소)까지 계속 접근하려고 시도합니다.
  • 이 과정에서 0x47480000과 같은 매핑되지 않은 페이지에 접근하게 됩니다.

4. 과도한 덤프 범위

  • KERN_BASE - _if.rsp는 사용자 스택 포인터부터 커널 베이스 주소까지의 전체 범위를 의미합니다.
  • 이는 필요한 스택 데이터보다 훨씬 더 많은 메모리를 덤프하려고 시도하는 것입니다.
  • 실제로 필요한 것은 스택에 있는 인자와 관련 데이터뿐이지만, 이 호출은 그 이상의 영역까지 접근하려고 합니다.

5. 해결 방안

이 문제를 해결하기 위해서는 hex_dump() 호출을 수정하여 필요한 메모리 영역만 덤프하도록 해야 합니다:

  1. 덤프할 메모리 크기를 제한하는 방법:
    // 예: 스택에서 필요한 부분만 덤프 (예: 256바이트)
    hex_dump(_if.rsp, _if.rsp, 256, true);
    
  1. 스택의 실제 사용 범위만 덤프하는 방법:
    // 스택 시작 주소와 현재 스택 포인터 사이의 영역만 덤프
    hex_dump(_if.rsp, _if.rsp, PHYS_BASE - _if.rsp, true);
    
  1. 페이지 경계를 고려하여 안전하게 덤프하는 방법:
    // 현재 페이지 내에서만 덤프 (4KB 이내)
    hex_dump(_if.rsp, _if.rsp, MIN(4096, PHYS_BASE - _if.rsp), true);
    

결론적으로, 이 오류는 hex_dump() 함수에 너무 큰 메모리 범위를 지정하여 매핑되지 않은 메모리 영역에 접근하려고 시도했기 때문에 발생했습니다. 덤프할 메모리 범위를 필요한 부분으로 제한하면 이 문제를 해결할 수 있습니다.


Perplexity로부터의 답변: pplx.ai/share