리눅스 커널 빌드에러 해결하기
운영체제 실습과제 중 겪었던 문제를 작성해보았다.
상황
첫 주차 실습과제는 실습환경 구성이다.
ubuntu는 버전이 상관없다고 하셔서24.04LTS
버전을 설치하였다.
ubuntu 설치후 kernel을 설치해야하는데
버전을 꼭5.5.13
버전을 설치하라고 하셔서
이 버전 kernel 설치 중 발생한 오류를 해결한 내용에 대해 작성해 보려고 한다.
설치 과정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# step 1 (커널 빌드를 위해 필요한 패키지 설치)
sudo apt update \
&& sudo apt install build-essential libncurses6 libncurses5-dev bin86 libssl-dev libelf-dev flex bison dwarves -y
# step 2 (원하는 커널 버전 다운로드)
cd /go/to/your/dir
wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.5.13.tar.xz \
&& tar xvf linux-5.5.13.tar.xz
# step 3 (커널 빌드)
cd linux-5.5.13
sudo cp -v /boot/config-$(uname -r) .config
sudo make menuconfig
- LOAD -> .config
- SAVE -> .config
- EXIT
sudo make -j$(nproc) # <- 여기서 부터 문제가 발생함!
sudo make modules_install
sudo make install
문제
커널 빌드를 위해 make를 하게되면 xrealloc
함수 부분에서 계속 use-after-free
에러가 발생하였다.
분명 배포한 커널 버전인데 warning
도 아니고 왜 error
가 발생하는지 도무지 이해가 되지않아 GPT와 함께 해결하려다가 3시간 가량의 사투 끝에 원인을 알게 되었다.
하지만… 안타깝게도 이게 끝이 아니였다. 정상적으로 빌드가 되어야 bzImage
가 생기는데 계속 생기지 않았다.
또한, vmlinux 빌드에 성공하면 System.map
, modules.builtin.modinfo
이라는 파일도 자동으로 생겨야하는데 계속 생기지않았다…
vmlinux 빌드가 계속 실패해서 bzImage
가 생성 되지 않은 것 같다.
또, 문제가 생겼다. 커널 컴파일 성공과 install 까지 완료했지만 커널 부팅이 되지 않는 문제가 생겼다.
GPT와 함께 3일간의 사투가 시작되었다.
문제 상황 요약
xrealloc
함수 부분에서 계속use-after-free
에러vmlinux
빌드 실패kernel
설치 성공! but, 설치한 kernel로 부팅 실패..
원인
- 문제 1의 원인
ubuntu24.04LTS
버전에서는gcc13
이 기본적으로 설치되어 있는데 이 gcc13에서는 내가 설치하려는 커널버전(5.5.13)의 xrealloc 함수 구현을 error라고 하고 있는 것이였다.
- 문제 2의 원인
- vmlinux를 빌드 하는중에
objtools
라는 프로그램으로 obj 파일들을 검증을 하게 되는데arch/x86/entry/thunk_64.o: warning: objtool: missing symbol table
문구와 함께 해당 파일을 계속 삭제해 버렸다. 그래서 정상적으로 빌드가 되지 않았다.
- vmlinux를 빌드 하는중에
- 문제 3의 원인
- 내가 직접 빌드한 커널은 서명되지 않은 상태의 커널인데 내 컴퓨터가 secure boot 설정이 되어 있어 서명되지않은 커널로 부팅을 하지 못한 것이였다.
해결과정
문제 1
검색해 보니 gcc10
버전이 해당 커널버전(5.5.13)이 배포되었던 시기와 비슷해서 해당 컴파일러로 컴파일로 시도하니 컴파일이 정상적으로 수행되었다.
1
2
3
4
5
# gcc10 설치
sudo apt install gcc-10 g++-10 -y
# 아까 문제 였던곳 컴파일
sudo make HOSTCC=gcc-10 CC=gcc-10 -j$(hproc)
다른 make 들도 HOSTCC=gcc-10 CC=gcc-10
옵션을 주고 하면 된다.
문제 2
make 실행하면서 나오는 출력을 파일을 파일로 빼서 에러들을 확인했는데 thunk_64.o
파일이 계속 삭제 되는 것을 확인했다. 하지만 처음에는 왜 삭제가 되고 있는지 알지 못했다..
가장 처음에는 현재 설치하는 커널이 예전 버전이라 이를 빌드할때 사용되는 현재 패키지 버전들과 충돌이 생겨 되지 않는다고 판단해 사용하는 패키지들을 해당 커널 시기의 버전으로 다운 그레이드하여 진행해 보았다. 하지만 성공하지 못했다.. (여기서 오래걸렸다.)
다운그레이드 과정 (binutils 2.34로 변경하기 위해)
wget http://ftp.gnu.org/gnu/binutils/binutils-2.34.tar.xz
tar -xvf binutils-2.34.tar.xz
./binutils-2.34/configure --prefix=/opt/binutils-2.34 --disable-nls --enable-gold --enable-ld=default
sudo make -j$(nproc)
sudo make install
export PATH=/opt/binutils-2.34/bin:$PATH
export LD_LIBRARY_PATH=/opt/binutils-2.34/lib:$LD_LIBRARY_PATH
export LD=/opt/binutils-2.34/bin/ld
export AS=/opt/binutils-2.34/bin/as
export OBJCOPY=/opt/binutils-2.34/bin/objcopy
export OBJDUMP=/opt/binutils-2.34/bin/objdump
hash -r
그후 왜 삭제 되는지에 대해 찾아보다가 objtool
이 해당 obj 파일을 검증하다가 empty symbol table 이라는 문구와 함께 삭제하는 것을 알게되어 thunk_64.o
파일만 objtool 검사를 넘어 가도록 설정하였다.
arch/x86/entry/Makefile
을 수정하여 검사를 넘어 가도록 하였다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the x86 low level entry code
#
OBJECT_FILES_NON_STANDARD_entry_64_compat.o := y
OBJECT_FILES_NON_STANDARD_thunk_$(BITS).o := y # 이거 추가
CFLAGS_syscall_64.o += $(call cc-option,-Wno-override-init,)
CFLAGS_syscall_32.o += $(call cc-option,-Wno-override-init,)
obj-y := entry_$(BITS).o thunk_$(BITS).o syscall_$(BITS).o
obj-y += common.o
obj-y += vdso/
obj-y += vsyscall/
obj-$(CONFIG_IA32_EMULATION) += entry_64_compat.o syscall_32.o
CFLAGS_REMOVE_thunk_$(BITS).o := -fno-PIE # 이거 추가
이후 다시 빌드하니 정상적으로 vmlinux가 생성되고 System.map 파일 등도 정상적으로 생성되었다. 이제 정상적으로 커널 빌드가 완료되었다.
문제 3
이 문제는 비교적 간단하게 해결했다.
boot 설정이 secure boot
로 설정 되어 있었기 때문에 직접 빌드한 커널로 부팅하지 못한 것이기 때문에
GRUB 설정에 들어가서 secure boot를 disabled
해준 후 다시 부팅하니까 정상적으로 커널이 로딩 되었다.