
Linux kernel 4.1.15 소스 트리로, CVE-2018-5873에 중점을 두어 취약점 분석 및 익스플로잇 연구를 위한 참고 자료를 제공합니다.
다음은 Linux 버전 4의 릴리스 노트입니다. 이 문서를 주의 깊게 읽으십시오. 이 문서는 이것이 무엇에 관한 것인지, 커널을 설치하는 방법, 그리고 문제가 발생했을 때 해야 할 일을 설명합니다.
Linux란 무엇인가?
Linux는 Unix 운영 체제의 클론으로, Linus Torvalds가 인터넷 전체에 걸친 느슨하게 연결된 해커 팀의 도움을 받아 처음부터 작성했습니다. POSIX 및 Single UNIX Specification 준수를 목표로 합니다.
현대적인 완전한 Unix에서 기대할 수 있는 모든 기능을 갖추고 있습니다. 여기에는 진정한 멀티태스킹, 가상 메모리, 공유 라이브러리, 요구 로딩, 공유 copy-on-write 실행 파일, 적절한 메모리 관리, IPv4 및 IPv6를 포함한 멀티스택 네트워킹이 포함됩니다.
GNU General Public License에 따라 배포됩니다. 자세한 내용은 함께 제공되는 COPYING 파일을 참조하십시오.
어떤 하드웨어에서 실행되나요?
원래 처음에는 32비트 x86 기반 PC(386 이상)용으로 개발되었지만, 오늘날 Linux는 (최소한) Compaq Alpha AXP, Sun SPARC 및 UltraSPARC, Motorola 68000, PowerPC, PowerPC64, ARM, Hitachi SuperH, Cell, IBM S/390, MIPS, HP PA-RISC, Intel IA-64, DEC VAX, AMD x86-64, AXIS CRIS, Xtensa, Tilera TILE, AVR32 및 Renesas M32R 아키텍처에서도 실행됩니다.
Linux는 페이지 메모리 관리 장치(PMMU)와 GNU C 컴파일러(gcc)(GNU Compiler Collection, GCC의 일부)의 포트가 있는 한 대부분의 범용 32비트 또는 64비트 아키텍처로 쉽게 이식할 수 있습니다. Linux는 PMMU가 없는 여러 아키텍처로도 포팅되었지만, 기능이 분명히 다소 제한됩니다. Linux는 자체적으로도 포팅되었습니다. 이제 커널을 사용자 공간 애플리케이션으로 실행할 수 있습니다. 이를 UserMode Linux(UML)라고 합니다.
문서:
인터넷과 서적 모두에서 전자 형식으로 제공되는 많은 문서가 있으며, Linux 특정 및 일반 UNIX 질문에 관한 문서도 있습니다. LDP(Linux Documentation Project) 서적은 모든 Linux FTP 사이트의 문서 하위 디렉토리에서 찾아보는 것이 좋습니다. 이 README는 시스템에 대한 문서를 의미하지 않습니다. 훨씬 더 좋은 출처가 있습니다.
Documentation/ 하위 디렉토리에는 다양한 README 파일이 있습니다. 예를 들어, 일반적으로 일부 드라이버에 대한 커널 특정 설치 노트가 포함되어 있습니다. 각 파일에 무엇이 포함되어 있는지에 대한 목록은 Documentation/00-INDEX를 참조하십시오. Changes 파일을 읽으십시오. 여기에는 커널 업그레이드로 인해 발생할 수 있는 문제에 대한 정보가 포함되어 있습니다.
Documentation/DocBook/ 하위 디렉토리에는 커널 개발자와 사용자를 위한 여러 가이드가 포함되어 있습니다. 이 가이드는 여러 형식으로 렌더링할 수 있습니다. PostScript (.ps), PDF, HTML 및 man-pages 등이 있습니다. 설치 후 "make psdocs", "make pdfdocs", "make htmldocs" 또는 "make mandocs"는 요청된 형식으로 문서를 렌더링합니다.
커널 소스 설치:
전체 소스를 설치하는 경우, 권한이 있는 디렉토리(예: 홈 디렉토리)에 커널 tarball을 넣고 압축을 풉니다.
xz -cd linux-4.X.tar.xz | tar xvf -
"X"를 최신 커널의 버전 번호로 바꾸십시오.
/usr/src/linux/ 영역을 사용하지 마십시오! 이 영역에는 라이브러리 헤더 파일에서 사용되는 (일반적으로 불완전한) 커널 헤더 세트가 있습니다. 이들은 라이브러리와 일치해야 하며, 우연히 발생하는 커널에 의해 엉망이 되어서는 안 됩니다.
패치를 적용하여 4.x 릴리스 간에 업그레이드할 수도 있습니다. 패치는 xz 형식으로 배포됩니다. 패치로 설치하려면 모든 최신 패치 파일을 가져와서 커널 소스의 최상위 디렉토리(linux-4.X)로 이동한 후 실행하십시오.
xz -cd ../patch-4.x.xz | patch -p1
현재 소스 트리의 버전 "X"보다 큰 모든 버전에 대해 "x"를 순서대로 바꾸십시오. 그러면 문제가 없을 것입니다. 백업 파일(일부-파일-이름~ 또는 일부-파일-이름.orig)을 제거하고 실패한 패치(일부-파일-이름# 또는 일부-파일-이름.rej)가 없는지 확인할 수 있습니다. 만약 있다면, 여러분이나 제가 실수한 것입니다.
4.x 커널용 패치와 달리, 4.x.y 커널(안정 커널이라고도 함)용 패치는 증분식이 아니라 기본 4.x 커널에 직접 적용됩니다. 예를 들어, 기본 커널이 4.0이고 4.0.3 패치를 적용하려는 경우, 먼저 4.0.1 및 4.0.2 패치를 적용해서는 안 됩니다. 마찬가지로, 커널 버전 4.0.2를 실행 중이고 4.0.3으로 이동하려는 경우, 4.0.3 패치를 적용하기 전에 먼저 4.0.2 패치를 되돌려야 합니다(즉, patch -R). 이에 대한 자세한 내용은 Documentation/applying-patches.txt에서 읽을 수 있습니다.
또는 스크립트 patch-kernel을 사용하여 이 프로세스를 자동화할 수 있습니다. 현재 커널 버전을 확인하고 발견된 모든 패치를 적용합니다.
linux/scripts/patch-kernel linux
위 명령의 첫 번째 인수는 커널 소스의 위치입니다. 패치는 현재 디렉토리에서 적용되지만, 두 번째 인수로 대체 디렉토리를 지정할 수 있습니다.
오래된 .o 파일과 종속성이 남아 있지 않은지 확인하십시오.
cd linux make mrproper
이제 소스가 올바르게 설치되었을 것입니다.
소프트웨어 요구 사항
4.x 커널을 컴파일하고 실행하려면 다양한 소프트웨어 패키지의 최신 버전이 필요합니다. 필요한 최소 버전 번호와 이러한 패키지의 업데이트를 얻는 방법은 Documentation/Changes를 참조하십시오. 이러한 패키지의 지나치게 오래된 버전을 사용하면 추적하기 매우 어려운 간접 오류가 발생할 수 있으므로, 빌드 또는 작동 중 명백한 문제가 발생할 때만 패키지를 업데이트할 수 있다고 가정하지 마십시오.
커널 빌드 디렉토리:
커널을 컴파일할 때, 모든 출력 파일은 기본적으로 커널 소스 코드와 함께 저장됩니다. "make O=output/dir" 옵션을 사용하면 출력 파일( .config 포함)의 대체 위치를 지정할 수 있습니다. 예:
커널 소스 코드: /usr/src/linux-4.X
빌드 디렉토리: /home/name/build/kernel
커널을 구성하고 빌드하려면 다음을 사용하십시오.
cd /usr/src/linux-4.X
make O=/home/name/build/kernel menuconfig
make O=/home/name/build/kernel
sudo make O=/home/name/build/kernel modules_install install
참고: 'O=output/dir' 옵션을 사용하는 경우, 모든 make 호출에 대해 동일하게 사용해야 합니다.
커널 구성:
사소한 버전만 업그레이드하더라도 이 단계를 건너뛰지 마십시오. 각 릴리스에서 새로운 구성 옵션이 추가되며, 구성 파일이 예상대로 설정되지 않으면 이상한 문제가 발생합니다. 최소한의 작업으로 기존 구성을 새 버전으로 가져오려면 "make oldconfig"를 사용하십시오. 그러면 새로운 질문에 대한 답변만 묻습니다.
대체 구성 명령은 다음과 같습니다.
"make config" 일반 텍스트 인터페이스.
"make menuconfig" 텍스트 기반 컬러 메뉴, 라디오리스트 및 대화상자.
"make nconfig" 향상된 텍스트 기반 컬러 메뉴.
"make xconfig" X 윈도우(Qt) 기반 구성 도구.
"make gconfig" X 윈도우(Gtk) 기반 구성 도구.
"make oldconfig" 기존 ./.config 파일의 내용을 기반으로 모든 질문에 기본값을 사용하고 새로운 구성 심볼에 대해 묻습니다.
"make silentoldconfig" 위와 유사하지만, 이미 답변된 질문으로 화면을 복잡하게 만들지 않습니다. 추가로 종속성을 업데이트합니다.
"make olddefconfig" 위와 유사하지만, 새로운 심볼을 묻지 않고 기본값으로 설정합니다.
"make defconfig" 아키텍처에 따라 arch/$ARCH/defconfig 또는 arch/$ARCH/configs/${PLATFORM}_defconfig의 기본 심볼 값을 사용하여 ./.config 파일을 만듭니다.
"make ${PLATFORM}_defconfig" arch/$ARCH/configs/${PLATFORM}_defconfig의 기본 심볼 값을 사용하여 ./.config 파일을 만듭니다. "make help"를 사용하여 아키텍처의 사용 가능한 모든 플랫폼 목록을 확인하십시오.
"make allyesconfig" 심볼 값을 최대한 'y'로 설정하여 ./.config 파일을 만듭니다.
"make allmodconfig" 심볼 값을 최대한 'm'으로 설정하여 ./.config 파일을 만듭니다.
"make allnoconfig" 심볼 값을 최대한 'n'으로 설정하여 ./.config 파일을 만듭니다.
"make randconfig" 심볼 값을 임의의 값으로 설정하여 ./.config 파일을 만듭니다.
"make localmodconfig" 현재 구성 및 로드된 모듈(lsmod)을 기반으로 구성을 만듭니다. 로드된 모듈에 필요하지 않은 모듈 옵션을 비활성화합니다.
다른 시스템의 localmodconfig를 만들려면,
해당 시스템의 lsmod를 파일에 저장하고
LSMOD 매개변수로 전달하십시오.
target$ lsmod > /tmp/mylsmod
target$ scp /tmp/mylsmod host:/tmp
host$ make LSMOD=/tmp/mylsmod localmodconfig
위는 크로스 컴파일할 때도 작동합니다.
"make localyesconfig" localmodconfig와 유사하지만, 모든 모듈 옵션을 내장(=y) 옵션으로 변환합니다.
Linux 커널 구성 도구 사용에 대한 자세한 내용은 Documentation/kbuild/kconfig.txt에서 찾을 수 있습니다.
"make config"에 대한 참고 사항:
불필요한 드라이버가 있으면 커널이 더 커지고, 어떤 상황에서는 문제가 발생할 수 있습니다. 존재하지 않는 컨트롤러 카드를 프로빙하면 다른 컨트롤러가 혼란스러워질 수 있습니다.
"Processor type"을 386보다 높게 설정하여 커널을 컴파일하면 386에서 작동하지 않는 커널이 생성됩니다. 커널은 부팅 시 이를 감지하고 포기합니다.
수학 에뮬레이션이 컴파일된 커널은 코프로세서가 있는 경우 계속 사용합니다. 수학 에뮬레이션은 그 경우 사용되지 않습니다. 커널은 약간 더 커지지만, 수학 코프로세서가 있든 없든 다른 시스템에서 작동합니다.
"kernel hacking" 구성 세부 사항은 일반적으로 더 크거나 느린 커널(또는 둘 다)을 초래하며, 일부 루틴을 구성하여 잘못된 코드를 적극적으로 깨뜨려 커널 문제(kmalloc())를 찾도록 하면 커널을 덜 안정적으로 만들 수도 있습니다. 따라서 "development", "experimental" 또는 "debugging" 기능에 대한 질문에는 'n'이라고 대답해야 합니다.
커널 컴파일:
최소 gcc 3.2가 있는지 확인하십시오. 자세한 내용은 Documentation/Changes를 참조하십시오.
이 커널에서 a.out 사용자 프로그램을 계속 실행할 수 있습니다.
"make"를 실행하여 압축된 커널 이미지를 만듭니다. lilo가 커널 makefile에 맞게 설치되어 있으면 "make install"도 가능하지만, 먼저 특정 lilo 설정을 확인하는 것이 좋습니다.
실제 설치를 수행하려면 root여야 하지만, 일반적인 빌드에는 root가 필요하지 않습니다. root의 이름을 함부로 사용하지 마십시오.
커널의 일부를 modules로 구성한 경우,
"make modules_install"도 수행해야 합니다.
자세한 커널 컴파일/빌드 출력:
일반적으로 커널 빌드 시스템은 상당히 조용한 모드로 실행됩니다(완전히 조용하지는 않음). 그러나 때로는 사용자나 다른 커널 개발자가 컴파일, 링크 또는 기타 명령이 정확히 어떻게 실행되는지 확인해야 할 수 있습니다. 이 경우 "verbose" 빌드 모드를 사용하십시오. 이는 "make" 명령에 "V=1"을 삽입하여 수행됩니다. 예:
make V=1 all
빌드 시스템이 각 대상의 재빌드 이유도 알려주도록 하려면 "V=2"를 사용하십시오. 기본값은 "V=0"입니다.
문제가 발생할 경우를 대비하여 백업 커널을 준비하십시오. 이는 특히 개발 릴리스의 경우 중요합니다. 각각의 새 릴리스에는 디버깅되지 않은 새 코드가 포함되어 있기 때문입니다. 해당 커널에 해당하는 모듈의 백업도 보관하십시오. 작동 중인 커널과 동일한 버전 번호의 새 커널을 설치하는 경우, "make modules_install"을 실행하기 전에 모듈 디렉토리를 백업하십시오.
또는 컴파일하기 전에 커널 구성 옵션 "LOCALVERSION"을 사용하여 일반 커널 버전에 고유한 접미사를 추가하십시오. LOCALVERSION은 "General Setup" 메뉴에서 설정할 수 있습니다.
새 커널을 부팅하려면 커널 이미지(예: 컴파일 후 .../linux/arch/i386/boot/bzImage)를 일반 부팅 가능한 커널이 있는 위치로 복사해야 합니다.
LILO와 같은 부트로더의 도움 없이 플로피에서 직접 커널을 부팅하는 것은 더 이상 지원되지 않습니다.
하드 드라이브에서 Linux를 부팅하는 경우, 아마도 LILO를 사용할 것입니다. LILO는 /etc/lilo.conf 파일에 지정된 커널 이미지를 사용합니다. 커널 이미지 파일은 일반적으로 /vmlinuz, /boot/vmlinuz, /bzImage 또는 /boot/bzImage입니다. 새 커널을 사용하려면 이전 이미지의 복사본을 저장하고 새 이미지를 이전 이미지 위에 복사하십시오. 그런 다음, 로딩 맵을 업데이트하기 위해 LILO를 다시 실행해야 합니다!! 그렇지 않으면 새 커널 이미지를 부팅할 수 없습니다.
LILO 재설치는 일반적으로 /sbin/lilo를 실행하는 것입니다. 새 커널이 작동하지 않을 경우를 대비하여 이전 커널 이미지(예: /vmlinux.old)에 대한 항목을 지정하기 위해 /etc/lilo.conf를 편집할 수 있습니다. 자세한 내용은 LILO 문서를 참조하십시오.
LILO를 다시 설치한 후에는 모든 것이 준비되어야 합니다. 시스템을 종료하고, 재부팅하고 즐기십시오!
커널 이미지에서 기본 루트 장치, 비디오 모드, 램디스크 크기 등을 변경해야 하는 경우 'rdev' 프로그램(또는 적절한 경우 LILO 부트 옵션)을 사용하십시오. 이러한 매개변수를 변경하기 위해 커널을 다시 컴파일할 필요가 없습니다.
새 커널로 재부팅하고 즐기십시오.
문제 발생 시:
커널 버그로 인한 문제가 있는 경우, MAINTAINERS 파일을 확인하여 문제가 있는 커널 부분과 관련된 특정 사람이 있는지 확인하십시오. 거기에 아무도 나열되어 있지 않으면, 두 번째로 좋은 방법은 저([email protected])에게 메일을 보내거나, 가능하면 다른 관련 메일링 리스트나 뉴스그룹에 보내는 것입니다.
모든 버그 보고서에서는 반드시 어떤 커널에 대해 이야기하고 있는지, 문제를 재현하는 방법, 그리고 설정이 무엇인지(상식적으로) 알려주십시오. 문제가 새로운 것이라면 그렇게 말해주고, 문제가 오래된 것이라면 언제 처음 발견했는지 알려주십시오.
버그로 인해 다음과 같은 메시지가 나타나는 경우
unable to handle kernel paging request at address C0000010 Oops: 0002 EIP: 0010:XXXXXXXX eax: xxxxxxxx ebx: xxxxxxxx ecx: xxxxxxxx edx: xxxxxxxx esi: xxxxxxxx edi: xxxxxxxx ebp: xxxxxxxx ds: xxxx es: xxxx fs: xxxx gs: xxxx Pid: xx, process nr: xx xx xx xx xx xx xx xx xx xx xx
또는 화면이나 시스템 로그에 유사한 커널 디버깅 정보가 표시되면, 정확히 복제해 주십시오. 덤프는 이해하기 어려워 보일 수 있지만, 문제 디버깅에 도움이 될 수 있는 정보를 포함하고 있습니다. 덤프 위의 텍스트도 중요합니다. 커널이 코드를 덤프한 이유에 대해 알려줍니다 (위의 예에서는 잘못된 커널 포인터 때문입니다). 덤프를 이해하는 방법에 대한 자세한 정보는 Documentation/oops-tracing.txt에 있습니다.
CONFIG_KALLSYMS로 커널을 컴파일한 경우 덤프를 그대로 보낼 수 있습니다. 그렇지 않으면 "ksymoops" 프로그램을 사용하여 덤프를 이해해야 합니다 (하지만 CONFIG_KALLSYMS로 컴파일하는 것이 일반적으로 선호됩니다). 이 유틸리티는 다음에서 다운로드할 수 있습니다. ftp://ftp..kernel.org/pub/linux/utils/kernel/ksymoops/ . 또는 수동으로 덤프를 조회할 수 있습니다.
위와 같은 디버깅 덤프에서 EIP 값이 무엇을 의미하는지 조회할 수 있으면 크게 도움이 됩니다. 16진수 값 자체는 저나 다른 사람에게 별로 도움이 되지 않습니다. 특정 커널 설정에 따라 달라지기 때문입니다. EIP 라인에서 16진수 값을 가져와서 ( "0010:"은 무시) 커널 namelist에서 조회하여 문제의 주소를 포함하는 커널 함수를 찾아야 합니다.
커널 함수 이름을 찾으려면 증상을 보인 커널과 관련된 시스템 바이너리를 찾아야 합니다. 이것은 'linux/vmlinux' 파일입니다. namelist를 추출하고 커널 충돌의 EIP와 일치시키려면 다음을 수행하십시오.
nm vmlinux | sort | less
그러면 오름차순으로 정렬된 커널 주소 목록이 표시되며, 여기에서 문제의 주소를 포함하는 함수를 쉽게 찾을 수 있습니다. 커널 디버깅 메시지에 제공된 주소가 함수 주소와 정확히 일치하지는 않을 수 있습니다 (사실 그럴 가능성은 거의 없습니다). 따라서 목록을 단순히 'grep'할 수는 없습니다. 그러나 목록은 각 커널 함수의 시작점을 제공하므로, 찾고 있는 주소보다 낮은 시작 주소를 가지고 있지만 더 높은 주소를 가진 함수가 뒤따르는 함수를 찾으면 원하는 함수를 찾을 수 있습니다. 사실, 문제 보고서에 약간의 "컨텍스트"를 포함하여 관심 있는 줄 주변의 몇 줄을 제공하는 것이 좋습니다.
어떤 이유로 위의 작업을 수행할 수 없는 경우(사전 컴파일된 커널 이미지 등), 가능한 한 많은 설정 정보를 알려주시면 도움이 됩니다. 자세한 내용은 REPORTING-BUGS 문서를 읽어 주십시오.
또는 실행 중인 커널에서 gdb를 사용할 수 있습니다(읽기 전용, 즉 값을 변경하거나 중단점을 설정할 수 없습니다). 이렇게 하려면 먼저 커널을 -g로 컴파일하십시오. arch/i386/Makefile을 적절히 편집한 다음 "make clean"을 수행하십시오. 또한 CONFIG_PROC_FS("make config"를 통해)를 활성화해야 합니다.
새 커널로 재부팅한 후 "gdb vmlinux /proc/kcore"를 실행하십시오. 이제 모든 일반적인 gdb 명령을 사용할 수 있습니다. 시스템이 충돌한 지점을 조회하는 명령은 "l *0xXXXXXXXX"입니다. (XXX를 EIP 값으로 바꾸십시오.)
실행되지 않는 커널에서 gdb를 사용하는 것은 현재 실패합니다. gdb가 (잘못) 커널이 컴파일된 시작 오프셋을 무시하기 때문입니다.