Post

리눅스 커널 빌드에러 해결하기

리눅스 커널 빌드에러 해결하기

운영체제 실습과제 중 겪었던 문제를 작성해보았다.

상황

첫 주차 실습과제는 실습환경 구성이다.
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일간의 사투가 시작되었다.

문제 상황 요약

  1. xrealloc 함수 부분에서 계속 use-after-free 에러
  2. vmlinux 빌드 실패
  3. 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 문구와 함께 해당 파일을 계속 삭제해 버렸다. 그래서 정상적으로 빌드가 되지 않았다.
  • 문제 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 해준 후 다시 부팅하니까 정상적으로 커널이 로딩 되었다.

성공 사진!

imageimage

This post is licensed under CC BY 4.0 by the author.