Krafton Jungle/5. PintOS

[PintOS 2주차] Day 8

munsik22 2025. 5. 22. 16:16

"인터넷 없음, 보안" 문제 해결

어제 저녁부터 갑자기 와이파이 연결이 끊기면서 "인터넷 없음, 보안"이라고만 뜨고 인터넷에 연결이 안 되는 이슈가 발생했다 🤯

시간이 지나면 해결되겠거니 했지만, 오늘 아침에 출근을 해도 문제가 해결되지 않았다. 여러 해결 방법들이 실패한 가운데, 다시 접속에 성공한 해결책은 다음과 같다. (참고)

  1. Win + R을 누른 후, services.msc를 실행한다.
  2. WWAN AutoConfig를 더블클릭한다.
  3. 시작 유형을 자동으로 바꾼 후 시작(S)을 누른다.

이후 인터넷 없음 문제가 해결되어서 이렇게 블로그 글을 쓸 수 있게 되었다 😇


read-normal 해결하기

read-normal 테스트에서 계속 PF가 발생했고, backtrace 추적 결과 filesize()에서 오류가 발생했음을 알 수 있었다.

if (!is_kernel_vaddr(file)) {
	printf("[FILESIZE] Invalid kernel ptr at fd=%d: %p\n", fd, file);
	exit(-1);
}

filesize()에 위와 같이 디버깅용 코드를 추가했고, 그 결과는 다음과 같다.

이 말은 fd = 2에 들어 있는 file 포인터가 커널 포인터가 아니라 유저 주소 (0x423C038)라는 뜻이다. 그 뒤 file_length(file)에서 이 주소를 접근하려다가 PF가 발생했고, 그게 커널 모드에서 발생했다고 판단되어 Kernel panic이 발생한 것이다.

Executing 'close-normal':
Your FDT is at 0x8004240088
[DEBUG] file_open() calloc returned: 0x800423c038
[FILESYS_OPEN] file = 0x800423c038
(close-normal) begin
(close-normal) open "sample.txt"
[DEBUG] file_open() calloc returned: 0x800423c038
[FILESYS_OPEN] file = 0x800423c038
-> file = 0x423c038
[OPEN] fd = 2, file = 0x423c038 (as uint64 = 423c038)
(close-normal) close "sample.txt"
[CLOSE] file ptr = 0x423c038
Page fault at 0x423c044: not present error reading page in kernel context.

openclose 둘 다 동작은 잘 하고 있지만, 파일이 커널 영역이 아닌 유저 영역에 매핑된 것이 문제다. file_open()에서 리턴한 file의 주소는 0x800423C038인데, open()에 도착한 주소는 0x423C038이다. 포인터의 상위 비트가 잘려서 저장된다는 문제가 있다는 것을 알게 되었다.

#include "filesys/filesys.h"

함수 자체에는 문제가 없었고, 컴파일러에 의해 발생한 문제였다.

컴파일러는 선언되지 않은 filesys_open()암시적으로 해석한다.
  • C 언어는 선언 없이 쓰면 기본적으로 int 리턴이라고 가정
  • 64비트 포인터의 상위 32비트가 날아감
  • fdt[fd]에 유저 주소가 저장됨 → 커널에서 dereference → Page Fault 발생
개념 교훈
함수 선언 생략 컴파일러는 int로 간주해서 큰일 남
포인터 상위 비트 잘림 리턴 타입이 64비트인데 32비트로 처리되면 발생
#include 순서 선언이 있어도 포함 안 하면 말짱 도루묵

 

당연히 기본 코드에 filesys.h 헤더 파일이 포함되있는 줄 알고 구현하다 봉변을 당했다. 앞으로는 헤더 파일도 꼼꼼하게 체크하는 습관을 길러야겠다 😓


2주차 코드 및 결과

🔹 create

bool create (const char *file, unsigned initial_size) {
	if (!is_valid(file)) exit(-1);
	lock_acquire(&filesys_lock);
	bool res = filesys_create(file, initial_size);
	lock_release(&filesys_lock);
	return res;
}

🔹 remove

bool remove (const char *file) {
	if (!is_valid(file)) exit(-1);
	lock_acquire(&filesys_lock);
	bool res = filesys_remove(file);
	lock_release(&filesys_lock);
	return res;
}

🔹 open

int open (const char *filename) {
	if (!is_valid(filename)) exit(-1);
	struct thread *curr = thread_current();
	int fd;
	bool is_not_full = false;
	for(fd = 2; fd < 64; fd++) {
		if (curr->fdt[fd] == NULL) {
			is_not_full = true;
			break;
		}
	}
	if (!is_not_full) return -1; // Return -1 if fdt is full

	lock_acquire(&filesys_lock);
	struct file *file = filesys_open(filename);
	lock_release(&filesys_lock);
	if (file == NULL) return -1; // Return -1 if file is not opened

	curr->fdt[fd] = file;
	return fd;
}

🔹 filesize

int filesize (int fd) {
	if (fd < 2 || fd > 63) exit(-1); // invalid fd
	struct file *file = thread_current()->fdt[fd];
	if (file == NULL) exit(-1);

	lock_acquire(&filesys_lock);
	off_t res = file_length(file);
	lock_release(&filesys_lock);
	return res;
}

🔹 read

int read (int fd, void *buffer, unsigned size) {
	if (size == 0) return 0;
	if (!is_valid(buffer)) exit(-1);
	if (fd == 0) { // fd0 is stdin
		char *buf = (char *) buffer;
		for (int i = 0; i < size; i++) {
			buf[i] = input_getc();
		}
		return size;
	}
	else if (fd == 1) exit(-1); // fd1 is stdout (invalid)
	else if (fd < 2 || fd > 63) exit(-1); // invalid fd
	else {
		struct file *file = thread_current()->fdt[fd];
		if (file == NULL) exit(-1);
		lock_acquire(&filesys_lock);
		off_t res = file_read(file, buffer, size);
		lock_release(&filesys_lock);
		return res;
	}
}

🔹 write

int write(int fd, const void *buffer, unsigned size) {
	if (!is_valid(buffer)) exit(-1);
	if(fd == 1) { // fd1 is stdout
		putbuf(buffer, size);
		return size;
	} else if (fd == 0) exit(-1); // fd0 is stdin (invalid)
	else if (fd < 2 || fd > 63) exit(-1); // invalid fd
	else {
		struct file *file = thread_current()->fdt[fd];
		if (file == NULL) exit(-1);
		lock_acquire(&filesys_lock);
		off_t res = file_write(file, buffer, size);
		lock_release(&filesys_lock);
		if (res < 0) return -1;
		return res;
	}
}

🔹 seek

void seek (int fd, unsigned position) {
	if (fd < 2 || fd > 63) exit(-1); // invalid fd
	struct thread *curr = thread_current();
	struct file *file = curr->fdt[fd];
	if (file == NULL) exit(-1);
	lock_acquire(&filesys_lock);
	file_seek(file, position);
	lock_release(&filesys_lock);
}

🔹 tell

unsigned tell (int fd) {
	if (fd < 2 || fd > 63) exit(-1); // invalid fd
	struct thread *curr = thread_current();
	struct file *file = curr->fdt[fd];
	if (file == NULL) exit(-1); // file not found
	lock_acquire(&filesys_lock);
	off_t res =  file_tell(file);
	lock_release(&filesys_lock);
	return res;
}

🔹 close

void close (int fd) {
	if (fd < 2 || fd > 63) exit(-1); // invalid fd
	struct thread *curr = thread_current();
	struct file *file = curr->fdt[fd];
	if (file == NULL) exit(-1);
	curr->fdt[fd] = NULL;
	// if (fd == curr->next_fd && curr->next_fd > 2) curr->next_fd--;
	lock_acquire(&filesys_lock);
	file_close(file);
	lock_release(&filesys_lock);
}

🔸 is_valid

bool is_valid(const void *addr) {
	if (addr == NULL) return false;
	if (!is_user_vaddr(addr)) return false;
	if (pml4_get_page(thread_current()->pml4, addr) == NULL) return false;
	return true;
}

38 of 95 tests failed.