2013년 11월 26일 화요일

2.4.23 & 2.6.0 이하 리눅스 커널의 do_mremap() 취약점

자료출처: 해커스쿨

지난 12월에 리눅스 커널의 do_brk() 취약점이 발표된 이후 1달도 채 지나지 않아 또 다른 심각한 취약점이 do_mremap() 함수에서 발표되었습니다.
이번 취약점의 발견자는 지난 do_brk() 취약점에서와 동일한 폴란드의 ISEC 그룹이며, 이미 이 취약점에 대한 공격 테스트를 마치고 Exploit까지 발표한 상태입니다. 리눅스 커널 개발자들은 패치된 버젼의 2.6.1과 2.4.24를 배포하기 시작했으며, 이번 사건으로 인하여 서버 관리자들은 또 한번의 커널 업그레이드 수고를 하시게 되었습니다.

* do_brk() 취약점 때문에 2.4.23으로 커널을 업그레이드 하시거나 공격 방어 모듈을 설치하신 분들도 또 다시 do_mremap() 패치 작업을 진행하셔야 합니다.

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

이 취약점에 대한 자세한 내용은 다음과 같습니다.


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

[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.24 혹은 2.6.1 보다 낮을 경우엔 이 취약점에 의하여 공격당할 수 있으므로 필히 패치 작업을 진행하셔야 합니다.

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

[취약점 확인]
현 게시물에 첨부된 유틸리티를 이용하여 운영하고 계신 서버의 do_mremap() 취약점 존재 여부를 판단하실 수 있습니다.
취약점이 존재할 경우 커널 업그레이드 과정을 거쳐 패치를 진행하시고, 패치 후에도 이 유틸리티를 이용하여 패치 성공 여부를 확인해 보시기 바랍니다.

[취약점 확인 절차]

1. 다음 소스를 복사하시거나 FTP 등으로 해당 서버에 업로드 하신 후 컴파일을 합니다.

/*
* mremap_bug.c
* Creation date: 07.01.2004
* Copyright(c) 2004 Angelo Dell'Aera <buffer@antifork.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA  02111-1307  USA
*/

/*
* Proof of concept code for testing do_mremap() Linux kernel bug.
* It is based on the code by Christophe Devine and Julien Tinnes
* posted on Bugtraq mailing list on 5 Jan 2004 but it's safer since
* it avoids any kernel data corruption.
*
* The following test was done against the Linux kernel 2.6.0. Similar
* results were obtained against the kernel 2.4.23 and previous ones.
*
* buffer@mintaka:~$ gcc -o mremap_bug mremap_bug.c
* buffer@mintaka:~$ ./mremap_bug
*
* Base address : 0x60000000
*
* 08048000-08049000 r-xp 00000000 03:03 2694       /home/buffer/mremap_bug
* 08049000-0804a000 rw-p 00000000 03:03 2694       /home/buffer/mremap_bug
* 40000000-40015000 r-xp 00000000 03:01 52619      /lib/ld-2.3.2.so
* 40015000-40016000 rw-p 00014000 03:01 52619      /lib/ld-2.3.2.so
* 40016000-40017000 rw-p 00000000 00:00 0
* 40022000-40151000 r-xp 00000000 03:01 52588      /lib/libc-2.3.2.so
* 40151000-40156000 rw-p 0012f000 03:01 52588      /lib/libc-2.3.2.so
* 40156000-40159000 rw-p 00000000 00:00 0
* 60000000-60002000 rw-p 00000000 00:00 0
* bfffd000-c0000000 rwxp ffffe000 00:00 0
*
* Remapping at 0x70000000...
*
* 08048000-08049000 r-xp 00000000 03:03 2694       /home/buffer/mremap_bug
* 08049000-0804a000 rw-p 00000000 03:03 2694       /home/buffer/mremap_bug
* 40000000-40015000 r-xp 00000000 03:01 52619      /lib/ld-2.3.2.so
* 40015000-40016000 rw-p 00014000 03:01 52619      /lib/ld-2.3.2.so
* 40016000-40017000 rw-p 00000000 00:00 0
* 40022000-40151000 r-xp 00000000 03:01 52588      /lib/libc-2.3.2.so
* 40151000-40156000 rw-p 0012f000 03:01 52588      /lib/libc-2.3.2.so
* 40156000-40159000 rw-p 00000000 00:00 0
* 60000000-60002000 rw-p 00000000 00:00 0
* 70000000-70000000 rw-p 00000000 00:00 0
* bfffd000-c0000000 rwxp ffffe000 00:00 0
*
* Report :
* This kernel appears to be VULNERABLE
*
* Segmentation fault
* buffer@mintaka:~$
*/

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <asm/unistd.h>
#include <errno.h>
 
#define MREMAP_FIXED    2

#define PAGESIZE 4096
#define VMASIZE  (2*PAGESIZE)
#define BUFSIZE  8192

#define __NR_real_mremap __NR_mremap

static inline _syscall5( void *, real_mremap, void *, old_address,
                         size_t, old_size, size_t, new_size,
                         unsigned long, flags, void *, new_address );

#define MAPS_NO_CHECK 0
#define MAPS_CHECK    1

int mremap_check = 0;

void maps_check(char *buf)
{
        if (strstr(buf, "70000000"))
            mremap_check++;
}

void read_maps(int fd, char *path, unsigned long flag)
{
        ssize_t  nbytes;
        char     buf[BUFSIZE];

        if (lseek(fd, 0, SEEK_SET) < 0) {
                fprintf(stderr, "Unable to lseek %s\n", path);
                return;
        }

        while ( (nbytes = read(fd, buf, BUFSIZE)) > 0) {

                if (flag & MAPS_CHECK)
                        maps_check(buf);

                if (write(STDOUT_FILENO, buf, nbytes) != nbytes) {
                        fprintf(stderr, "Unable to read %s\n", path);
                        exit (1);
                }
        }
}

int main(int argc, char **argv)
{
        void     *base;
        char     path[18];
        pid_t    pid;
        int      fd;
       
        pid = getpid();
        sprintf(path, "/proc/%d/maps", pid);

        if ( !(fd = open(path, O_RDONLY))) {
                fprintf(stderr, "Unable to open %s\n", path);
                return 1;
        }

        base = mmap((void *)0x60000000, VMASIZE, PROT_READ | PROT_WRITE,
                    MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);

        printf("\nBase address : 0x%x\n\n", base);
        read_maps(fd, path, MAPS_NO_CHECK);

        printf("\nRemapping at 0x70000000...\n\n");
        base = real_mremap(base, 0, 0, MREMAP_MAYMOVE | MREMAP_FIXED,
                           (void *)0x70000000);

        read_maps(fd, path, MAPS_CHECK);

        printf("\nReport : \n");
        (mremap_check)
                ? printf("This kernel appears to be VULNERABLE\n\n")
                : printf("This kernel appears to be NOT VULNERABLE\n\n");

        close(fd);
        return 0;
}


[root@work root]# cat > mremap_check.c
... 붙여넣기 ...
[Ctrl+D]
[root@work root]# gcc -o mremap_check mremap_check.c
[root@work root]#

2. 프로그램 실행

[root@work root]# ./mremap_check

Base address : 0x60000000

08048000-08049000 r-xp 00000000 03:02 294572     /root/mremap_check
08049000-0804a000 rw-p 00000000 03:02 294572     /root/mremap_check
40000000-40015000 r-xp 00000000 03:02 3482984    /lib/ld-2.3.2.so
40015000-40016000 rw-p 00014000 03:02 3482984    /lib/ld-2.3.2.so
40016000-40018000 rw-p 00000000 00:00 0
40022000-40155000 r-xp 00000000 03:02 3482991    /lib/libc-2.3.2.so
40155000-40159000 rw-p 00132000 03:02 3482991    /lib/libc-2.3.2.so
40159000-4015b000 rw-p 00000000 00:00 0
60000000-60002000 rw-p 00000000 00:00 0
bfffd000-c0000000 rwxp ffffe000 00:00 0

Remapping at 0x70000000...

08048000-08049000 r-xp 00000000 03:02 294572     /root/mremap_check
08049000-0804a000 rw-p 00000000 03:02 294572     /root/mremap_check
40000000-40015000 r-xp 00000000 03:02 3482984    /lib/ld-2.3.2.so
40015000-40016000 rw-p 00014000 03:02 3482984    /lib/ld-2.3.2.so
40016000-40018000 rw-p 00000000 00:00 0
40022000-40155000 r-xp 00000000 03:02 3482991    /lib/libc-2.3.2.so
40155000-40159000 rw-p 00132000 03:02 3482991    /lib/libc-2.3.2.so
40159000-4015b000 rw-p 00000000 00:00 0
60000000-60002000 rw-p 00000000 00:00 0
bfffd000-c0000000 rwxp ffffe000 00:00 0

Report :
This kernel appears to be NOT VULNERABLE

[root@work root]#

위처럼 NOT VULNRABLE 이라고 출력될 경우 취약하지 않은 커널을 사용하고 계심으로 패치를 하실 필요가 없습니다.
반면에, 취약점이 존재할 경우엔 다음과 같은 메시지가 출력됩니다.

Report :
This kernel appears to be VULNERABLE

이 경우엔 패치를 진행하십시요.

참고로 첨부된 체크 프로그램은 서버에 어떠한 악영향도 미치지 않음으로 안심하고 사용하셔도 됩니다.


[취약점 피해]
다음과 같이 외국에서 발표된 공격 프로그램을 이용하여 테스트를 해보았습니다.

====================================================
Trying 192.168.0.2 ...
Connected to 192.168.0.2.
Red Hat Linux release 9 (Shrike)
Kernel 2.4.23 on an i686
login: user
Password:
Last login: Tue Dec 16 09:21:01 from 192.168.0.1
[user@localhost user]$
[user@localhost user]$ id
uid=501(user) gid=501(user) groups=501(user)
[user@localhost user]$
====================================================

이처럼 일반 사용자 권한을 가지고 있는 사용자가 공격 코드를 만들어 실행합니다.

====================================================
[user@localhost user]$ cat > exp.c
.. 악용 가능성이 있음으로 생략 ..
[user@localhost user]$ gcc -o exp exp.c
[user@localhost user]$ ./exp

[+] Please wait...HEAVY SYSTEM LOAD!
        4483 of 1114129 [ 0 %  ETA 28960.2 s ] 

====================================================

프로그램을 실행한 후, 약 5분이 지나자 시스템 전체가 마비되는 것을 확인할 수 있었습니다. 마비된 시스템은 telnet, ssh, web server를 포함한 모든 서비스를 제공할 수 없는 상태가 되었습니다. (리부팅 후엔 시스템이 정상화됨)
공격 프로그램의 코드를 보면, do_mremap() 함수의 취약점을 이용하여 최고 관리자 권한을 얻을 수 있도록 구현된 것으로 보이나, 실제 테스트해본 결과 위처럼 로컬 D.o.S 공격 효과만을 보였습니다. 어쨌건, 이 취약점으로 인하여 시스템이 피해를 볼 수 있음으로 패치 작업을 꼭 진행하시기를 당부 드립니다.


[취약점 분석]
ISEC 그룹에서 발표한 보안 권고문을 첨부하도록 하겠습니다.

Synopsis:  Linux kernel do_mremap() local privilege escalation
           vulnerability
Product:   Linux kernel
Version:   2.4 up to 2.4.23, 2.6.0
Vendor:    http://www.kernel.org/
Author:    Paul Starzetz ,
           Wojciech Purczynski

Date:      January 5, 2004
Update:    January 15, 2004
Update:    January 16, 2004 (reformatted)


Issue:
======

A critical security vulnerability has been found in the Linux kernel memory management code in mremap(2) system call due to incorrect bound checks.


Details:
========

The mremap system call provides functionality of resizing (shrinking or growing) as well as moving across process's addressable space of existing virtual memory areas (VMAs) or any of its parts.

A typical VMA covers at least one memory page (which is exactly 4kB on the i386  architecture). An incorrect bound check discovered inside the do_mremap() kernel code performing remapping of a virtual memory area may lead to creation of a virtual memory area of 0 bytes in length.

The problem bases on the general mremap flaw that remapping of 2 pages from inside a VMA creates a memory hole of only one page in length but also an additional VMA of two pages. In the case of a zero sized remapping request no VMA hole is created but an additional VMA
descriptor of 0 bytes in length is created.

Such a malicious virtual memory area may disrupt the operation of the other parts of the kernel memory management subroutines finally leading to unexpected behavior.

A typical process's memory layout showing invalid VMA created with mremap system call:

    08048000-0804c000 r-xp 00000000 03:05 959142     /tmp/test
    0804c000-0804d000 rw-p 00003000 03:05 959142     /tmp/test
    0804d000-0804e000 rwxp 00000000 00:00 0
    40000000-40014000 r-xp 00000000 03:05 1544523    /lib/ld-2.3.2.so
    40014000-40015000 rw-p 00013000 03:05 1544523    /lib/ld-2.3.2.so
    40015000-40016000 rw-p 00000000 00:00 0
    4002c000-40158000 r-xp 00000000 03:05 1544529    /lib/libc.so.6
    40158000-4015d000 rw-p 0012b000 03:05 1544529    /lib/libc.so.6
    4015d000-4015f000 rw-p 00000000 00:00 0
[*] 60000000-60000000 rwxp 00000000 00:00 0
    bfffe000-c0000000 rwxp fffff000 00:00 0

The broken VMA in the above example has been marked with a [*].


Exploitation:
=============

The iSEC team has identified multiple attack vectors for the bug discovered.  In this section we want to describe the page counter method however we strongly believe that a much faster and more convenient method exists.

As mentioned above a VMA of 0 bytes in size can be introduced into the process's virtual memory list. Its unusual size renders such a VMA partially invisible to the kernel main VM helper routine called find_vma(). The find_vma(ADDR) function returns the first VMA descriptor (START, END) from the current process's list satysfying ADDR < END or NULL if none. Obviously given a VMA starting and ending at the same address ADDR the condition is violated if one searches for ADDR's VMA thus the next VMA in the list will be returned.

The mremap() code calls the insert_vm_struct() helper function after creating the bogus VMA descriptor in kernel memory which in turn checks the new location calling the find_vma() helper which returns the wrong result if a zero sized VMA is already present in the new location.
Therefore it is possible to introduce multiple bogus VMA descriptors for the same virtual memory address. This happens only if the adjacent zero sized VMAs differ in their descriptor flags because otherwise they will be linked together in insert_vm_struct().

Later the process virtual memory list could look like:

    08048000-080a2000 r-xp 00000000 03:02 53159      /tmp/test
    080a2000-080a5000 rw-p 00059000 03:02 53159      /tmp/test
    080a5000-080a6000 rwxp 00000000 00:00 0
    40000000-40001000 r--p 00000000 00:00 0
    60000000-60000000 r--p 00000000 00:00 0
    60000000-60000000 rw-p 00000000 00:00 0
    60000000-60000000 r--p 00000000 00:00 0
    60000000-60001000 rwxp 00000000 00:00 0
    bffff000-c0000000 rwxp 00000000 00:00 0


Further we have found that there is an off-by-one increment inside the copy_page_range() function for the page counter of the first VMA page directly following a zero sized VMA area. This is not a bug in the copy_page_range code(), it is just a feature for a combined zero and non-zero VMA. The copy_page_range function is called on fork() to copy parent's page tables into the child process.

Moreover we must note that it is possible to remove a zero-sized VMA from the virtual memory list if another suitable VMA is mapped directly below the starting address of the 0-VMA. Suitable means that the new VMA must have exactly the same attributes (read, exec, etc) as the following
zero-sized VMA and do not map a file. This again is a feature of the mmap() system call which will try to minimize the number of used VMA descriptors merging them if possible. Note that merging the VMAs doesn't influence any page counters in following VMAs.

Combining the findings above we conclude that it is possible to arbitrarily increment the page counter of the first VMA page by forking more and more a process with a zero-sized VMA 'sandwich'. Cleanup must be done in the child before it can exit() otherwise the kernel would
print a nasty error message while trying to remove the bogus VMA mappings.

The goal is to overflow the page counter to become 1 again in the child process.  If the corresponding VMA is unmapped now, the page counter will become 0 and the page returned to the kernel memory management.
Note that the parent will still hold a reference to the freed page in its page table thus making a manipulation of kernel memory possible.

Let's take a closer look at the incrementing of the page counter.  We can introduce M (marked with A's and B's) 0-sized VMAs directly before the victim VMA hosting the page we want the counter to overflow. If the victim maps anonymous memory, the first write access to the victim VMA page (marked with P) will allocate and insert a fresh page frame into the process's page table and the page counter will be set to 1:

[A][B][A][B] ... [A][P  VICTIM  ]

After the first fork() P's page counter will become 1 + M + 1 where the first one is for the original copy in the parent, M for the bogus VMAs and one for the copy in the child. Cleaning up the 0-VMAs in the child will not change the page counter however it will be decremented by one
on child's exit. Thus after the first fork()-exit() pair it will become 1 + M. We can conclude for N forks taking integer overflows into account that without the final exit() call in the child following equation holds:

1 + M*N + 1 = 1

or that

M*N = 2^32-1 = 3 * 5 * 17 * 257 * 65537

Thus we can for example choose to create (3*5*257) 0-sized VMAs and fork the parent (17*65537) times to overflow P's page counter. This may be a quite longish task. Times ranging from about one hour on a fast machine to more than 10 hours have been observed.

Further exploitation proves to be easy because the kernel page management has the nice property to use a kind of reversed LRU policy for page allocation.  That means that if a page has been released to the kernel MM subsystem it will be returned on a subsequent allocation
request. The released page could be for example allocated to a file mapping we can normally only read from or to kernel structures, etc.

It is worth noting that the parent's page reference (PTE) must be unprotected before we can use it to modify page contents because fork() will mark it as read only (for copy-on-write reasons).


Impact:
=======

No special privileges are required to use the mremap(2) system call thus any process may misuse its unexpected behavior to disrupt the kernel memory management subsystem. Proper exploitation of this vulnerability may lead to local privilege escalation including execution of  arbitrary code with kernel level access. Proof-of-concept exploit code has been created and successfully tested giving UID 0 shell on vulnerable systems.

All users are encouraged to patch all vulnerable systems as soon as appropriate vendor patches are released.


Credits:
========

Paul Starzetz has identified the vulnerability and performed further research.


Disclaimer:
===========

This  document and all the information it contains are provided "as is", for educational purposes only, without warranty of any kind, whether express or implied.

The  authors reserve the right not to be responsible for the topicality, correctness, completeness or quality of the information provided in this document. Liability claims regarding damage caused by the use of any information provided, including any kind of information which is
incomplete or incorrect, will therefore be rejected.


[취약점 패치]
이번 do_mremap() 취약점에 대한 패치는 do_brk() 때와는 달리 커널 업그레이드만이 유일한 해결책으로 알려져 있습니다.

다음 절차에 따라 커널 업그레이드를 진행하시기 바랍니다.

시작하기 전에..

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

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

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

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

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

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

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

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

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

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

이 때, /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 등의 리눅스 전문 사이트에서 해결책에 대한 정보를 검색하시기 바랍니다.

댓글 없음:

댓글 쓰기