[커널 20차] 4주차

2023.06.12 03:41

김희찬 조회 수:79

일자 : 2023. 06. 03

범위 : 리눅스 커널 내부 구조 5장 

참가 : 약 20명

  
  

Chapter 5.

  

6. Ext3 파일시스템과 Ext4 파일시스템

  

Q. p.147 저널링 공간이란? 

  

A. 저널은 부트섹터 다음으로 이어지며 inode 테이블 번호가 저장된 파일로 구성되어 있습니다. 

https://codedatasotrage.tistory.com/71

  

Q. journalctl을 통해 시스템 로그를 읽어들일 때도 저널링 공간에서 읽는 것인가?

  
  

Q. 메타 데이터만 저장한다? 전체 데이터를 저장해야 전원 Off 시 등 데이터 손실을 막을 수 있지 않나?

그 저장한다고 하는 메타 데이터라 함은 무엇인가? Jourling 모드가 3개가 있는데, 그 모드 각각은 무엇을 보호하고자 함인가? 그리고 어떻게 보호하는가?

  
  

7. 가상 파일시스템

  

Q. file_operations

  

ext2나 FAT 등 파일시스템 관련 함수들은 커널 안에서 기본적으로 구현이 되어 있으나, 다른 디바이스 관련된 함수는 별도의 모듈을 커널에 포함해야함. 파일 시스템을 특정 가능하니, 

  

사용자 입장은 file_operations 함수만 호출하면됨, 

file_operations는 인터페이스 function들이 구현되어 있음.

파일시스템 개발자는 file_operations 인터페이스를 구현하

  
  

Q. journaling 단어의 유래

A0.logging이랑 다른 느앙스라서 다른 단어를 쓰지 않았을까 추정

A1.저널링이 어떤 것을 남긴다. 읽을 수 있게 남기는 것

[https://www.dailyhagah.com/%EC%A0%80%EB%84%90%EB%A7%81journaling%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80/](https://www.dailyhagah.com/%EC%A0%80%EB%84%90%EB%A7%81journaling%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80/)

  
  
  

Chapter 6. 인터럽트와 트랩 그리고 시스템 호출

  

1. 인터럽트 처리 과정 

  

Q. 디바이스 2개가 하나의 라인을 공유할 때, 디바이스 두개에 해당하는 인터럽트 핸들러를 어떻게 구분할까?

디바이스 ID를 가지고 핸들러 1, 2가 자신의 디바이스에서 핸들러를 디바이스 ID를 통해 구분하며, 아닐 경우 Early Return.

디바이스의 구분을 핸들러에 위임하는 형태 (핸들러 구현 시 자기가 처리해야할 디바이스가 아니면 처리를 하면 안되는 부분이네요..)

  

A. https://www.oreilly.com/library/view/linux-device-drivers/0596000081/ch09s06.html#:~:text=Whenever%20two%20or%20more%20drivers,passing%20each%20its%20own%20dev_id%20.

Whenever two or more drivers are sharing an interrupt line and the hardware interrupts the processor on that line, the kernel invokes every handler registered for that interrupt, passing each its own dev_id. Therefore, a shared handler must be able to recognize its own interrupts, and should quickly exit when its own device has not interrupted.

(강준원님 공유)

  
  

Q. p.172 마지막 문단 설명 오류

A. 1) 트랩의 번호에 대응되는 엔트리에 등록되어있는 함수 호출이 먼저, 2) 그 다음 커널은 현재 실행 중이던 태스크의 문맥을 저장

  
  

Q. SAVE_ALL에 eip 등 내용 미포함 (?)

1) CPU가 eflags , cs, eip, ss, esp 등의 레지스터를 스택에 저장

2) 트랩 번호 대응되는 엔트리에 등록된 함수 호출

3) 커널은 실행중인 태스크 문맥 저장(SAVE_ALL이 호출되어 control unit에 의해 자동으로 저장되어 있는 eflags , cs, eip, ss, esp 등을 제외하고 인터럽트 핸들러가 사용할 수 있는 모든 CPU레지스터를 스택에 저장)

  

위와 같은 순서로 시스템 콜이 호출되는 것이 맞아 보임

  

https://www.oreilly.com/library/view/understanding-the-linux/0596005652/ch04s06.html

SAVE_ALL saves all the CPU registers that may be used by the interrupt handler on the stack, except for eflags , cs, eip, ss, and esp, which are already saved automatically by the control unit (see the earlier section "Hardware Handling of Interrupts and Exceptions“). The macro then loads the selector of the user data segment into ds and es.

(강준원님 공유)

  
  
  

3. 새로운 시스템 호출 구현

  

Q. sys call return이 long인 이유, 커널에서는 long을 int보다 많이 쓰는지, 왜 그러한지

A0. 실제 커널 코드를 보았을때 long이 더 많았다

A1. cpu bit에 따라서 long은 달라지므로 좀더 유연하기에 int보다 long을 쓴다고 생각

  

Q. kernel에서 unsigned정수형 타입을 호환성 측면에서 size_t를 주로 쓰는지 그렇지 않은지

A0. 용도에 따라서 다를 것이라 생각

  
  

4. 시스템 호출 구현 확장

  

Q. p.182 사용자 공간에 쓰기가 가능한지 확인하기 위해 access_ok() 라는 커널 내부 함수를 사용한다. 사용자 공간에 쓰기가 가능한지 왜 확인하는가? 무엇을 확인하는가?

  

A. res 를 할당하는 것은 사용자의 몫이기 때문에 (공간을 할당하지 않았을 수도 있으므로), 보안적인 측면이 강함.

  

A. 두가지 체크 방법이 있을 수 있음. 접근하려는 주소에 Read, Write 권한이 제대로 있느냐, write를 하려는데 유저가 주소를 잘못 건드려서 거나, 악성의 이유로 잘못된 주소를 넘겨줄 경우, ReadOnly인 곳에 Write 를 할 경우.

커널에서 실행하는 것이기 때문에 커널 모드로 실행되고 있는 것이고, 커널의 특정 영역을 Write 하도록 변수를 넘겼을 경우 등등을 체크한다.

  

The access_ok macro is just a quick check for the probable validity of the pointer. For example, it would catch mistaken calls with NULL or read-only arguments.

Ideally, the driver should recover even if later the access functions fail. This could however happen only after some expensive hardware operations. Therefore checking early may make the driver more robust against the most common user-space programmer errors.

(이영재님 공유)

  
  

Q. 그림 6.19 if(!start) return -1 에서 start (?) search 여아 하는것이 아닌가?

A. if(!search) return -1 이 맞아보임.

  
  
  
  
  
  
  

Chapter 7. 리눅스 모듈 프로그래밍

  

1. 마이크로 커널
  

2. 모듈 프로그래밍 무작정 따라하기
  

Q. 모듈이 커널 공간에서 동작하기 때문에, 유저 공간에서 사용되는 libc 라이브러리를 사용하지 못한다고 알고 있는데, 맞는지 궁금합니다.

  

A. libc 라이브러리에서 시스템 콜들을 사용하고 있는데, 사용자가 커널 호출을 하는 것을 커널 안에서 실행할 수 없는 격이므로, 사용하지 못하는게 맞습니다. (애초부터 모듈은 커널 내부에서 실행되고, 시스템 함수를 직접 호출하면 된다.)

  
  
  
  

3. 시스템 호출 hooking

  

Q. 그림 7.4 int syscall_hooking_init(void) 함수 내용

  

write_cr0 를 하면 모든 커널이 모든 페이지를 Write할 수 있도록 셋팅 되는데

set_memory_rw 함수는 같은 역할을 하는 중복

  

[https://stackoverflow.com/questions/67789564/is-it-necessary-to-call-set-memory-rw-after-disabling-cr0-write-protect-to-mod](https://stackoverflow.com/questions/67789564/is-it-necessary-to-call-set-memory-rw-after-disabling-cr0-write-protect-to-mod)

  

CR0 레지스터는 아래에 설명이 있습니다~

[https://en.wikipedia.org/wiki/Control_register](https://en.wikipedia.org/wiki/Control_register)

  

Examples: [https://cpp.hotexamples.com/examples/-/-/write_cr0/cpp-write_cr0-function-examples.html](https://cpp.hotexamples.com/examples/-/-/write_cr0/cpp-write_cr0-function-examples.html)

  

Q. cr0. 전역적으로 쓰쓰기를 가능하게 한 후, set_memory_rw를 통해 시스템콜 테이블을 쓴거 아닌가?

A. write_cr0 라인을 통해서 커널이 모든 page에(read only 이든 아니든) 쓰기 가능하게 만들었고, set_memory_rw 라인을 통해서 sys_call_table 위치에 data를 쓴 것이 아니라, sys_call_table이 있는 위치에서 3개 page를 Read & Write 가능하도록 enable 시킨 것으로 보입니다.

sys_call_table이 있는 페이지의 속성을 Read & Write가 모두 가능하도록 바꾼거죠.

근데 이 set_memory_rw 라인 자체가 이미 write_cr0를 하는 순간 안해도 되는 부분이라(커널이 모든 페이지에 쓰기 가능해졌으므로) 중복이라고 보았습니다.

  

[https://stackoverflow.com/questions/67789564/is-it-necessary-to-call-set-memory-rw-after-disabling-cr0-write-protect-to-mod](https://stackoverflow.com/questions/67789564/is-it-necessary-to-call-set-memory-rw-after-disabling-cr0-write-protect-to-mod)

(강준원님 공유)

  

Q. 제가 set_memory_rw 함수 부분의 라이브러리를 찾아보았는데, 쓰기만 가능하게 하는 함수를 찾을 수가 없었습니다. 만약에 테이블 자체도 읽히지 않는다면 Read&Write를 가능하게 만든거라고 추론해보았습니다.

  

https://elixir.bootlin.com/linux/v4.19.13/source/arch/arm64/mm/pageattr.c#L75

  

A. 둘 중 하나만 있어도 코드가 동작할 것 같습니다. (실습때 시도해볼 필요가 있음)

  

4. 시스템 호출 hooking 모듈 확장

  

Q. list_del_init 함수를 호출하여 lsmod 명령을 통해 모듈 리스트에서 숨길 수 있음. 그 반대는? 숨겼던 모듈을 숨김해제 (lsmod에서도 보일 수 있도록) 하는 방법은?

  

A. 전역변수로 struct list_head * hidden 하나 선언해서 모듈 초기화할때 삭제하기 전에 저장해두고 나중에 모듈 삭제할때 복구하면 될것같긴 하네요

  
  
  

Chapter 8. 디바이스 드라이버

1. 디바이스 드라이버 일반  

-

2. 문자 디바이스 드라이버 구조

  

Q. class_create 함수를 왜 사용하는가.

udev : 디바이스에서 이벤트 일어났을 때 받아주는 객체

번호 제목 글쓴이 날짜 조회 수
공지 [공지] 스터디 정리 노트 공간입니다. woos 2016.05.14 629
208 [커널20차] 8주차 이경재 2023.06.24 74
207 [커널20차] 7주차 이경재 2023.06.18 78
206 [커널 18차] 108주차 kkr 2023.06.17 52
» [커널 20차] 4주차 김희찬 2023.06.12 79
204 [커널 19차] 55 주차 Min 2023.06.10 28
203 [커널 19차] 54 주차 Min 2023.06.03 34
202 [커널 18차] 106주차 kkr 2023.06.03 66
201 [커널 20차] 3주차 김희찬 2023.06.03 73
200 [커널 19차] 52 ~ 53 주차 Min 2023.05.27 55
199 [커널 20차] 2주차 김희찬 2023.05.20 141
198 [커널 19차] 51 주차 Min 2023.05.13 45
197 [커널 20차] 1주차 김희찬 2023.05.13 193
196 [커널 18차] 102주차 kkr 2023.05.07 75
195 [커널 19차] 50 주차 Min 2023.05.07 31
194 [커널 19차] 49 주차 Min 2023.04.29 55
193 [커널 19차] 48 주차 Min 2023.04.23 83
192 [커널 18차] 100주차 kkr 2023.04.22 83
191 [커널 18차] 99주차 kkr 2023.04.16 78
190 [커널 19차] 47 주차 Min 2023.04.15 41
189 [커널 19차] 45, 46 주차 Min 2023.04.10 59
XE Login