2013년 11월 26일 화요일

리눅스 커널 do_mremap 내부 함수의 또 다른 취약점

자료출처: 해커스쿨

작년 12월의 do_brk() 취약점, 그리고 올해 1월의 do_mremap() 취약점에 이은 또 다른 리눅스 커널의 취약점입니다.
이번 취약점 역시 do_mremap() 함수에서 발견되었으며, 취약한 커널의 버젼은 2.6대의 커널의 경우 2.6.2 이하, 2.4대의 커널의 경우 2.4.24 이하가 모두 해당됩니다.

* do_brk() 취약점은 물론 1월의 do_mremap() 취약점을 패치하신 분들도 또 다시 패치 작업을 하셔야 합니다. 또 다른 do_mremap() 취약점이기 때문입니다.

* 이번 패치를 진행하시면 지난 do_mremap, do_brk 취약점은 물론 지금까지 발견된 모든 커널 취약점까지 패치됩니다.

이 취약점에 대한 자세한 내용은 다음과 같습니다.
다음 링크들 중에서 각자 필요한 부분을 클릭하여 참조하시기 바랍니다.

[공격의 대상]
이 취약점은 2.4.24과 2.6.2 이하의 리눅스 커널을 사용하는 모든 운영체제에
해당합니다. 서버 관리자 분들은 다음과 같은 방법으로 현 시스템의
커널 버젼을 확인할 수 있습니다.

[root@work root]# uname -r
2.4.23
[root@work root]#
--> 2.4 시리즈의 커널을 사용할 경우

[root@work root]# uname -r
2.6.0
[root@work root]#
--> 2.6 시리즈의 커널을 사용할 경우

만약 위 숫자가 2.4.25 혹은 2.6.4 보다 낮을 경우엔 이 취약점에 의하여 공격당할 수 있으므로 필히 패치 작업을 진행하셔야 합니다.

참고1) 이 취약점은 로컬 공격에 해당합니다. 즉, 타겟의 쉘 접속 권한을 가지고 있는 공격자만이 이 취약점을 악용할 수 있습니다. (일반계정->루트)
      
참고2) 레드햇, 와우, 수세 등등 배포본의 종류와 관계없이 리눅스 기반의 커널을 사용하고 있는 모든 운영체제에 해당하는 취약점 입니다.


[취약점 피해]
이 취약점을 이용하면, 계정을 가지고 있는 일반 사용자가 최고 관리자 권한(root)를 획득할 수 있습니다.

ISEC 그룹에선 취약성 존재 여부를 판별해주는 테스트 코드를 발표하였으며, 이 테스트 코드가 수정된 변종 공격 코드가 존재할 수 있으니 필히 패치 작업을 진행하셔야 합니다.

====================================================
Trying 192.168.0.2 ...
Connected to 192.168.0.2.
Red Hat Linux release 9 (Shrike)
Kernel 2.4.20-8 on an i686
login: user
Password:
Last login: Tue Mar 16 10:19:09 from 192.168.0.1
[user@localhost user]$
[user@localhost user]$ ./vuln_test
[+] kernel 2.4.20-8  vulnerable: YES  exploitable YES
    MMAP #65530  0x50bfa000 - 0x50bfb000
[+] Success

Usage: ping [-LRUbdfnqrvVaA] [-c count] [-i interval] [-w deadline]
            [-p pattern] [-s packetsize] [-t ttl] [-I interface or address]
            [-M mtu discovery hint] [-S sndbuf]
            [ -T timestamp option ] [ -Q tos ] [hop1 ...] destination 

[user@localhost user]$
====================================================

위 모습처럼 vulnerable과 exploitable 부분이 YES로 표시되면 공격을 당할 수 있습니다. (테스트 코드는 악용의 소지가 있으므로 첨부하지 않습니다.)


[취약점 분석]
다음은 지난 3월 1일 iSEC에서 발표한 기술 문서를 번역한 것입니다.

:: Linux kernel do_mremap VMA 로컬 권한 상승 취약점 ::

.버전: Linux kernel 2.2 - 2.2.25, 2.4 - 2.4.24, 2.6 - 2.6.2
.URL : http://isec.pl/vulnerabilities/isec-0014-mremap-unmap.txt
.CVE : CAN-2004-0077
.저자: Paul Starzetz
.날짜: March 1, 2004
.번역: y2family@wiseguys(hackerschool research team)



문제점:
========
mremap(2) 시스템 콜 내부의 리눅스 커널 메모리 관리 코드가 함수 리턴값을 체크 하지 않아서 생기는 중대한 보안상 취약점이 최근 발견 되었다. 이 버그는 05-01-2004에 발표된 mremap 버그와 같은 커널 내부의 함수 코드에 관련되어져 있다는 점 이외에는 완전히 별개의 것이다.


세부사항:
==========
리눅스 커널은 사용자가 접근 가능한 유효 메모리 지역들의 리스트를 프로세스별로 관리한다.
각각의 프로세스들은 소위 '가상 메모리 영역 기술자'들(VMAs)라고 불리는 단일 링크드 리스트를 가지고 있다. 각각의 VMA는 페이지 보호와 같이 유효 메모리 지역의 출발점, 그것의 길이 뿐만 아니라 다양한 메모리 플래그들을 기술한다.

그 리스트 안에 있는 모든 VMA는 프로세스의 페이지 테이블의 한 부분과 각각 대응하며, 그 페이지 테이블은 프로세스에 의해 보여지는 물리적 메모리 페이지의 기술자들(Page Table Entries-PTEs)을 포함한다. 그러므로 VMA 기술자는 '페이지 R/W 플레그 등과 같이 PTE 내용을 저장하는 특정한 영역의 프로세스 페이지 테이블' 이라고 할 수 있다.

mremap() 시스템 콜은 현존하는 가상 메모리 영역 또는 그것(VMA)의 어떠한 부분을 프로세스의 접근 가능한 메모리 공간으로 이동시킬 수 있을 뿐만아니라, 사이즈 또한 변화 시킬 수 있다.
(감소 또는 증가)

VMA 내부의 가상 메모리 일부를 새로운 장소로 이동시키는 것은 원래의 페이지 테이블 목록을 복사하는 것 뿐만 아니라 새로운 VMA 기술자를 생성하는 것을 필요로 한다.

이 일을 수행하기 위해 do_mremap 코드는 do_munmap()라는 커널 내부 함수를 불러 오는데, 이
함수는 기존의 가상 메모리 매핑을 제거하고 새로운 장소안에 존재하고 있지도 모를 기존의 메모리 매핑을 제거 하기위해 쓰인다. 불행하게도 그 코드는 사용 가능한 최대 갯수의 VMA 기술자 수가 초과 되어 실패할지도 모를 do_munmap() 함수의 리턴 값을 체크하지 않는다. 이것은 현존하는 메모리 매핑의 중간 부분 매핑을 해제시키고 VMA 기술자들이 프로세스의 한계 수치(현재 65535)에 도달했을때 발생한다.

그중에서 한가지 가능한 상황을 다음 그림과 같이 나타낼 수 있다.
대응하는 페이지 테이블 엔트리들(PTEs)을 o와 x로 표시하였다.

mremap() 콜 이전:

(oooooooooooooooooooooooo)     (xxxxxxxxxxxx)
[----------VMA1----------]     [----VMA2----]
      [REMAPPED-VMA] <---------------|


VMA 한계에 도달하지 않은 mremap() 콜 이후:

(oooo)(xxxxxxxxxxxx)(oooo)
[VMA3][REMAPPED-VMA][VMA4]


VMA 한계에 도달 한 mremap() 콜 이후:

(ooooxxxxxxxxxxxxxxoooo)
[---------VMA1---------]
     [REMAPPED-VMA]


프로세스의 VMA 목록에서 VMAs가 최대 갯수에 도달한 이후부터, do_munmap()는 필요한 VMA 홀을 생성하는것을 거부한다. 그것은 VMA 기술자 한계를 초과하여 원래의 VMA를 2개의 VMA 영역으로 쪼개어 버릴 것이기 때문이다.

VMA1(이것이 바로 do_mremap 코드 내부에서 do_munmap의 첫번째 기원이다)의 중간 부분의 매핑
해제를 시도한 이후 리턴값을 체크하지 않음으로 인해서 VMA2의 대응하는 페이지 테이블 목록은 여전히 VMA1로 기술되는 페이지 테이블 영역 속으로 삽입되어 지고, 따라서 VMA1 페이지 보호플래그의 영향아래 놓인다. 또한 VMA1 내부의 원래 PTEs가 상실되므로 대응하는 페이지 프레임들은 영원히 사용할 수 없는 상태로 남겨진다.

커널은 또한 겹쳐진 VMA 영역을 VMA 기술자 리스트에 삽입하려고 하지만 이것은 나아가 저수준의 VMA 조작 코드가 체크 함으로 실패하게 된다. 커널 버전 2.4와 2.6 에서 저수준의 VMA 목록 체크는 단지 BUG()를 호출함으로써 악의적인 프로세스를 종료시킨다.

do_mremap() 코드 내부의 do_munmap()에는 2가지의 또다른 체크되지 않은 호출이 있는데, 두번째 발생하는 체크되지 않은 do_munmap 역시 공격가능하다고 믿는다. 두번째 경우는 재 맵핑될 VMA가 잘려나갈 경우에 발생한다. do_munmap는 메모리가 아주 부족한 상황에서 VMA 기술자를 할당하려고 시도 할때도 실패할 수 있다는 것을 주목 하자.


취약점 공략:
============

취약점을 이용하는 것은 아주 쉬웠다. 우리들의 첫번제 추측은 읽기전용 파일(/etc/passwd 등)의 한 VMA 매핑을 다른 쓰기 가능한 VMA로 PTEs를 이동시키는 것이었다. 그러나 이 시도는 실패하였다. BUG()가 호출된 이후 메모리 기술자의 mmap 세마포어가 잠긴 상태(down_write())로 되었기 때문 이었다. 따라서 다른 클론 쓰레드에서 세마포어를 획득하는 더 이상의 메모리 작업이 방지되었다.

따라서 우리의 관심은 초기의 2.4 버전에서 소개되었지만 기본적으로 설정되지는 않았던 페이지 테이블 케쉬 코드로 옮겨갔다. 2.4.19 이후의 커널에서는 기본적으로 페이지 테이블 캐쉬가 사용된다.
페이지 테이블 캐쉬의 기본 개념은 최근에 사용된 페이지 테이블들을 링크드 리스트에 보관하여 새로운 페이지 테이블 할당을 빠르게 하는 것이다.

리눅스 시스템의 모든 프로세스들은 페이지 디렉토리에 관한 포인터를 담고 있는 메모리 기술자(mm_struct)와 관련이 있다.  이 페이지 디렉토리는 페이지 테이블에 대하여 1024개의 포인터들을 포함하는 싱글 페이지 프레임(우리는 PAE가 없는 4kb 크기의 페이지에 대해서 기술한다)이다.
i386기반에서 하나의 페이지 테이블은 프로세스 가상메모리의 4MB 까지 커버하는 1024개의 PTEs를 가지고 있다. 하나의 PTE는 PTE의 가상 주소에 매핑된 물리적 주소와 페이지 접근 권리를 포함한다.


페이지 테이블들은 페이지 폴트가 발생하는 경우에 할당되어진다. 그리고 만약 프로세스가 최소한 4MB 크기와 4MB의 정렬된 메모리 영역 부분을 포함하는 적어도 한 페이지 테이블 범위의 가상 메모리 매핑이 해제되는 경우 페이지 테이블은 자유롭게 되며 대응하는 페이지 프레임들은 메모리 관리자에게로 넘어간다.

새로운 페이지 테이블이 할당 되어야져 한다면 다음과 같은 두가지의 길이 있다:느린것과 빠른것.
빠른 방법은 페이지 테이블 캐쉬의 첫 부분으로부터 한 페이지를 차지하는 반면에 느린 방법은 단지 get_free_page()만 호출한다. 이것은 페이지 테이블 캐쉬의 페이지들이 캐쉬에 삽입되기 전에 적절하게 제거된 경우에 잘 작동한다. 일반적으로 페이지 테이블들은 do_munmap로 부터 호출되는 zap_page_range()에 의해 제거된다. 실제의 유효한 PTE를 포함하는 프로세스의 페이지 테이블의 모든 장소가 대응하는 VMA 기술자에 의해서 커버 되는데, 이것은 리눅스 메모리 관리를 적절히 작동시키는데 아주 중요하다.

mremap 코드 안에서 체크 되지 않은 do_munmap의 경우에서, 우리는 VMA에 의해 커버되지 않은체
페이지 테이블의 한 부분이 남겨지는 경우를 찾았다. 그 코드는 다음과 같다.


[269]        if (old_len >= new_len) {
                do_munmap(current->mm, addr+new_len, old_len - new_len);
                if (!(flags & MREMAP_FIXED) || (new_addr == addr))
                        goto out;
        }

이 부분의 코드는 사용자가 매핑을 해제하기를 원하는 위치의 VMA를 자르는 역할을 한다.
do_munmap는 [addr+new_len, addr+new_len + (old_len-new_len)] 부분이 VMA의 중간 부분으로 가고 허용된 최대 번호의 VMA 기술자가 이미 프로세스에 의해 사용되어 지고 있다면 실패할 것이란 것을 쉽게 볼 수 있다. 그것은 또한 페이지 테이블은 addr+new_len 으로부터 여전히 유효한 PTEs를 포함하게 된다는 것을 의미한다. 이후 mremap 코드에서, VMA의 대응하는 한 부분은 이동되고 잘려진다.


[179]        if (!move_page_tables(current->mm, new_addr, addr, old_len)) {
                unsigned long vm_locked = vma->vm_flags & VM_LOCKED;

                if (allocated_vma) {
                        *new_vma = *vma;
                        new_vma->vm_start = new_addr;
                        new_vma->vm_end = new_addr+new_len;
                        new_vma->vm_pgoff += (addr-vma->vm_start) >> PAGE_SHIFT;


그러나 새로운 장소가 MREMAP_MAYMOVE 플래그의 상태인 경우 생성된 VMA의 길이보다 더 많은 PTEs(즉 old_len)가 이전의 장소로 부터 이동된다. 이것은 이전의 do_munmap가 실패하지 않은 경우
에만 효과가 있다. 이 경우는 다음과 같이 나타내어질 수 있다.


mremap 이전:

       <--  old_len -->
(oooooooooooooooooooooooooooo)
[------|-----VMA1-----|------]
            |---------------------------------> new_addr


VMA 한계 아닐경우, mremap 이후:
                                                new_len
(oooooo)              (oooooo)                        (oooooo)
[-VMA1-]              [-VMA3-]                        [-VMA2-]


VMA 한계일 경우, mremap 이후:
                                                new_len   [*]
(oooooo                oooooo)                        (oooooo)ooooooooo
[-----------VMA1-------------]                        [-VMA2-]


페이지 테이블 안에 이런 [*] '임자없는' PTE들은 메모리 관리자가 통제력을 상실했기 때문에 더 나아가 공격이 가능하다. 이제 만약 프로세스가 저 주인없는 PTEs들을 커버하는 충분히 큰 지역을 매핑해제 하는 경우, 밑에있는 페이지 테이블 프레임이 페이지 테이블 캐쉬로 삽입 될 것이다. 하지만 아직 유효한 PTEs를 포함한다. 그것은 프로세스 P에서 주소 A로의 다음 페이지 테이블 프레임 할당시에 우리의 PTEs는 프로세스 P의 페이지 테이블 안에 나타난다는 것을 의미한다! 그 프로세스가 주소 A 의 가상 메모리에 접근하려고 시도 하는 경우 PTEs가 적절한 권한(읽기 또는 쓰기)을 가지고 있다면 페이지 폴트 또한 일어나지 않을 것이다. 즉, 페이지 테이블 케쉬를 통하여 우리는 어떠한 데이터라도 다른 프로세스의 가상 메모리 공간에 삽입할 수 있다는 것이다.

우리의 코드는 setuid 바이너리를 통하는 방법을 사용하지만 이것이 가능한 모든 방법은 아니다.
캐쉬 바로 앞에 하나의 빈 페이지 프레임이 존재 하도록하기 위해서 페이지 테이블 캐쉬를 그리고 스스로 실행하는(self executing) 페이지들을 포함하는 특별한 페이지 테이블을 준비했다.
그것이 어떻게 작동하는지 완전히 이해하기 위해서는 execve() 시스템 콜을 파헤쳐 봐야만 한다.

만약 사용자가 execve()을 호출하면, 커널은 프로세스에 대해 가상 메모리 지역과 프로세스의 페이지 테이블 할당을 포함한 현재 실행 가능한 모든 추적을 제거한다. 그런 후 가상 메모리의 꼭대기에 새로운 바이너리의 프로그램 환경변수와 인자들이 저장되는 스택을 위한 새로운 VMA가 생성된다.(그것들은 커널 메모리에 보존된다.) 이것은 첫번째 페이지 테이블 프레임이 가상 메모리의 0xbfc00000에서 0xc0000000까지의 지역에 할당되게 된다.

다음은, 더 이상의 로딩을 담당하는 프로그램 인터프리터 뿐만아니라 실행 될 바이너리의 .text와 .data 부분이 새로운 가상 메모리 공간으로 매핑된다. ELF 링킹 포멧 때문에 이것은 보통 ld.so 다이나믹 링커이다. 이 부분에서 커널은 아래의 페이지 테이블을 할당하지 않는다. 오직 VMA 기술자들이 프로세스의 VMA 목록으로 삽입될 뿐이다.

중요치 않은 몇몇의 작업 이후 커널은 바이너리를 실행하기 위해서 제어권을 다이나믹 링커에게 로 넘긴다. 이것은 두번째 페이지 폴트를 일으키며 다이나믹 링커 첫번째 코드 페이지의 로딩을 유발한다. 표준의 리눅스 커널에서 이것은 0x40000000에서 0x40400000까지 범위의 페이지 테이블을 위한 페이지 프레임을 할당 할 것이다.

페이지 테이블 캐쉬가 사용되는 커널에서 두가지 할당 모두 첫번째 캐쉬로 부터 페이지 프레임을 가질 것이다. 이것은 만약 캐쉬 페이지 리스트 안의 두번째 페이지가 유효한 PTEs를 포함하면 그것들이 정상적인 다이나믹 링커 코드대신 나타나게 된다는 것을 의미한다. PTEs를 위치 시켜서 그것들이 다이나믹 링커의 코드 영역을 덮어버리게 하는것은 쉽다. 페이지 테이블의 첫번째 PTE는 페이지 리스트를 유지하기 위해 캐쉬 코드에 의해 사용된다는 것을 주의해야 한다. 우리의 코드에서는 페이지 테이블 캐쉬를, 마지막에 짧은 쉘코드가 있고 NOP로 채워진 페이지의 PTEs를 포함하는 특별한 프레임으로 위치하게 하였다.

또한 2004년 1월 5일 발견되어진 첫번째 mremap 홀 또한 페이지 테이블 캐쉬를 통해서 아주 쉽게 공격이 가능하다. 세부 사항은 숙련된 독자들을 위해 남겨둔다.

mremap 버그 공격을 위한 두번째 가능성은 /etc/passwd와 같은 읽기 전용 파일로 부터 주인없는 PTEs를 커버하는 또다른 VMA를 생성하는 것이다.


영향:
=====

mremap(2) 시스템 콜을 이용하는데 특별한 권한이 필요없기 때문에 어떠한 프로세스라도 커널 메모리 관리 하부조직을 붕괴시키기 위해 그 예기치 않은 행동을 사용 하는것이 가능하다.

이 취약점의 적절한 이용은 공격자에게 루트 권한을 주는 로컬 권한 상승을 유도한다. 또한 그 취약점은 사용가능한 시스템 메모리에 서비스 거부 공격(DOS)을 이르킬 수 있다.

테스트 되고 취약한 것으로 알려진 커널 버전은 2.2.25이하, 2.4.24 이하 그리고 2.6.2 이하 모든 버전이다. 리눅스 커널 2.2.25 버전은 MREMAP_FIXED 플래그를 인식하지 않는다. 하지만 이것이 성공적으로 공격 당하는 것을 막지는 못한다. 모든 사용자는 적절한 패치가 배포되는 즉시 패치할 것이 권장된다. 제한된 사용자당 가상 메모리 또한 do_munmap()를 실패하게 한다.


저자의 말:
==========

Paul Starzetz 가 이 취약점을 밝혀냈으며 연구를 하였음.
이곳에 제공된 복사, 배포 그리고 정보의 수정은 저자의 동의하에 허가됨.


역자의 말:
==========
이 글의 저작권은 없습니다.  역자에게는 오역이나 악용 으로 인한 책임은 없으며, 오역 된 부분이 있다면 메일로 연락주시고 검토후 수정하도록 하겠습니다.


[취약점 패치]
다음 절차에 따라 커널 업그레이드를 진행하시기 바랍니다.

시작하기 전에..

참고1) 만약 예상치 못한 이유로 커널 업그레이드에 실패할 경우에도 기존의 커널을 그대로 사용할 수 있습니다.

참고2) 커널 업그레이드 작업은 네트워크가 아닌, 직접 콘솔 상에서 하시기 바랍니다. 부팅 시 원하는 커널 이미지를 선택하고, 만약 새로운 커널이 시스템의 요구에 맞지 않아 정상적으로 부팅되지 않을 경우 복구하기 위해서 입니다.

먼저, 최신 버젼의 리눅스 커널을 www.kernel.org에서 다운로드 받습니다.
위 사이트에 접속한 후, The latest stable version of the Linux kernel is: 2.4.25 부분의 오른쪽에 있는 F(full)라는 링크를 클릭하시면 됩니다.
(최근에 주로 사용되는 커널은 2.6 시리즈와 2.4 시리즈가 있는데 이 문서는 2.4 시리즈를 기준으로 설명합니다.)

[직접 다운]
http://www.kernel.org/pub/linux/kernel/v2.4/patch-2.4.25.bz2

받으신 후에는 리눅스 서버로 파일을 업로드하신 후, /usr/src/ 디렉토리에서
압축을 해제시킵니다.

=======================================================================
[root@work src]# bzip2 -d linux-2.4.25.tar.bz2  <- bz2를 tar로..
[root@work src]# tar xvf linux-2.4.25.tar <- tar 압축 해제
[root@work src]# tar xvf linux-2.4.25.tar
linux-2.4.25/
linux-2.4.25/Makefile
linux-2.4.25/MAINTAINERS
linux-2.4.25/CREDITS
linux-2.4.25/crypto/
... 생략 ...
[root@work src]#
=======================================================================

이제 linux-2.4.25 디렉토리로 이동한 후, 커널의 옵션을 설정하는 make menuconfig 명령을 입력합니다.

=======================================================================
[root@work src]# cd linux-2.4.25
[root@work src]# make menuconfig
=======================================================================

그럼 메뉴 환경으로 구성된 옵션 설정 화면이 나타나며, 많은 옵션들 중 다음과 같은 것들을 설정해 줍니다.

1. network device support 메뉴에서 엔터를 입력한 후, socket filtering 부분에 스페이스 키로 *표 체크합니다.
   (*은 커널에 포함하여 컴파일, M은 모듈 형태로 빼내어 컴파일합니다.)

2. network device support -> ethernet(10 or 100M)에서 자신의 랜카드 부분에 *표 체크를 합니다.

3. 다시 처음으로 가서, File systems -> EXT3에 *표 체크를 합니다.


이제 exit를 눌러서 종료하고, save할 것이냐고 물어보면 yes를 선택합니다.
다음엔 다음과 같은 명령을 차례로 입력하여 커널 컴파일을 시작합니다.

=======================================================================
[root@work linux-2.4.25]# make dep  <- 의존성 체크
... 생략 ...
[root@work linux-2.4.25]# make clean  <- 관련 파일 초기화
... 생략 ...
[root@work linux-2.4.25]# make bzImage  <- 커널 컴파일
... 생략, 오랜 시간 소요 ...
[root@work linux-2.4.25]# make modules  <- 모듈 컴파일
... 생략 ...
[root@work linux-2.4.25]# make modules_install  <- 모듈 설치
... 생략 ...
[root@work linux-2.4.25]#
=======================================================================

모두 완료하였다면, 컴파일 완료된 커널 파일을 /boot/
디렉토리로 옮깁니다.

============================================================================
[root@work linux-2.4.25]# cp arch/i386/boot/bzImage /boot/new_kernel
[root@work linux-2.4.25]#
============================================================================

이 때, /boot/로 복사하는 파일명은 마음대로하되, bzImage라는 이름으로 지정할 경우엔 기존의 커널을 덮어씌워 버림으로 주의하도록 합니다.

이제 마지막으로, 부트 로더에 새로운 커널 정보를 등록합니다.

[부트 로더가 lilo일 경우]

먼저, vi /etc/lilo.conf를 입력합니다.
그 다음엔 다음과 같이 새로운 커널의 정보를 추가합니다.

==================================================================
image=/boot/new_kernel (위에서 지정한 파일 이름)
      label=new
      root=/dev/hda2 (최상위 디렉토리가 설치된 파티션이 hda2가 아닐 경우 알맞게 수정)
==================================================================

vi를 종료하고, 변경된 lilo 설정을 적용시키기 위하여 /sbin/lilo 명령을 한번 실행해 줍니다.

[부트 로더가 grub일 경우]

먼저, vi /boot/grub/grub.conf를 입력합니다.
그 다음엔 다음과 같이 새로운 커널의 정보를 추가합니다.

==================================================================
title Red Hat Linux
root (hd0,0)
kernel /boot/new_kernel ro root=/dev/hda2 vga=788
initrd /initrd-2.4.x.img
==================================================================

* 위에서 파일명과 파티션 정보는 알맞게 수정해 주십시오.

이제 리부팅을 한 후, 부트로드에서 커널을 선택하는 화면이 나타나면 새로 컴파일 한 new라는 이름의 커널을 선택해 줍니다.
이제 부팅이 완료된 후, uname -r 명령으로 변경된 커널의 버젼을 확인하고 TCP/IP 네트워크 등의 기능이 정상적으로 작동하는지 확인합니다.
모든 것이 정상적으로 작동하는 것이 확인된 후에는 다시 /etc/lilo.conf 파일을 열어 상단의 default 부분의 값을 새로운 커널의 이름인 new로 바꾸어 줍니다. 이렇게 하면, 부팅 시 자동으로 new라는 이름의 커널이 선택됩니다. 수정 후에는 다시 한번 /sbin/lilo를 실행합니다.

만약, 커널 컴파일 후에 부팅이 되지 않는다거나, 네트워크가 작동하지 않는다거나, 혹은 특정 하드웨어를 인식하지 못한다면, 각 오류에 대한 수많은 원인이 있을 수 있음으로 kldp.org 등의 리눅스 전문 사이트에서 해결책에 대한 정보를 검색하시기 바랍니다.

댓글 없음:

댓글 쓰기