Registros del proceso de reparación de vulnerabilidades de alto riesgo de Linux en los últimos dos años

1. Antecedentes

inserte la descripción de la imagen aquí

En agosto de 2023, de cara a las próximas "Universiadas" y "Juegos Asiáticos", la etapa de red de seguridad de rutina de este año también marcará el comienzo de nuevos desafíos y momentos. ¡Tiempo de "preparación" de emergencia! Aquí hablamos principalmente sobre el manejo de vulnerabilidades a nivel del sistema operativo Linux, lo que implica actualizar el kernel del sistema, y ​​se registra aquí como referencia.
inserte la descripción de la imagen aquí

El directorio de origen del kernel de Linux se coloca en el directorio "/usr/src/linux" de forma predeterminada. Este directorio a menudo se conoce como el "árbol de fuentes de Linux". Este directorio contiene todos los archivos del código fuente del kernel de Linux, incluidos los subdirectorios y archivos. Todos los archivos en este directorio se almacenan en formato de texto y están escritos en lenguaje C. Entre ellos, la descripción del directorio del código fuente del núcleo: 1. El directorio arch contiene el código principal relacionado con la arquitectura de hardware compatible con este código fuente principal, 2. El directorio de inclusión incluye la mayoría de los archivos incluidos del núcleo, 3. El directorio init contiene el código de inicio principal, 4. directorio mm, incluidos todos los códigos de administración de memoria, 5. directorio de controladores, incluidos todos los controladores de dispositivos en el sistema, 6. directorio Ipc, incluidos los códigos de comunicación entre procesos principales.

inserte la descripción de la imagen aquí

Desde el lanzamiento de la versión 2.6.0, el kernel de Linux se ha denominado ABCD. Se puede decir que los cambios en A y B son insignificantes, C es la versión real del kernel y cada cambio de versión traerá nuevas funciones. Por ejemplo, cambios en las API internas, etc., la cantidad de cambios suele ser de decenas de miles. D es para parches de seguridad y correcciones de errores. Si es un principiante o un usuario de Linux, solo conozca estable, que significa publicación estable de actualizaciones del kernel. mainline se refiere al kernel oficial actual, que Linus Torvalds actualiza y mantiene, y el código aportado por los desarrolladores se fusiona principalmente en mainline. Tanto linux-next como snapshot son instantáneas generadas antes del final del ciclo de envío del código, y los contribuyentes de código de Linux las utilizan para realizar pruebas. Actualmente, el ciclo de actualización de la versión estable es de seis a diez semanas, y el rc de la próxima versión estable se actualizará básicamente cada semana. La nueva versión del kernel se divide en dos tipos, uno es la versión Full Source, la versión completa del kernel. Relativamente grande, generalmente un archivo tar.gz o .bz2. El otro es un archivo de parche, es decir, un archivo de parche. El archivo de parche generalmente es de K a varios cientos de K en el tiempo, pero para una versión específica, debe encontrar la versión correspondiente para usarla.

Recursos relacionados: sitio web oficial del kernel de Linux , kernel Livepatch , construir un kernel de Linux recortado ;

2. Vulnerabilidades de alto riesgo relacionadas

2.1 Vulnerabilidad de omisión de autenticación curl

Código de vulnerabilidad: CVE-2023-27535
Descripción de la vulnerabilidad: existe una vulnerabilidad de omisión de autenticación en curl en la versión 7.13.0-7.88.1. libcurl reutilizará las conexiones FTP creadas anteriormente, incluso si se cambian uno o más parámetros, lo que posiblemente haga que el usuario efectivo sea diferente, lo que resultará en una segunda transferencia con credenciales incorrectas.
Rango de impacto de la vulnerabilidad: curl 7.13.0 - 7.88.1
Medidas de respuesta: actualice a la versión segura lo antes posible para los usuarios que usan este producto: https://github.com/curl/curl/releases o recurra a una versión anterior a la 7.13.0

2.2 Vulnerabilidad de escalada de privilegios locales del kernel de Linux (CVE-2021-33909)

Código de vulnerabilidad: CVE-2021-33909
Descripción de la vulnerabilidad: existe una vulnerabilidad de error de validación de entrada en el kernel de Linux, que se origina a partir de una falla de escritura fuera de los límites.
Rango de impacto de la vulnerabilidad: Linux kernel >=3.16 / <= 5.13.3
Medidas de reparación: Actualmente, el fabricante ha lanzado un parche de actualización para corregir la vulnerabilidad.El enlace para obtener el parche es: https://cdn.kernel.org/ pub/linux/kernel/v5.x/ChangeLog-5.13.4

Nota: El parche de vulnerabilidad aún necesita volver a compilar el kernel; si está conectado a Internet, puede usar directamente el comando yum update . Este comando instalará los últimos parches de seguridad conocidos en el sistema, pero no instalará nuevos paquetes de software; Además, para una instalación de parches a gran escala, también se pueden usar secuencias de comandos para centralizar todos los archivos de parches en la secuencia de comandos, de modo que se pueda realizar una instalación de parches a gran escala. Si no está conectado a Internet o en circunstancias especiales, también puede usar los comandos diff y patch para parchear, consulte los detalles a continuación.

2.3 Vulnerabilidad de desbordamiento del búfer del kernel de Linux (CNVD-2023-51380)

Código de vulnerabilidad: CNVD-2023-51380
Descripción de la vulnerabilidad: existe una vulnerabilidad de desbordamiento de búfer en el kernel de Linux. La vulnerabilidad proviene de un defecto en la consola de búfer de cuadros (fbcon). Al proporcionar fuente-> ancho y fuente-> altura no es correctamente verificada, un atacante puede aprovechar esta vulnerabilidad para causar un comportamiento indefinido y denegación de servicio.
Alcance de la vulnerabilidad: Linux Linux kernel <6.2
Medidas de reparación: el fabricante ha publicado una corrección de vulnerabilidad, preste atención a la actualización a tiempo:
https://github.com/torvalds/linux/commit/2b09d5d364986f724f17001ccfe4126b9b43a0be

2.4 Vulnerabilidad de escalada de privilegios locales de Polkit en Linux (CVE-2021-4034)

Código de vulnerabilidad: CVE-2021-4034
Descripción de la vulnerabilidad: existe una vulnerabilidad de escalada de privilegios locales en pkexec de polkit.Los atacantes que han obtenido privilegios ordinarios pueden obtener privilegios de root a través de esta vulnerabilidad.
Alcance de la vulnerabilidad: dado que polkit es una herramienta preinstalada para el sistema, todas las versiones principales actuales de Linux se ven afectadas.
Medidas de reparación: consulte el alcance del impacto de la vulnerabilidad y actualice a la última versión de seguridad a tiempo.

2.5 Vulnerabilidad de escalada de privilegios del kernel de Linux (CVE-2020-14386)

Código de vulnerabilidad: CVE-2020-14386
Descripción de la vulnerabilidad: existe una vulnerabilidad de escalada de privilegios (CVE-2020-14386) en la distribución de Linux. Realice una escritura fuera de los límites para lograr la escalada de privilegios. Un atacante local puede usar esta vulnerabilidad para elevar de un usuario sin privilegios a un usuario raíz con privilegios mediante el envío de contenido de solicitud especialmente diseñado al host afectado; solo los usuarios locales con la función CAP_NET_RAW habilitada pueden desencadenar este problema .

Alcance de la vulnerabilidad: Ubuntu 18.04 y versiones posteriores, Centos 8/RHEL 8, Debian 9/10, Red Hat Enterprise Linux 7 y centos7 no se ven afectados;

Medidas de reparación: 1) Actualice el kernel a una versión segura o aplique un parche de reparación; dirección de descarga del kernel: https://github.com/torvalds/linux/releases
2) Desactive la función CAP_NET_RAW para protección; si la función CAP_NET_RAW está deshabilitado de forma predeterminada (para Red Hat Enterprise Linux), solo los usuarios privilegiados pueden desencadenar este error. La mitigación es deshabilitar la capacidad CAP_NET_RAW para usuarios regulares y ejecutables. En Red Hat Enterprise Linux 8, la capacidad CAP_NET_RAW también está disponible aprovechando el espacio de nombres de usuario sin privilegios. La mitigación consiste en deshabilitar los espacios de nombres de usuario sin privilegios configurando user.max_user_namespace en 0:

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

OpenShift Container Platform 4.5 y 4.4 pueden mitigar esto eliminando "CAP_NET_RAW" de las capacidades de cri-o predeterminadas proporcionadas a los pods (nota: esto puede evitar que "ping" funcione en pods sin privilegios. Esta solución aún no está disponible para OpenShift 4.3 o inferior para la verificación):

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

Para un solo programa ejecutable, el comando getcap y el comando setcap se usan para ver y configurar el atributo de capacidades del archivo del programa respectivamente, y ejecutar el apagado de la siguiente manera:

# 查看程序的 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

Enlaces relacionados: Descripción de la vulnerabilidad de Redhat , Capacidades de Linux , Modelo de control de capacidades de Linux/contenedor

2.6 Vulnerabilidad de escalada de privilegios del kernel de Linux (CVE-2023-1829)

Código de vulnerabilidad: CVE-2023-1829
Descripción de la vulnerabilidad: existe una vulnerabilidad de uso posterior a la liberación en el filtro de índice de control de tráfico del kernel de Linux (tcindex).Dado que la función tcindex_delete no puede desactivar correctamente el filtro y eliminar la estructura subyacente en algunos casos, Puede que esto resulte en una estructura libre doble, que puede ser explotada por un usuario local con pocos privilegios para elevar sus privilegios a root.
Alcance de la vulnerabilidad: 2.6.12-rc2 <= Versión del kernel de Linux < 6.3
Medidas correctivas: La vulnerabilidad se solucionó y los usuarios afectados pueden actualizar el kernel de Linux a las siguientes versiones:
Linux Kernel 4.14.308
Linux Kernel 4.19.276
Linux Kernel 5.4 .235
Núcleo de Linux 5.10.173
Núcleo de Linux 5.15.100
Núcleo de Linux 6.1.18
Núcleo de Linux 6.2.5
Núcleo de Linux 6.3

2.7 Vulnerabilidad de escalada de privilegios del kernel de Linux (CVE-2023-0386)

Código de vulnerabilidad: CVE-2023-0386
Descripción de la vulnerabilidad: Se encontró una falla en el kernel de Linux Se encontró acceso no autorizado a la ejecución de un archivo setuid funcional en el subsistema OverlayFS del kernel de Linux Los archivos se copian de un montaje nosuid a otro . Este error de asignación de uid permite a los usuarios locales elevar sus privilegios en el sistema.
Rango de impacto de la vulnerabilidad: linux kernel v2.6.12-rc2 a v6.2-rc6
Medidas de reparación: La vulnerabilidad ha sido reparada, https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux. git/commit/?id=4f11ada10d0ad3fd53e2bd67806351de63a4f9c3
Dirección de descarga: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/refs/, parche fs/overlayfs/copy_up.c
inserte la descripción de la imagen aquí

2.8 Vulnerabilidad de escalada de privilegios del kernel de Linux (CVE-2023-32233)

Código de vulnerabilidad: CVE-2023-32233
Descripción de la vulnerabilidad: existe una vulnerabilidad UAF en el kernel de Linux Netfilter nf_tables, que se puede explotar con éxito para lograr una escalada de privilegios local.
Rango de impacto de la vulnerabilidad: v5.1-rc1 <= Linux Kernel <= 6.3.1
Medidas de reparación: La vulnerabilidad ha sido corregida, enlace de referencia: https://github.com/torvalds/linux/commit/c1592a89942e9678f7d9c8030efa777c0d57edab; patch include/ net /netfilter/nf_tables.h y net/netfilter/nf_tables_api.c
, net/netfilter/nft_dynset.c, net/netfilter/nft_lookup.c, net/netfilter/nft_objref.c total de 5 paquetes de parches:
inserte la descripción de la imagen aquí

3. Parches del sistema operativo Linux

inserte la descripción de la imagen aquí

3.1 Proceso de reparación de parches

Con respecto a la aplicación de parches al kernel, dado que hay muchos códigos fuente del kernel de Linux, cuando se modifica el kernel y se lanza un nuevo kernel, generalmente se lanza en forma de parche, en lugar de todo el kernel empaquetado y lanzado.

1) Generar un parche

En Linux, podemos usar el comando Patch para parchear el código para corregir errores, vulnerabilidades, etc., y ayudar a los usuarios a actualizar y corregir algunas vulnerabilidades de seguridad en el kernel de Linux; mientras que el archivo de parche se genera usando el comando diff, el comando diff Su función es comparar las diferencias entre dos archivos línea por línea y luego enviar los resultados de la comparación al archivo de parche . También puede usar el comando Diffstat para comparar atributos; el formato del comando para generar un archivo de parche es el siguiente:

Formato de gramática:

diff [Opciones] Archivo de origen (carpeta) Archivo de destino (carpeta) #Es parchear el archivo de origen (carpeta) para convertirlo en un archivo de destino (carpeta), el término se llama "actualizar".

diff -uNr  oldfile   newfile > patch_file.patch

Análisis de parámetros:

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

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

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

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

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

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

Nota: La función del comando patch es comparar todos los archivos del archivo de origen (carpeta) y el archivo de destino (carpeta) uno por uno, y registrar la información de diferencia en patch_file.patch. El contenido del archivo de parche se explica a continuación:

※ Parte del encabezado del parche:

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

※ Parte del bloque ( @@representa el comienzo de un bloque):

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

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

※ Texto:

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

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

※ Por ejemplo, las siguientes notas del parche:

inserte la descripción de la imagen aquí
2) parche

A menudo, los archivos de parche son publicados por el funcionario, y podemos parchear directamente el contenido del archivo de parche publicado en nuestro propio código a través del comando de parche, es decir, completar la actualización del código. El formato del comando de parche es el siguiente (aquí solo se presenta la operación de parche en el archivo de origen (carpeta)):

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   #打补丁

Análisis de parámetros:

pN: El directorio de nivel N debe ignorarse al aplicar parches.
-R: Indica que el archivo "nuevo" y el archivo "antiguo" en el archivo del parche deben ser reemplazados (en realidad equivalente a parchear la nueva versión para convertirla en una versión anterior) -E: Si se encuentra un archivo vacío en la tabla
, solo bórralo

Ejemplo: si el archivo de parche contiene el nombre de ruta /net/packet/af_packet.c, entonces:

-p 0 Use el nombre completo de la ruta; por lo tanto, generalmente se recomienda no usar una ruta absoluta al usar el comando diff para hacer un parche, de lo contrario, debe contar desde el directorio raíz hasta qué nivel se encuentra actualmente al aplicar el parche. p 1 Elimine la barra inclinada inicial y
deje Descargar net/packet/af_packet.c.
-p 3 Elimina la barra diagonal inicial y los dos primeros directorios, dejando af_packet.c.

Ejemplo: Usando las instrucciones de la figura anterior, al ejecutar: diff --git a/net/packet/af_packet.c b/net/packet/af_packet.cel resultado es el siguiente:

--- 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 &&

Descripción: El encabezado del parche se compone de ---/+++dos líneas al principio, que se utilizan para indicar los archivos a parchear. ---El comienzo indica el archivo antiguo y el comienzo de +++ indica el nuevo archivo. Un archivo de parche puede contener muchas secciones que comienzan con —/+++, y cada sección se usa para aplicar un parche. Se pueden incluir tantos parches en un archivo de parche.

Si se usa el parámetro -p0, significa encontrar una carpeta llamada a del directorio actual y buscar el archivo af_packet.c en net/packet/ para realizar la operación de parche.

Si se usa el parámetro -p1, significa ignorar el directorio de primer nivel (es decir, independientemente de a), buscar la carpeta net/packet/ del directorio actual y encontrar af_packet.c debajo de ella. La premisa de esto es que el directorio actual debe ser el directorio donde se encuentra a. El archivo de parche de diferencia puede estar en cualquier ubicación , siempre que se especifique la ruta del archivo de parche de diferencia. Por supuesto, puede usar rutas relativas o rutas absolutas.

3) Instalación, compilación y aplicación de parches del kernel de Linux
inserte la descripción de la imagen aquí

#下载内核
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   

Para obtener más información sobre la actualización y compilación del kernel de Linux, consulte: Actualización del sistema Linux y actualización de la versión del kernel ;

4. Apéndice

4.1 Descripción del archivo de compilación del kernel

1) archivo .config

Se usa para usar el archivo de configuración del kernel generado por make menuconfig para decidir si compilar cada sistema funcional del kernel en el kernel o compilarlo en un módulo o no compilarlo.

2)vmlinuz y vmlinux

vmlinuz es el kernel comprimido de arranque, "vm" significa "Memoria virtual". Linux admite memoria virtual A diferencia de los sistemas operativos antiguos como DOS, que tienen un límite de memoria de 640 KB, Linux puede usar el espacio del disco duro como memoria virtual, de ahí el nombre "vm". vmlinuz es un kernel de Linux ejecutable . Hay dos formas de compilar vmlinuz : una es crearlo a través de "make zImage" al compilar el kernel. zImage es adecuado para kernels pequeños y su existencia es por compatibilidad con versiones anteriores; la otra es el kernel Creada por comandos durante la compilación make bzImage, bzImage es una imagen del kernel comprimida . Nota: bzImage no está comprimida con bzip2. La bz en bzImage es fácil de causar malentendidos. bz significa "gran zImage", y b en bzImage significa "grande". Tanto zImage(vmlinuz) como bzImage(vmlinuz) son 用gzip压缩. No solo son un archivo comprimido, sino que hay un código de descompresión gzip incrustado al comienzo de ambos archivos, por lo que no puede descomprimir vmlinuz con gunzip o gzip --dc. El archivo del kernel contiene un pequeño gzip que descomprime el kernel y lo inicia. La diferencia entre los dos es que el antiguo zImage descomprime el kernel en la memoria de gama baja (los primeros 640 K) y bzImage descomprime el kernel en la memoria de gama alta (más de 1 M). Si el kernel es relativamente pequeño, se puede usar uno de zImage o bzImage, y el sistema que se ejecuta en las dos formas es el mismo. Los núcleos grandes usan bzImage, no zImage. vmlinu x es el núcleo sin comprimir, vmlinu z es el archivo comprimido de vmlinux.

3) initrd.img
initrd es la abreviatura de "ramdisk inicial". initrd generalmente se usa para iniciar temporalmente el hardware a un estado en el que el kernel real vmlinuz puede tomar el control y continuar iniciando. Por ejemplo, initrd-2.4.7-10.img se usa principalmente para cargar sistemas de archivos como ext3 y controladores para dispositivos scsi. Si está utilizando un disco duro scsi y no hay un controlador de hardware scsi en el kernel vmlinuz, el kernel no puede cargar el sistema de archivos raíz antes de cargar el módulo scsi, pero el módulo scsi se almacena en /lib/modules del archivo raíz sistema. Para resolver este problema, puede arrancar un kernel initrd que pueda leer el kernel real y usar el initrd para corregir el problema de arranque scsi.El initrd-2.4.7-10.img es un archivo comprimido con gzip. El archivo de imagen initrd se mkinitrdcrea usando la utilidad mkinitrd para crear un archivo de imagen initrd Este comando es propiedad de RedHat y otras distribuciones de Linux pueden tener comandos correspondientes. Ver ayuda para más: man mkinitrd

4) System.map
System.map es una tabla de símbolos del kernel para un kernel específico, generada por "nm vmlinux" y los símbolos irrelevantes se filtran. Las siguientes líneas son de /usr/src/linux-2.4/Makefile:

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

Al programar, se nombran símbolos como nombres de variables o nombres de funciones. El kernel de Linux es un bloque de código muy complejo con muchos símbolos globales. El kernel de Linux no usa nombres de símbolos, pero usa direcciones de variables o funciones para identificar variables o nombres de funciones. Por ejemplo, en lugar de usar símbolos como size_t BytesRead, En su lugar, haga referencia a esta variable como c0343f20. Para los informáticos, prefiera nombres como size_t BytesRead a aquellos como c0343f20. El kernel está escrito principalmente en C , por lo que el compilador/enlazador nos permite usar nombres de símbolos al codificar y direcciones cuando se ejecuta el kernel. Sin embargo, en algunos casos, necesitamos saber la dirección de un símbolo, o el símbolo correspondiente a la dirección, esto se hace mediante la tabla de símbolos, que es una lista de todos los símbolos junto con sus direcciones.

La tabla de símbolos de Linux utiliza 2 archivos : /proc/ksyms y System.map. /proc/ksymses un "archivo proc", creado cuando se inicia el núcleo . De hecho, no es realmente un archivo, es solo una representación de los datos del núcleo, pero le da a la gente la ilusión de un archivo de disco, que se puede ver por su tamaño de archivo de 0 . Sin embargo, System.mapson archivos reales que existen en su sistema de archivos. Cuando compila un kernel nuevo, la dirección de cada nombre de símbolo cambiará y su antiguo System.map tiene información de símbolo incorrecta.Cada vez que se compila un kernel, se genera un nuevo System.map, y debe usar el nuevo System. map para reemplazar el antiguo System.map.

Aunque el kernel en sí no usa System.map, otros programas como klogd, lsof y ps requieren un System.map correcto. Si usa System.map incorrecto o no lo usa, la salida de klogd no será confiable, lo que puede dificultar la solución de problemas del programa. Sin System.map, es posible que se enfrente a algunas indicaciones molestas. Algunos otros controladores requieren un System.map para resolver los símbolos y no funcionarán correctamente sin un System.map creado para el núcleo particular que está ejecutando.

Para realizar la resolución de nombre y dirección, el demonio de registro del kernel de Linux klogd necesita usar System.map. System.map debe colocarse donde el software que lo utiliza pueda encontrarlo. Ejecución: man klogd muestra que si System.map no se proporciona a klogd como una ubicación variable, comprobará System.map en tres lugares en el siguiente orden: /boot/System.map, /System.map, /usr/ src/linux/System.map
System.map también tiene información de versión, y klogd puede encontrar inteligentemente el archivo de imagen (mapa) correcto.

4.2, hacer el proceso menuconfig

Cuando ejecutamos el comando make menuconfig, ¿qué hace exactamente el sistema por nosotros? Hay un total de los siguientes archivos involucrados:

1. La carpeta de scripts en el directorio raíz del kernel de Linux; la carpeta de scripts almacena archivos relacionados con el dibujo de gráficos de la interfaz de configuración de make menuconfig. Como usuario, no necesitamos preocuparnos por el contenido de esta carpeta. 2. arch/$ARCH/Kconfig

, el archivo Kconfig en el directorio de cada capa

3. el archivo makefile en el directorio raíz del kernel de Linux, el archivo makefile en el directorio de cada capa

4. el archivo .config en el directorio raíz del kernel de Linux, el archivo en archivo arch/$ARCH/configs/

5 .include/generated/autoconf.h en el directorio raíz del kernel de Linux

inserte la descripción de la imagen aquí
Antes de que ejecutemos el comando make menuconfig y aparezca la siguiente interfaz de configuración, el sistema ha realizado el siguiente trabajo por nosotros:

Primero, el sistema leerá el archivo Kconfig en el directorio arch/$ARCH/ para generar todas las opciones de interfaz de configuración (Kconfig es el núcleo de todo el mecanismo de configuración de Linux), entonces, ¿cuál es el valor de la variable de entorno ARCH? Está determinado por el archivo MAKE en el directorio raíz del kernel de Linux , y hay una definición de esta variable de entorno en el archivo MAKE:

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   ?=

Por ejemplo, si la interfaz de configuración es generada por el comando make ARCH=arm menuconfig, el sistema leerá el archivo arm/arm/kconfig para generar opciones de configuración.

En segundo lugar, algunas de sus opciones de configuración predeterminadas se almacenan en el directorio arch/$ARCH/configs/, que es la carpeta arch/arm/configs para arm. Hay muchas opciones en esta carpeta, ¿cuál leerá el sistema? De manera predeterminada, el kernel leerá el archivo .config en el directorio raíz del kernel de Linux como la opción predeterminada del kernel. Podemos optar por modificar el archivo .config directamente y ejecutar el comando make menuconfig para leer las nuevas opciones. Pero generalmente este no es el caso.En la interfaz de configuración de menuconfig, podemos seleccionar ciertas opciones para seleccionarlas o no seleccionarlas a través de espacio, esc y retorno de carro.Al guardar y salir, el kernel de Linux actualizará las nuevas opciones a .config En este punto, podemos renombrar .config a otro archivo y guardarlo (el sistema borrará el archivo .config al ejecutar make distclean), y no necesitamos ir a arch/arm/configs para obtener el archivo correspondiente cuando configuremos el kernel en el futuro Sí, ahórrese el problema de la reconfiguración, solo copie el archivo .config guardado como un archivo .config para cargar.

A través de los dos pasos anteriores, podemos leer y configurar correctamente la interfaz que necesitamos, entonces, ¿cómo establecen una relación de compilación con el archivo MAKE? Cuando guarde la opción make menuconfig, el sistema no solo actualizará automáticamente el .config, sino que también guardará todas las opciones en forma de macro en el archivo include/generated/autoconf.h en el directorio raíz del kernel de Linux. El código fuente en el kernel serán estos archivos .h y se compilarán condicionalmente de acuerdo con la definición de la macro. Cuando necesitamos elegir si compilar un archivo como un todo, también necesitamos modificar el makefile correspondiente, por ejemplo: cuando
inserte la descripción de la imagen aquí
elegimos si compilar el archivo s3c2410_ts.c, el makefile decidirá si compila este archivo de acuerdo con CONFIG_TOUCHSCREEN_S3C2410 Esta macro está en Kconfig Definida en el archivo , cuando completemos la configuración, aparecerá en .config y autconf.Hasta ahora, hemos completado el proceso de compilación de todo el kernel de Linux. Al final, encontraremos que durante todo el proceso de configuración del kernel de Linux, la interfaz que le queda al usuario es en realidad solo el Kconfig, los archivos makefile y los archivos fuente correspondientes de cada capa .

Por ejemplo, si queremos agregar una función al kernel y controlar su proceso de reclamo a través de make menuconfig, lo primero que debemos hacer es: modificar el archivo Kconfig en el directorio correspondiente y agregar las opciones correspondientes de acuerdo con la sintaxis de Kconfig. ; en segundo lugar, ejecute make menuconfig para elegir compilar en el kernel Ya sea que no esté compilado en el kernel o compilado en un módulo, el archivo .config y el archivo autoconf.h se generarán automáticamente; finalmente, modifique el archivo MAKE en el directorio correspondiente para completar la adición de opciones de compilación, finalmente ejecute el comando make para compilar.

4.3, configuración y Makefile

Hay dos documentos, Kconfig y Makefile, en cada directorio del árbol de fuentes del kernel de Linux . El Kconfig distribuido a cada directorio constituye una base de datos de configuración del núcleo distribuida , y cada Kconfig describe el menú de configuración del núcleo relacionado con el documento fuente del directorio al que pertenece . Al ejecutar la configuración del kernel make menuconfig, el menú se lee desde Kconfig, y el usuario lo selecciona y lo guarda en el archivo de configuración del kernel de **.config**. Cuando se compila el kernel, el Makefile llama al archivo .config y se conoce la elección del usuario. Este contenido muestra que Kconfig es el menú de configuración correspondiente a cada nivel del kernel.

Si desea agregar un nuevo controlador al código fuente del kernel, debe modificar Kconfig para que pueda seleccionar este controlador.Si desea que este controlador se compile , debe modificar Makefile. Hay dos tipos de documentos que deben modificarse al agregar un nuevo controlador (si agrega solo archivos, solo necesita modificar los archivos Kconfig y Makefile de la capa actual; si agrega un directorio, necesita modificar un par de Kconfig y Makefile bajo la capa y el directorio actuales Makefile) Kconfig y Makefile. Si desea saber cómo modificar estos dos documentos, necesita conocer la estructura gramatical de los dos documentos. Para conocer la gramática de Kconfig, consulte la referencia "[linux-2.6.31] kbuild".
Makefile consta de 5 partes:

archivo del núcleo ilustrar
Makefile Makefile de nivel superior
.config archivo de configuración del núcleo
arch/$(ARCH)/Makefile Archivo de arquitectura
guiones/Makefile.* Reglas comunes que se aplican a todos los Makefiles de kbuild, etc.
kbuild Makefiles Hay alrededor de 500 archivos de este tipo.

El Makefile de nivel superior lee la configuración del kernel y genera el archivo .config El Makefile de nivel superior crea dos objetivos principales: vmlinux (imagen del kernel) y módulos (todos los archivos de módulos). Construye estos objetivos visitando recursivamente subdirectorios bajo el árbol de fuentes del núcleo. Los subdirectorios a los que se accede dependen de la configuración del núcleo. El Makefile de nivel superior contiene un Makefile de arquitectura, especificado por arch/$(ARCH)/Makefile. Los Makefiles de arquitectura proporcionan información específica de la arquitectura al Makefile de nivel superior. Cada subdirectorio tiene un archivo kbuild y un archivo Makefile para ejecutar los comandos transmitidos desde la capa superior. Los archivos kbuild y Makefile usan la información en el archivo .config para construir listas de varios archivos usados ​​por kbuild para construir objetos integrados o módulos. scripts/Makefile.* contiene todas las definiciones/reglas, etc. Esta información se usa para construir el kernel usando kbuild y Makefile.

Nota: independientemente del extracto de http://blog.chinaunix.net/uid-26497520-id-3593098.html#0

4.3 Referencia de la escena de parcheo del kernel de Linux

1) Actualice 2.6.23.11 a 2.6.23.12. Primero debo revertir 2.6.23.11 a 2.6.23 y luego parchear 2.6.23.12:

bzcat …/parche-2.6.23.11.bz2|patch -p1 -R #volver a 2.6.23
bzcat …/patch-2.6.23.12.bz2|patch -p1 #llegar a 2.6.23.12

2) 2.6.22.9 primero debe ser degradado a 2.6.22 y luego actualizado a 2.6.23 y luego actualizado a 2.6.23.9

bzcat …/patch-2.6.22.9.bz2|patch -p1 -R #Use el comando R para cancelar el parche. De esta forma bajaremos de 22.9 a 22
zcat …/patch-2.6.23.gz|patch -p1 #Esto actualizará a 2.6.23
zcat …/patch-2.6.23.11.bz2|patch -p1 # Esto actualizará a 2.6 .23.11 Esta es la última versión estable

4.4, hacer defconfig, hacer menuconfig, hacer saveefconfig, hacer olddefconfig, hacer localmodconfig 区别

1) make defconfig

  primero genera el .config inicial a través de make xxx_defconfig, que es equivalente a copiar el archivo XXX_defconfig en un archivo .config, donde defconfig es el elemento de configuración más pequeño y la compilación del kernel compilará el controlador de acuerdo con el archivo .config , después de cargar Después del comando, el siguiente make menuconfig configurará la configuración en función del .config actual;

2) make menuconfig

  La función de make menuconfig (interfaz de imagen, basada en la biblioteca ncurses) es similar a la de make config (este último es un diálogo de tipo texto), que consiste en configurar el archivo de configuración en función de la interfaz. de make config es cargar ".config" como configuración por defecto, configurarlo equivale a configurar el archivo .config con una interfaz gráfica;

3) make Savedefconfig

  Ejecute make saveconfig para generar el archivo defconfig más pequeño ejecutando .config;

4) make olddefconfig

  usa make oldconfig para verificar el .config del elemento de configuración recién agregado para verificar la dependencia y regenerar un nuevo archivo .config, y la diferencia entre el .config recién generado y el anterior es que el antiguo .config se renombra a .config.archivo antiguo. diffconfig .config.old .configPuede comparar la diferencia entre las configuraciones del kernel antiguo y el nuevo ejecutando
5) make localmodconfig

  a través de make localmodconfig ejecutará el comando lsmod para verificar qué módulos (módulos) están cargados en el sistema actual y, finalmente, eliminar los módulos innecesarios en el original. config, solo mantenga estos módulos del lsmod anterior, lo que simplifica el proceso de configuración del kernel y se usa principalmente en escenarios de prueba rápida. Desventaja: este método solo puede hacer que el núcleo compilado admita los módulos que se han cargado en el núcleo actual, y los módulos que no se han utilizado actualmente no se compilarán en el núcleo posterior; Ventajas: el núcleo compilado es pequeño y rápido .

"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.

Supongo que te gusta

Origin blog.csdn.net/ximenjianxue/article/details/131973515
Recomendado
Clasificación