[問題] kernel module 區域變數記憶體
大家好,想請問kernel module的function中array of struct與struct的記憶體配置方式
是不是不一樣(變數為函數中直接宣告,未使用kmalloc)?會這樣問是因為最近在寫作業時
遇到使用copy_to_user複製一段記憶體內容到userspace時只要複製的內容是array of
struct就會panic,log如下:
usercopy: kernel memory exposure attempt detected from 00000000e7ee16e5
(<process stack>) (16 bytes)
但只要把原本要複製的內容放到同個資料結構的struct中就可以正常copy...,以下是複
時用到的資料結構:
struct U64 {
unsigned long long msl;
unsigned long long lsl;
};
然後餵給copy_to_user的arg(size)都一樣是16 bytes。目前推測array of struct配置的
成員記憶體是不連續的,可是kernelspace的virtual address讓我在debug時看到的記憶
體都是不連續的(array of struct與struct),所以不確定這樣推測是否正確。
不知道各位前輩有什麼看法,謝謝大家!
**更新**(補上程式碼),以下為可以正常運作的程式碼,原本有問題的版本是使用fib(ar
ra
of struct)做複製(copy_to_user(buf, &fib[g - 1], size)),另外,size一直都是16
bytes:
static long long fib_sequence(long long g, char *buf, size_t size)
{
unsigned long long a;
a = 10000000000000000000;
struct U64 fib[g + 1], tmp = {0};
memset(fib, 0, sizeof(struct U64) * (g + 1));
int k;
fib[0].lsl = 1;
fib[1].lsl = 1;
for (k = 2; k <= g; k++) {
fib[k].lsl = fib[k - 1].lsl + fib[k - 2].lsl;
fib[k].msl = fib[k - 1].msl + fib[k - 2].msl;
if (fib[k].lsl > a) {
fib[k].lsl = fib[k].lsl - a;
fib[k].msl = fib[k].msl + 1;
}
}
tmp = fib[g - 1];
copy_to_user(buf, &tmp, size);
return 1;
}
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 49.213.161.228
※ 文章網址: https://www.ptt.cc/bbs/LinuxDev/M.1553628544.A.D7C.html
※ 編輯: dces4212 (49.213.161.228), 03/27/2019 03:40:15
→
03/27 16:17,
5年前
, 1F
03/27 16:17, 1F
→
03/27 16:18,
5年前
, 2F
03/27 16:18, 2F
→
03/27 20:41,
5年前
, 3F
03/27 20:41, 3F
→
03/27 20:41,
5年前
, 4F
03/27 20:41, 4F
※ 編輯: dces4212 (140.128.72.6), 03/27/2019 20:54:24
→
03/28 00:17,
5年前
, 5F
03/28 00:17, 5F
→
03/28 00:28,
5年前
, 6F
03/28 00:28, 6F
→
03/28 00:29,
5年前
, 7F
03/28 00:29, 7F
→
03/28 00:35,
5年前
, 8F
03/28 00:35, 8F
→
03/28 00:35,
5年前
, 9F
03/28 00:35, 9F
→
03/28 00:49,
5年前
, 10F
03/28 00:49, 10F
→
03/28 00:50,
5年前
, 11F
03/28 00:50, 11F
→
03/28 00:51,
5年前
, 12F
03/28 00:51, 12F
→
03/28 00:51,
5年前
, 13F
03/28 00:51, 13F
只要用array of struct當copy_to_user()的arg就一次都沒成功過(g範圍是0~100),但只
要單用struct就不會出問題。會考慮kmalloc的,感謝。目前推測觸發BUG()的地方是這裡
(因為就連g很小的時候都有問題,就不太可能是#L50的檢查了)
(https://elixir.bootlin.com/linux/v4.15.18/source/mm/usercopy.c#L54),#L54做的
檢查其實看不太懂,#L50已經檢查過是否要複製的範圍在stack內,不知道這個是不是檢
查是否為stack內可存取的記憶體,註解寫的if object is safely感覺又不太像這意思,
不知道大大有啥看法。
※ 編輯: dces4212 (49.213.161.228), 03/28/2019 01:13:03
→
03/28 10:52,
5年前
, 14F
03/28 10:52, 14F
→
03/28 10:52,
5年前
, 15F
03/28 10:52, 15F
→
03/28 13:24,
5年前
, 16F
03/28 13:24, 16F
→
03/28 13:32,
5年前
, 17F
03/28 13:32, 17F
→
03/28 15:56,
5年前
, 18F
03/28 15:56, 18F
了解!
[ 4167.013170] usercopy: kernel memory exposure attempt detected from
00000000e7ee16e5 (<process stack>) (16 bytes)
[ 4167.013177] ------------[ cut here ]------------
[ 4167.013178] kernel BUG at
/build/linux-7kdHqT/linux-4.15.0/mm/usercopy.c:72!
[ 4167.013183] invalid opcode: 0000 [#1] SMP PTI
[ 4167.013184] Modules linked in: fibdrv(OE)....(已省略)
[ 4167.013262] CPU: 1 PID: 16325 Comm: client Tainted: G W OE
4.15.0-46-generic #49-Ubuntu
[ 4167.013263] Hardware name: ASUSTeK COMPUTER INC. UX430UN/UX430UN, BIOS
UX430UN.302 11/28/2017
[ 4167.013268] RIP: 0010:__check_object_size+0x123/0x1b0
[ 4167.013269] RSP: 0018:ffffbc64858f7e08 EFLAGS: 00010286
[ 4167.013271] RAX: 0000000000000064 RBX: 0000000000000010 RCX:
0000000000000006
[ 4167.013273] RDX: 0000000000000000 RSI: 0000000000000092 RDI:
ffff9ac0eec96490
[ 4167.013274] RBP: ffffbc64858f7e28 R08: 0000000000000000 R09:
0000000000001831
[ 4167.013275] R10: 0000000000000000 R11: ffffffffaff5380d R12:
0000000000000001
[ 4167.013276] R13: ffffbc64858f7e38 R14: ffffbc64858f7e28 R15:
1ffff78c90b1efc7
[ 4167.013278] FS: 00007ff1e9d3d500(0000) GS:ffff9ac0eec80000(0000)
knlGS:0000000000000000
[ 4167.013279] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 4167.013281] CR2: 00007fffc3d96080 CR3: 00000003d28fe006 CR4:
00000000003606e0
[ 4167.013282] Call Trace:
[ 4167.013288] fib_read+0x159/0x197 [fibdrv]
[ 4167.013290] ? fib_read+0x34/0x197 [fibdrv]
[ 4167.013293] __vfs_read+0x1b/0x40
[ 4167.013294] vfs_read+0x8e/0x130
[ 4167.013296] SyS_read+0x55/0xc0
[ 4167.013300] do_syscall_64+0x73/0x130
[ 4167.013303] entry_SYSCALL_64_after_hwframe+0x3d/0xa2
[ 4167.013305] RIP: 0033:0x7ff1e9861081
[ 4167.013306] RSP: 002b:00007fffc3d51638 EFLAGS: 00000246 ORIG_RAX:
0000000000000000
[ 4167.013308] RAX: ffffffffffffffda RBX: 0000000000000000 RCX:
00007ff1e9861081
[ 4167.013309] RDX: 0000000000000010 RSI: 00007fffc3d51650 RDI:
0000000000000003
[ 4167.013310] RBP: 00007fffc3d516a0 R08: 00007ff1e9b3dd80 R09:
00007ff1e9b3dd80
[ 4167.013311] R10: 00007fffc3d51620 R11: 0000000000000246 R12:
000055f6d8e947c0
[ 4167.013313] R13: 00007fffc3d51780 R14: 0000000000000000 R15:
0000000000000000
[ 4167.013314] Code: 48 0f 45 d1 48 c7 c6 53 f2 6d af 48 c7 c1 ef ff 6e af 48
0f 45 f1 49 89 d9 49 89 c0 4c 89 f1 48 c7 c7 f8 ff 6e af e8 fd dd e7 ff <0f>
0b f3 c3 48 8b 3d 82 18 1a 01 48 8b 0d 13 99 1d 01 be 00 00
[ 4167.013369] RIP: __check_object_size+0x123/0x1b0 RSP: ffffbc64858f7e08
※ 編輯: dces4212 (49.213.161.228), 03/28/2019 21:31:09
→
03/28 21:32,
5年前
, 19F
03/28 21:32, 19F
→
03/31 04:31,
5年前
, 20F
03/31 04:31, 20F
推
03/31 10:04,
5年前
, 21F
03/31 10:04, 21F
→
03/31 10:06,
5年前
, 22F
03/31 10:06, 22F
→
03/31 10:09,
5年前
, 23F
03/31 10:09, 23F
→
03/31 10:10,
5年前
, 24F
03/31 10:10, 24F
推
03/31 10:11,
5年前
, 25F
03/31 10:11, 25F
推
03/31 10:13,
5年前
, 26F
03/31 10:13, 26F
→
03/31 10:14,
5年前
, 27F
03/31 10:14, 27F
→
03/31 10:33,
5年前
, 28F
03/31 10:33, 28F
→
03/31 10:38,
5年前
, 29F
03/31 10:38, 29F
→
03/31 10:44,
5年前
, 30F
03/31 10:44, 30F
→
03/31 10:47,
5年前
, 31F
03/31 10:47, 31F
→
03/31 10:54,
5年前
, 32F
03/31 10:54, 32F
→
03/31 11:01,
5年前
, 33F
03/31 11:01, 33F
→
03/31 11:03,
5年前
, 34F
03/31 11:03, 34F
→
03/31 11:03,
5年前
, 35F
03/31 11:03, 35F
→
03/31 11:05,
5年前
, 36F
03/31 11:05, 36F
發現有意思的地方了...,g=0的時候只要用tmp=fib[-1]再把tmp餵給copy_to_user就不會
觸發BUG(),但假如直接餵fib[-1]給copy_to_user就會panic。推測先餵給tmp這邊沒有檢
查是否非法存取所以沒事(目前在userspace測試只能往後拿到6KB左右的資料,之後就被
seg fault了,而kernel space是比較有趣的地方,只要我不把往後拿拿到的資料餵給
copy_to_user,我往後-20000 * 16 byte (struct大小為16bytes)都可以拿到,但假如要
傳到userspace我只能在stack frame(16KB)內偷資料,只要超過就會被panic,這邊很怪
的
地方是kernel怎知道我這tmp裡面偷拿了甚至超過stack frame(16KB)的資料,目前猜測是
kernel 自己有個trap之類的機制隨時在監測是否有access violation)。
另外我是用GCC編譯的。
感謝兩位大大,讓我知道根本不是array of struct跟struct記憶體配置差別,是我自己
在copy_to_user面前非法存取了哈哈。
※ 編輯: dces4212 (49.213.161.228), 03/31/2019 21:25:14
→
03/31 21:27,
5年前
, 37F
03/31 21:27, 37F
→
03/31 21:28,
5年前
, 38F
03/31 21:28, 38F
忘記補充一點,剛剛測試發現當g=0的時候我對fib[0]賦值後再使用copy_to_user會發生
copy失敗的問題(copy_to_user回傳了16 bytes),蠻怪的..,g>0後都可以正常複製。
※ 編輯: dces4212 (49.213.161.228), 03/31/2019 22:05:31
推
04/04 12:11,
5年前
, 39F
04/04 12:11, 39F
→
04/04 12:12,
5年前
, 40F
04/04 12:12, 40F
→
04/04 12:12,
5年前
, 41F
04/04 12:12, 41F
→
04/04 12:13,
5年前
, 42F
04/04 12:13, 42F
程式碼幾乎一樣,一開始是發現g=0時userspace拿到的資料是0(應為1,fib[0]=1),這時
候覺得很奇怪所以就加個if(g=0) {printk(當下的fib[0].msl, lsl 還有copy_to_user的
ret val)},然後發現fib在kernelspace是有拿到1的,還有copy_to_user的ret是16(複製
失敗大小,成功應為0),差不多是這樣。手機排版,sorry.
※ 編輯: dces4212 (101.10.82.251), 04/05/2019 16:00:31
推
04/09 13:07,
5年前
, 43F
04/09 13:07, 43F
→
04/09 13:08,
5年前
, 44F
04/09 13:08, 44F
→
04/09 13:08,
5年前
, 45F
04/09 13:08, 45F
→
04/09 13:12,
5年前
, 46F
04/09 13:12, 46F
沒錯,fib[1].lsl=1;這段每次都會執行到。剛測試了一下,發現確實是這個assigment去
改到buf的內容,會確定的原因挺詭異的,我最先是在assigment前後放printk看buf的內
容,然後只要我保留那段assigment,我新加的printk就會導致panic,而一旦我把那段
assigment 移掉,printk就正常印出位置了...,看來是非法寫入後又嘗試讀取相關記憶
體導致的,這跟之前說tmp偷到的資料只要不copy_to_user就沒事有差不多的概念..,挺
好奇kernel是怎做這個檢查的..,因為這不是直接觸發BUG(),不知道y大有什麼看法?
感謝大大!
※ 編輯: dces4212 (49.213.161.228), 04/12/2019 03:10:28
※ 編輯: dces4212 (49.213.161.228), 04/12/2019 03:11:12
推
04/16 20:26,
5年前
, 47F
04/16 20:26, 47F
→
04/16 20:27,
5年前
, 48F
04/16 20:27, 48F
→
04/16 20:28,
5年前
, 49F
04/16 20:28, 49F
了解,感謝y大。
用的參數是%p, &fib[1].lsl 及 &buf 都落在0x0~0xffffffff間(多次測試)
→
04/24 20:54,
5年前
, 50F
04/24 20:54, 50F
→
04/24 20:55,
5年前
, 51F
04/24 20:55, 51F
→
04/24 20:56,
5年前
, 52F
04/24 20:56, 52F
→
04/24 20:57,
5年前
, 53F
04/24 20:57, 53F
感謝z大提醒,這是作業,預期是會有不同項的費氏數列輸入,並且在計算過程中一一印
出每一項的結果,其實也可以不用VLA來實做的。
※ 編輯: dces4212 (49.213.161.228), 04/26/2019 05:02:50
※ 編輯: dces4212 (101.9.132.120), 04/26/2019 05:15:12
→
04/26 05:23,
5年前
, 54F
04/26 05:23, 54F
→
04/26 05:23,
5年前
, 55F
04/26 05:23, 55F
→
04/26 05:23,
5年前
, 56F
04/26 05:23, 56F
→
04/26 05:24,
5年前
, 57F
04/26 05:24, 57F
LinuxDev 近期熱門文章
PTT數位生活區 即時熱門文章
8
14