Linux high-risk vulnerability repair process records in the past two years

1. Background

insert image description here

In August 2023, in the face of the upcoming "Universiade" and "Asian Games", this year's routine security network stage will also usher in new challenges and moments. Emergency "preparation" time! Here we mainly talk about the vulnerability handling at the Linux OS level, which involves upgrading the system kernel, and it is hereby recorded for reference.
insert image description here

The Linux kernel source directory is placed in the "/usr/src/linux" directory by default. This directory is often referred to as the "Linux source tree". This directory contains all files of the Linux kernel source code, including subdirectories and files. All files in this directory are stored in text format and written in C language. Among them, the description of the kernel source code directory: 1. The arch directory contains the core code related to the hardware architecture supported by this core source code; 2. The include directory includes most of the include files of the core; 3. The init directory contains the core Startup code; 4. mm directory, including all memory management codes; 5. drivers directory, including all device drivers in the system; 6. Ipc directory, including core inter-process communication codes.

insert image description here

Since the release of version 2.6.0, the Linux kernel has been named ABCD. The changes in A and B can be said to be insignificant, C is the real version of the kernel, and each version change will bring new features. For example, changes in internal APIs, etc., the number of changes is often tens of thousands. D is for security patches and bug fixes. If you are a beginner or user of Linux, just know about stable, which stands for stable release of kernel updates. mainline refers to the current official kernel, which is updated and maintained by Linus Torvalds, and the code contributed by developers is mainly merged into mainline. Both linux-next and snapshot are snapshots generated before the end of the code submission cycle, and are used for testing by Linux code contributors. At present, the update cycle of the stable version is six to ten weeks, and the rc of the next stable version will be updated basically every week. The new version of the kernel is divided into two types, one is the Full Source version, the complete kernel version. Relatively large, usually a tar.gz or .bz2 file. The other is a patch file, that is, a patch file. The patch file is generally only K to several hundred K in time, but for a specific version, you have to find the corresponding version to use it.

Related resources: Linux kernel official website , kernel Livepatch ; build a trimmed Linux kernel ;

2. Related high-risk vulnerabilities

2.1. curl authentication bypass vulnerability

Vulnerability code: CVE-2023-27535
Vulnerability description: There is an authentication bypass vulnerability in curl in version 7.13.0-7.88.1. libcurl will reuse previously created FTP connections, even if one or more parameters are changed, possibly making the effective user different, resulting in a second transfer with wrong credentials.
Vulnerability impact range: curl 7.13.0 - 7.88.1
Turnaround measures: Please update to the safe version as soon as possible for users who use this product: https://github.com/curl/curl/releases or fall back to a version earlier than 7.13.0

2.2. Linux kernel local privilege escalation vulnerability (CVE-2021-33909)

Vulnerability code: CVE-2021-33909
Vulnerability description: There is an input validation error vulnerability in the Linux kernel, which originates from an out-of-bounds write flaw.
Vulnerability impact range: Linux kernel >=3.16 / <= 5.13.3
Repair measures: Currently, the manufacturer has released an upgrade patch to fix the vulnerability. The link for obtaining the patch is: https://cdn.kernel.org/pub/linux/kernel/v5. x/ChangeLog-5.13.4

Note: The vulnerability patch still needs to recompile the kernel; if you are connected to the Internet, you can directly use the yum update command. This command will install the latest known security patches in the system, but will not install new software packages; in addition , for a large-scale patch installation, scripts can also be used to centralize all patch files into the script, so that large-scale patch installation can be realized. If you are not connected to the Internet or in special circumstances, you can also use the diff and patch commands to patch, see below for details.

2.3. Linux kernel buffer overflow vulnerability (CNVD-2023-51380)

Vulnerability code: CNVD-2023-51380
Vulnerability description: There is a buffer overflow vulnerability in the Linux kernel. The vulnerability comes from a defect in the frame buffer console (fbcon). When providing font->width and font- >height is not properly checked, an attacker can exploit this vulnerability to cause undefined behavior and denial of service.
Vulnerability scope: Linux Linux kernel <6.2
Repair measures: The manufacturer has released a vulnerability fix, please pay attention to the update in time:
https://github.com/torvalds/linux/commit/2b09d5d364986f724f17001ccfe4126b9b43a0be

2.4. Linux Polkit Local Privilege Escalation Vulnerability (CVE-2021-4034)

Vulnerability code: CVE-2021-4034
Vulnerability description: There is a local privilege escalation vulnerability in polkit's pkexec. Attackers who have obtained ordinary privileges can gain root privileges through this vulnerability.
Vulnerability scope: Since polkit is a pre-installed tool for the system, all current mainstream Linux versions are affected.
Repair measures: refer to the impact scope of the vulnerability, and upgrade to the latest security version in time.

2.5. Linux Kernel Privilege Escalation Vulnerability (CVE-2020-14386)

Vulnerability code: CVE-2020-14386
Vulnerability description: There is a privilege escalation vulnerability (CVE-2020-14386) in the Linux distribution. Perform out-of-bounds write to achieve privilege escalation. A local attacker can use this vulnerability to elevate from an unprivileged user to root user privileges by sending specially crafted request content to the affected host; only local users with the CAP_NET_RAW function enabled can trigger this issue .

Vulnerability scope: Ubuntu 18.04 and subsequent versions; Centos 8/RHEL 8; Debian 9/10; Red Hat Enterprise Linux 7 and centos7 are not affected;

Repair measures: 1) Upgrade the kernel to a safe version or apply a repair patch; kernel download address: https://github.com/torvalds/linux/releases
2) Turn off the CAP_NET_RAW function for protection; if the CAP_NET_RAW function is disabled by default (for Red Hat Enterprise Linux), only privileged users can trigger this error. The mitigation is to disable the CAP_NET_RAW capability for regular users and executables. On Red Hat Enterprise Linux 8, the CAP_NET_RAW capability is also available by leveraging the unprivileged user namespace. The mitigation is to disable unprivileged user namespaces by setting user.max_user_namespace to 0:

echo "user.max_user_namespaces=0" > /etc/sysctl.d/userns.conf
sysctl -p /etc/sysctl.d/userns.conf

OpenShift Container Platform 4.5 and 4.4 can mitigate this by removing "CAP_NET_RAW" from the default cri-o capabilities provided to pods (note: this may prevent "ping" from working in unprivileged pods. This fix is ​​not yet available for OpenShift 4.3 or lower for verification):

apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
  labels:
    machineconfiguration.openshift.io/role: worker
  name: 50-reset-crio-capabilities
spec:
  config:
    ignition:
      version: 2.2.0
    storage:
      files:
      - contents:
          source: data:text/plain;charset=utf-8;base64,W2NyaW8ucnVudGltZV0KZGVmYXVsdF9jYXBhYmlsaXRpZXMgPSBbCiAgICAiQ0hPV04iLAogICAgIkRBQ19PVkVSUklERSIsCiAgICAiRlNFVElEIiwKICAgICJGT1dORVIiLAogICAgIlNFVEdJRCIsCiAgICAiU0VUVUlEIiwKICAgICJTRVRQQ0FQIiwKICAgICJORVRfQklORF9TRVJWSUNFIiwKICAgICJTWVNfQ0hST09UIiwKICAgICJLSUxMIiwKXQo=
        filesystem: root
        mode: 0644
        path: /etc/crio/crio.conf.d/reset-crio-capabilities.conf

For a single executable program, the getcap command and the setcap command are used to view and set the capabilities attribute of the program file respectively, and execute the shutdown as follows:

# 查看程序的 cap 权限
getcap /bin/ping	 //默认输出如下

/bin/ping = cap_net_admin,cap_net_raw+p

# 删除 cap_net_raw 权限

setcap cap_net_raw-ep /bin/ping

# 检查

getcap /bin/ping  //输出应如下

/bin/ping =

#也可以检查执行文件是否设置了SUID,即-s权限,如果有,普通用户就可以执行这些命令了
chmod 755 /bin/ping   #在移除 SUID 权限后,普通用户在执行 ping 命令时碰到了 "ping: socket: Operation not permitted" 错误
#恢复
setcap cap_net_admin,cap_net_raw+ep /bin/ping
#移除,命令中的 ep 分别表示 Effective 和 Permitted 集合,+ 号表示把指定的 capabilities 添加到这些集合中,- 号表示从集合中移除(对于 Effective 来说是设置或者清除位)。
setcap cap_net_admin,cap_net_raw-ep /bin/ping

Related links: Redhat Vulnerability Description , Linux capabilities , Linux/Container Capabilities Control Model

2.6. Linux Kernel Privilege Escalation Vulnerability (CVE-2023-1829)

Vulnerability code: CVE-2023-1829
Vulnerability description: There is a use-after-free vulnerability in the Linux kernel traffic control index filter (tcindex). Since the tcindex_delete function cannot properly deactivate the filter and delete the underlying structure in some cases, it may This results in a double free structure, which can be exploited by a local low-privileged user to elevate their privileges to root.
Vulnerability scope: 2.6.12-rc2 <= Linux Kernel version < 6.3
Remediation measures: The vulnerability has been fixed, and affected users can update the Linux kernel to the following versions:
Linux Kernel 4.14.308
Linux Kernel 4.19.276
Linux Kernel 5.4 .235
Linux Kernel 5.10.173
Linux Kernel 5.15.100
Linux Kernel 6.1.18
Linux Kernel 6.2.5
Linux Kernel 6.3

2.7. Linux Kernel Privilege Escalation Vulnerability (CVE-2023-0386)

Vulnerability code: CVE-2023-0386
Vulnerability description: A flaw was found in the Linux kernel. Unauthorized access to the execution of a functional setuid file was found in the OverlayFS subsystem of the Linux kernel. Files are copied from one nosuid mount to another. This uid mapping error allows local users to elevate their privileges on the system.
Vulnerability impact range: linux kernel v2.6.12-rc2 to v6.2-rc6
Repair measures: The vulnerability has been fixed, https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux. git/commit/?id=4f11ada10d0ad3fd53e2bd67806351de63a4f9c3
Download address: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/refs/, patch fs/overlayfs/copy_up.c
insert image description here

2.8. Linux Kernel Privilege Escalation Vulnerability (CVE-2023-32233)

Vulnerability code: CVE-2023-32233
Vulnerability description: There is a UAF vulnerability in the Linux kernel Netfilter nf_tables, which can be successfully exploited to achieve local privilege escalation.
Vulnerability impact range: v5.1-rc1 <= Linux Kernel <= 6.3.1
Repair measures: The vulnerability has been fixed, reference link: https://github.com/torvalds/linux/commit/c1592a89942e9678f7d9c8030efa777c0d57edab; patch include/ net/netfilter/nf_tables.h and net/netfilter/nf_tables_api.c
, net/netfilter/nft_dynset.c, net/netfilter/nft_lookup.c, net/netfilter/nft_objref.c total 5 patch packages:
insert image description here

3. Linux OS patching

insert image description here

3.1. Patch repair process

Regarding kernel patching, since there are many source codes of the Linux kernel, when the kernel is modified and a new kernel is released, it is generally released in the form of a patch, rather than the entire kernel packaged and released.

1) Generate a patch

In Linux, we can use the Patch command to patch the code to fix bugs, vulnerabilities, etc., and help users update and fix some security vulnerabilities in the Linux kernel; while the patch file is generated using the diff command, the diff command Its function is to compare the differences between two files line by line , and then output the comparison results to the patch file . You can also use the Diffstat command to compare attributes; the format of the command to generate a patch file is as follows:

Grammar format:

diff [Options] Source file (folder) Destination file (folder) #It is to patch the source file (folder) to make it a destination file (folder), the term is called "upgrade".

diff -uNr  oldfile   newfile > patch_file.patch

Parameter analysis:

    -u:以统⼀格式创建补丁⽂件,这种格式⽐缺省格式更紧凑些

    -N:确保补丁⽂件将正确地处理已经创建和删除⽂件的情况

    -r:递归,会将两个不同版本源代码⽬录中的所有对应⽂件全部都进⾏⼀次⽐较,包括⼦⽬录⽂件

    oldfile:源⽂件(⽬录),未进⾏修改的

    newfile:以oldfile为基础,根据需求对⾥⾯的⽂件内容修改之后结果

    patch_file.patch:补丁文件⼀般以.patch为后缀。

Note: The function of the patch command is to compare all the files of the source file (folder) and the target file (folder) one by one, and record the difference information into patch_file.patch. The content of the patch file is explained below:

※ Patch header part:

    1、--- test1.txt 表示源文件(被修改的文件)
    2、+++ test2.txt 表示目的文件

※ Block part ( @@represents the beginning of a block):

    3、@@ -1,3 表示源文件从第1行开始,一共有3行有差异

    4、@@  1,3 表示目的文件从第1行开始,一共有3行有差异

※ Text:

    5、-zzzzzxxccv 表示被修改的文件要删除这一行

    6、+bbbbbbbbgd表示被修改的文件要增加这一行

※ For example, the following patch notes:

insert image description here
2) patch

Often the patch files are released by the official, and we can directly patch the contents of the released Patch file to our own code through the patch command, that is, complete the code upgrade. The format of the patch command is as follows (here only introduces the patch operation on the source file (folder)):

patch -pN < xxx.patch
#去除补丁,恢复旧版本
patch -RE -p0 < xxx.patch
#内核打补丁
gunzip ../setup-dir/ patch-2.4.21-rmk1.gz  #发布的补丁文件都是使用gzip压缩的
cd linux-2.4.21    #进入你的内核源代码目录
patch –p1 < ../../setup-dir/patch-2.4.21-rmk1   #打补丁

Parameter analysis:

pN: The N-level directory should be ignored when patching.
-R: Indicates that the "new" file and "old" file in the patch file are to be replaced (actually equivalent to patching the new version to make it an old version) -E: If an empty file is found in the table
, just delete it

Example: If the patch file contains the pathname /net/packet/af_packet.c, then:

-p 0 Use the full path name; therefore, it is generally recommended not to use an absolute path when using the diff command to make a patch, otherwise you need to count from the root directory to which level you are currently in when patching -p 1 Remove the leading slash and
leave Download net/packet/af_packet.c.
-p 3 Remove the leading slash and the first two directories, leaving af_packet.c.

Example: Using the instructions in the above figure, by executing: diff --git a/net/packet/af_packet.c b/net/packet/af_packet.cthe output is as follows:

--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2170,7 +2170,8 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
 	int skb_len = skb->len;
 	unsigned int snaplen, res;
 	unsigned long status = TP_STATUS_USER;
-	unsigned short macoff, netoff, hdrlen;
+	unsigned short macoff, hdrlen;
+	unsigned int netoff;
 	struct sk_buff *copy_skb = NULL;
 	struct timespec64 ts;
 	__u32 ts_status;
@@ -2239,6 +2240,10 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
 		}
 		macoff = netoff - maclen;
 	}
+	if (netoff > USHRT_MAX) {
    
    
+		atomic_inc(&po->tp_drops);
+		goto drop_n_restore;
+	}
 	if (po->tp_version <= TPACKET_V2) {
    
    
 		if (macoff + snaplen > po->rx_ring.frame_size) {
    
    
 			if (po->copy_thresh &&

Description: The patch header is composed of ---/+++two lines at the beginning, which are used to indicate the files to be patched. ---The beginning indicates the old file, and the beginning of +++ indicates the new file. A patch file may contain many sections starting with —/+++, and each section is used to apply a patch. So many patches can be included in one patch file.

If the parameter -p0 is used, it means to find a folder called a from the current directory, and look for the af_packet.c file under net/packet/ under it to perform the patch operation.

If the parameter -p1 is used, it means to ignore the first-level directory (that is, regardless of a), look for the net/packet/ folder from the current directory, and find af_packet.c under it. The premise of this is that the current directory must be the directory where a is located. The diff patch file can be in any location , as long as the path of the diff patch file is specified. Of course, you can use relative paths or absolute paths.

3) Linux kernel installation, compilation and patching
insert image description here

#下载内核
wget https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/snapshot/linux-6.5-rc3.tar.gz
#不用最新的也可以去如下网站下载内核
https://mirrors.edge.kernel.org/pub/linux/kernel/v6.x/
https://mirrors.aliyun.com/linux-kernel/
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v6.x/linux-6.4.6.tar.gz
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v6.x/patch-6.4.6.xz
#全部补丁
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v6.x/patch-6.4.xz
#内核3.10.x补丁,30-Jun-2013 22:51发布的,可修复之前暴漏的漏洞
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v3.x/patch-3.10.gz
#国内镜像网站最新版内核,2023-07-27 15:08
wget https://mirrors.aliyun.com/linux-kernel/v6.x/linux-6.4.7.tar.gz
wget https://mirrors.aliyun.com/linux-kernel/v6.x/patch-6.4.7.xz
//或
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v6.x/linux-6.4.6.tar.gz
wget https://mirrors.edge.kernel.org/pub/linux/kernel/v6.x/patch-6.4.6.xz
#将新内核和补丁包放到如下目录
mv linux-6.4.7.tar.gz patch-6.4.7.xz /usr/src/kernels/
#检查漏洞对应的补丁包文件,本次主要涉及如下:
对比https://github.com/torvalds/linux/commit/c1592a89942e9678f7d9c8030efa777c0d57edab下的nf_tables.h、nf_tables_api.c、nft_dynset.c、nft_lookup.c、nft_objref.c这5个补丁包(v6.5-rc3 中更新的),如果6.4.6或6.4.7对应文件的内容没有更新相关内容,或补丁报里对应文件没有相关内容,就进行替换,尝试编译
还有一个文件:https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=acf69c946233259ab4d64f8869d4037a198c7f06中的af_packet.c

#进到目录
cd /usr/src/kernels
yum install epel-release -y
yum install xz -y #一般cenos7已安装
#解压
tar -zxvf linux-6.5-rc3.tar.gz
tar -xvf linux-6.4.6.tar.gz -C /usr/src/kernels/
xz -d patch-6.4.6.xz
cp patch-6.4.6.patch /usr/src/kernels/linux-6.4.6

//配置内核,同make olddefconfig
cp -v /boot/config-$(uname -r) /usr/src/kernels/linux-6.4.6/.config  #现场centos7.5显示/boot/config-3.10.0-862.el7.x86_64;类似如下:

#
# Automatically generated file; DO NOT EDIT.
# Linux/x86_64 3.10.0-862.el7.x86_64 Kernel Configuration
#
CONFIG_64BIT=y
CONFIG_X86_64=y
CONFIG_X86=y
CONFIG_INSTRUCTION_DECODER=y
CONFIG_OUTPUT_FORMAT="elf64-x86-64"
CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
……
//打补丁的话直接跳转到打补丁那一步

//内核6.5.3 配置linux内核特性和模块,未使用可跳过,看内核打补丁
cd linux-6.5-rc3
#安装配置编译工具
yum install build-essential libncurses-dev bison flex libssl-dev libelf-dev
make mrproper   #每次配置并重新编译内核前需要先执行“make mrproper”命令清理源代码树,包括过去曾经配置的内核配置文件“.config”都将被清除。即进行新的编译工作时将原来老的配置文件给删除到,以免影响新的内核编译。相当于Remove all generated files + config + various backup files

make menuconfig   //用它生成的内核配置文件,决定将内核的各个功能系统编译进内核还是编译为模块还是不编译

#编译
make dep   #生成内核功能间的依赖关系,为编译内核做好准备。如果内核从未编译过,此步可跳过
make clean   #remove most generated files but keep the config and enough build support to build external modules;如果内核从未编译过,此步可跳过
make -j24     #make -j $(nproc --all) ,生成内核模块、bzImage、System.map等文件;如果-j后不跟任何数字,则不限制处理器并行编译的任务数
make bzImage  #可选项,bzImage命令会生成一个启动映像文件bzImage
make modules -j24
make modules_install -j24   #编译成功后,系统会在/lib/modules目录下生成一个新内核版本的子目录,里面存放着新内核的所有可加载模块(即将编译好的modules,也就是所生成的驱动文件放到/lib/modules/目录中去);
make install -j24    #将所生成的驱动文件放到/boot/目录中去,增加:
#cp .config /boot/config-6.4.0
#cp System.map /boot/System.map-6.4.0
#cp /arch/i386/boot/bzImage /boot/vmlinuz-6.4.0

#升级
update-initramfs -c -k 6.5-rc3  #或
mkinitramfs   #敲入命令生成内核版本相对应的img 文件:
#mkinitramfs 6.4.0 –o /boot/initrd.img-6.4.0   #至此,升级内核所需的所有文件config、System.map、vmlinuz、initrd.img 都已全部完成
update-grub			#更新启动文件grub.cfg,将6.4.0添加至系统启动选项中
#完成后重启
reboot

//打补丁
cd /usr/src/kernels/linux-6.4.6
patch -p1 < ../xx.patch   #据现场实际来

#配置内核,安装依赖
yum install ncurses-devel
make mrproper   #相当于Remove all generated files + config + various backup files,会检查有无不正确的.o文件和依赖关系,如果是下载的完整的源程序包即第一次进行编译,那么本步可以省略
make olddefconfig  #将当前系统存在的.config 文件拷贝至新内核源码目录,采用已有的.config文件的参数作为默认参数,同时升级依赖属性,新属性设置为默认值不再提醒。说明见下文
make menuconfig   //先 load(加载本地的 .config)
General setup
Preemption Model (Voluntary Kernel Preemption (Desktop)) ---> //内核抢占模式
(X) Preemptible Kernel (Low-Latency Desktop) //抢占式低延时,或者:
(*)Fully Preemptible Kernel (Real-Time)   //完全抢占内核
#保存退出。
//打完后重新编译安装内核
nproc  #确定内核核数,比如是24个
make -j24
make modules -j24
make modules_install -j24
make install -j24
#验证
ls -lh /boot   //查看是否有新增的内核版本

#确认当前启动的内核配置
cat /boot/grub2/grub.cfg |grep "menuentry "  //查看所有可用内核
grub2-mkconfig -o /boot/grub2/grub.cfg    //重新生成 gurb 配置
grub2-set-default 'CentOS Linux (3.10.0-862.el7.x86_64) 7 (Core)'  //设置默认启动的内核
grub2-editenv list    //查看内核修改结果,类似如下
saved_entry=CentOS Linux (3.10.0-862.el7.x86_64) 7 (Core)
tuned-adm profile latency-performance  //系统设置为低延迟的性能模式

//其他方式更新grub配置,有的系统没有如下这个命令,可跳过
update-initramfs -c -k 5.4.87  
update grub

##重启生效
reboot   

For more information on Linux kernel upgrade and compilation, please refer to: Linux system upgrade and kernel version upgrade ;

4. Appendix

4.1. Kernel compilation file description

1) .config file

It is used to use the kernel configuration file generated by make menuconfig to decide whether to compile each functional system of the kernel into the kernel or compile it into a module or not compile it.

2)vmlinuz 和 vmlinux

vmlinuz is the bootable , compressed kernel, "vm" stands for "Virtual Memory". Linux supports virtual memory. Unlike old operating systems such as DOS, which have a memory limit of 640KB, Linux can use hard disk space as virtual memory, hence the name "vm". vmlinuz is an executable Linux kernel . There are two ways to build vmlinuz : one is to create it through "make zImage" when compiling the kernel. zImage is suitable for small kernels , and its existence is for backward compatibility; the other is the kernel Created by commands during compilation make bzImage, bzImage is a compressed kernel image . Note: bzImage is not compressed with bzip2. The bz in bzImage is easy to cause misunderstanding. bz means "big zImage", and b in bzImage means "big". Both zImage(vmlinuz) and bzImage(vmlinuz) are 用gzip压缩. Not only are they a compressed file, but there is gzip decompression code embedded in the beginning of both files, so you cannot unpack vmlinuz with gunzip or gzip --dc. The kernel file contains a tiny gzip that decompresses the kernel and boots it. The difference between the two is that the old zImage decompresses the kernel to the low-end memory (the first 640K), and bzImage decompresses the kernel to the high-end memory (above 1M). If the kernel is relatively small, one of zImage or bzImage can be used, and the system running in the two ways is the same. Large kernels use bzImage, not zImage. vmlinu x is the uncompressed kernel, vmlinu z is the compressed file of vmlinux.

3) initrd.img
initrd is short for "initial ramdisk". initrd is generally used to temporarily boot the hardware to a state where the actual kernel vmlinuz can take over and continue booting. For example, initrd-2.4.7-10.img is mainly used to load file systems such as ext3 and drivers for scsi devices. If you are using a scsi hard disk, and there is no scsi hardware driver in the kernel vmlinuz, the kernel cannot load the root file system before loading the scsi module, but the scsi module is stored under /lib/modules of the root file system. In order to solve this problem, you can boot an initrd kernel that can read the actual kernel and use the initrd to correct the scsi boot problem. The initrd-2.4.7-10.img is a file compressed with gzip. The initrd image file is mkinitrdcreated using the mkinitrd utility to create an initrd image file . This command is proprietary to RedHat , and other Linux distributions may have corresponding commands. See help for more: man mkinitrd

4) System.map
System.map is a kernel symbol table for a specific kernel, generated by "nm vmlinux" and irrelevant symbols are filtered out. The following lines are from /usr/src/linux-2.4/Makefile:

nm vmlinux | grep -v '(compiled)|(.o$$)|( [aUw] )|(..ng$$)|(LASH[RL]DI)' | sort > System.map

When programming, symbols such as variable names or function names are named. The Linux kernel is a very complex code block with many global symbols. The Linux kernel does not use symbol names, but uses addresses of variables or functions to identify variables or function names. For example, instead of using symbols such as size_t BytesRead, Instead reference this variable like c0343f20. For computer people, prefer those names like size_t BytesRead to those like c0343f20. The kernel is mostly written in C , so the compiler/linker allows us to use symbol names when coding, and addresses when the kernel runs. However, in some cases, we need to know the address of a symbol, or the symbol corresponding to the address. This is done by the symbol table, which is a list of all symbols together with their addresses.

The Linux symbol table uses 2 files : /proc/ksyms and System.map. /proc/ksymsis a "proc file", created when the kernel boots . In fact, it is not really a file, it is just a representation of kernel data, but it gives people the illusion of a disk file, which can be seen from its file size of 0 . However, System.mapare actual files that exist on your filesystem. When you compile a new kernel, the address of each symbol name will change, and your old System.map has wrong symbol information. Every time a kernel is compiled, a new System.map is generated, and you should use the new System.map to replace the old System.map.

Although the kernel itself does not actually use System.map, other programs such as klogd, lsof, and ps require a correct System.map. If you use the wrong or no System.map, klogd output will be unreliable, which can make troubleshooting the program difficult. Without System.map, you may face some annoying prompts. A few other drivers require a System.map to resolve symbols, and they won't work properly without a System.map created for the particular kernel you're running.

In order to perform name-address resolution, the Linux kernel log daemon klogd needs to use System.map. System.map should be placed where the software that uses it can find it. Execution: man klogd shows that if System.map is not given to klogd as a variable location, then it will check System.map in three places in the following order: /boot/System.map, /System.map, / usr/src/linux/System.map
System.map also has version information, and klogd can intelligently find the correct image (map) file.

4.2, make menuconfig process

When we execute the make menuconfig command, what exactly does the system do for us? There are a total of the following files involved:

1. The scripts folder under the root directory of the Linux kernel; the scripts folder stores files related to the graphics drawing of the make menuconfig configuration interface. As a user, we do not need to care about the contents of this folder. 2.arch/$ARCH/Kconfig

file , the Kconfig file under each layer directory

3. the makefile file under the Linux kernel root directory, the makefile file under each layer directory

4. the .config file under the Linux kernel root directory, the file under arch/$ARCH/configs/

5 .include/generated/autoconf.h file in the root directory of the Linux kernel

insert image description here
Before we execute the make menuconfig command and the following configuration interface appears, the system has done the following work for us:

First, the system will read the Kconfig file in the arch/$ARCH/ directory to generate the entire configuration interface options (Kconfig is the core of the entire linux configuration mechanism), so what is the value of the ARCH environment variable? It is determined by the makefile file in the root directory of the linux kernel , and there is a definition of this environment variable under the makefile:

SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
                  -e s/arm.*/arm/ -e s/sa110/arm/ \
                  -e s/s390x/s390/ -e s/parisc64/parisc/ \
                  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
                  -e s/sh[234].*/sh/ )
      ..........
      export KBUILD_BUILDHOST := $(SUBARCH)
      ARCH        ?= $(SUBARCH)
      CROSS_COMPILE   ?=

For example, if the configuration interface is generated by the make ARCH=arm menuconfig command, the system will read the arm/arm/kconfig file to generate configuration options.

Secondly, some of its default configuration options are stored in the arch/$ARCH/configs/ directory, which is the arch/arm/configs folder for arm. There are many options in this folder, which one will the system read? By default, the kernel will read the .config file in the root directory of the linux kernel as the default option of the kernel. We can choose to modify the .config file directly and execute the make menuconfig command to read the new options. However, this is generally not the case. In the menuconfig configuration interface, we can select certain options to be selected or not selected through space, esc, and carriage return. When saving and exiting, the Linux kernel will update the new options to .config. At this point, we can rename .config to another file and save it (the system will delete the .config file when executing make distclean), and we don’t need to go to arch/arm/configs to obtain the corresponding file when we configure the kernel in the future Yes, save the trouble of reconfiguration, just copy the saved .config file as a .config file to load.

Through the above two steps, we can correctly read and configure the interface we need, so how do they establish a compilation relationship with the makefile? When you save the make menuconfig option, the system will not only automatically update the .config, but also save all the options in the form of a macro in the include/generated/autoconf.h file in the root directory of the Linux kernel. The source code in the kernel will be these .h files, and will be conditionally compiled according to the definition of the macro. When we need to choose whether to compile a file as a whole, we also need to modify the corresponding makefile. For example: when
insert image description here
we choose whether to compile the file s3c2410_ts.c, the makefile will decide whether to compile this file according to CONFIG_TOUCHSCREEN_S3C2410. This macro is in Kconfig Defined in the file , when we complete the configuration, it will appear in .config and autconf. So far, we have completed the compilation process of the entire linux kernel. Finally, we will find that during the entire Linux kernel configuration process, the interface left to the user is actually only the Kconfig, makefile and corresponding source files of each layer .

For example, if we want to add a function to the kernel and control its claim process through make menuconfig, the first thing we need to do is: modify the Kconfig file in the corresponding directory, and add the corresponding options according to the Kconfig syntax; secondly, execute make menuconfig to choose to compile into the kernel Either not compiled into the kernel, or compiled into a module, the .config file and autoconf.h file will be automatically generated; finally modify the makefile in the corresponding directory to complete the addition of compilation options; finally execute the make command to compile.

4.3, config and Makefile

There are two documents Kconfig and Makefile under each directory of the Linux kernel source tree . The Kconfig distributed to each directory constitutes a distributed kernel configuration database , and each Kconfig describes the kernel configuration menu related to the source document of the directory it belongs to . When executing kernel configuration make menuconfig, the menu is read out from Kconfig, and the user selects it and saves it in the kernel configuration file of **.config**. When the kernel is compiled, the .config is called by the Makefile, and the user's choice is known. This content shows that Kconfig is the configuration menu corresponding to each level of the kernel.

If you want to add a new driver to the source code of the kernel, you need to modify Kconfig so that you can select this driver. If you want this driver to be compiled , you need to modify Makefile. There are two types of documents that need to be modified when adding a new driver (if you add only files, you only need to modify the current layer Kconfig and Makefile files; if you add a directory, you need to modify a pair of Kconfig and Makefile under the current layer and directory. Makefile) Kconfig and Makefile. If you want to know how to modify these two documents, you need to know the grammatical structure of the two documents. For the grammar of Kconfig, please refer to the reference "[linux-2.6.31] kbuild".
Makefile consists of 5 parts:

kernel file illustrate
Makefile Top-level Makefile
.config kernel configuration file
arch/$(ARCH)/Makefile Architecture Makefile
scripts/Makefile.* Common rules that apply to all kbuild Makefiles etc.
kbuild Makefiles There are about 500 such files

The top-level Makefile reads the kernel configuration and generates the .config file. The top-level Makefile builds two main targets: vmlinux (kernel image) and modules (all module files). It builds these targets by recursively visiting subdirectories under the kernel source tree. Which subdirectories are accessed depends on the kernel configuration. The top-level Makefile contains an architecture Makefile, specified by arch/$(ARCH)/Makefile. Architecture Makefiles provide architecture-specific information to the top-level Makefile. Each subdirectory has a kbuild file and a Makefile file to execute the commands passed down from the upper layer. The kbuild and Makefile files use the information in the .config file to construct lists of the various files used by kbuild to build built-in or module objects. scripts/Makefile.* contains all definitions/rules, etc. This information is used to build the kernel using kbuild and Makefile.

Note: regardless of the excerpt from http://blog.chinaunix.net/uid-26497520-id-3593098.html#0

4.3. Linux kernel patching scene reference

1) Upgrade 2.6.23.11 to 2.6.23.12. I should first roll back 2.6.23.11 to 2.6.23 and then patch 2.6.23.12:

bzcat …/patch-2.6.23.11.bz2|patch -p1 -R #fall back to 2.6.23
bzcat …/patch-2.6.23.12.bz2|patch -p1 #hit to 2.6.23.12

2) 2.6.22.9 must first be downgraded to 2.6.22 and then upgraded to 2.6.23. Then upgraded to 2.6.23.9

bzcat …/patch-2.6.22.9.bz2|patch -p1 -R #Use the R command to cancel the patch. In this way, we will drop 22.9 to 22
zcat …/patch-2.6.23.gz|patch -p1 #This will upgrade to 2.6.23
zcat …/patch-2.6.23.11.bz2|patch -p1 # This will upgrade to 2.6 .23.11 This is the latest stable version

4.4、make defconfig、 make menuconfig、 make savedefconfig、 make olddefconfig 、make localmodconfig 区别

1) make defconfig

  first generates the initial .config through make xxx_defconfig, which is equivalent to copying the XXX_defconfig file into a .config file, where defconfig is the smallest config item, and the kernel compilation will compile the driver according to the .config file, after loading the After the command, the following make menuconfig will configure config based on the current .config;

2) make menuconfig

  The function of make menuconfig (image interface, based on ncurses library) is similar to that of make config (the latter is a text-type dialogue), which is to configure the config file based on the interface. The function of make config is to load ".config" as the default configuration, configuring it is equivalent to configuring the .config file with a graphical interface;

3) make savedefconfig

  Execute make saveconfig to generate the smallest defconfig file by executing .config;

4) make olddefconfig

  uses make oldconfig to check the .config of the newly added config item for dependency check and regenerate a new .config file, and the difference between the newly generated .config and the previous one is that the old .config is renamed to .config. old file. diffconfig .config.old .configYou can compare the difference between the old and new kernel configurations by executing
5) make localmodconfig

  through make localmodconfig will execute the lsmod command to check which modules (Modules) are loaded in the current system, and finally remove the unnecessary modules in the original .config, only Keep these modules from the previous lsmod, which simplifies the kernel configuration process and is mostly used in quick test scenarios. Disadvantage: This method can only make the compiled kernel support the modules that have been loaded in the current kernel, and the modules that have not been used at present will not be compiled into the subsequent kernel; Advantages: The compiled kernel is small and the compilation is fast.

"make config"      Plain text interface.
"make menuconfig"  Text based color menus, radiolists & dialogs.
"make nconfig"     Enhanced text based color menus.
"make xconfig"     Qt based configuration tool.
"make gconfig"     GTK+ based configuration tool.
"make oldconfig"   Default all questions based on the contents of
                   your existing ./.config file and asking about
                   new config symbols.
"make olddefconfig"
                   Like above, but sets new symbols to their default
                   values without prompting.
"make defconfig"   Create a ./.config file by using the default
                   symbol values from either arch/$ARCH/defconfig
                   or arch/$ARCH/configs/${PLATFORM}_defconfig,
                   depending on the architecture.
"make ${PLATFORM}_defconfig"
                   Create a ./.config file by using the default
                   symbol values from
                   arch/$ARCH/configs/${PLATFORM}_defconfig.
                   Use "make help" to get a list of all available
                   platforms of your architecture.
"make allyesconfig"
                   Create a ./.config file by setting symbol
                   values to 'y' as much as possible.
"make allmodconfig"
                   Create a ./.config file by setting symbol
                   values to 'm' as much as possible.
"make allnoconfig" Create a ./.config file by setting symbol
                   values to 'n' as much as possible.
"make randconfig"  Create a ./.config file by setting symbol
                   values to random values.
"make localmodconfig" Create a config based on current config and
                      loaded modules (lsmod). Disables any module
                      option that is not needed for the loaded modules.

                      To create a localmodconfig for another machine,
                      store the lsmod of that machine into a file
                      and pass it in as a LSMOD parameter.

                      Also, you can preserve modules in certain folders
                      or kconfig files by specifying their paths in
                      parameter LMC_KEEP.

                      target$ lsmod > /tmp/mylsmod
                      target$ scp /tmp/mylsmod host:/tmp

                      host$ make LSMOD=/tmp/mylsmod \
                      LMC_KEEP="drivers/usb:drivers/gpu:fs" \
                      localmodconfig

                      The above also works when cross compiling.

"make localyesconfig" Similar to localmodconfig, except it will convert
                      all module options to built in (=y) options. You can
                      also preserve modules by LMC_KEEP.
"make kvmconfig"   Enable additional options for kvm guest kernel support.
"make xenconfig"   Enable additional options for xen dom0 guest kernel
                   support.
"make tinyconfig"  Configure the tiniest possible kernel.

Guess you like

Origin blog.csdn.net/ximenjianxue/article/details/131973515