[問題] kernel module 區域變數記憶體

作者: dces4212 (flawless)   2019-03-27 03:28:57
大家好,想請問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;
}
作者: wens (文思)   2019-03-27 16:17:00
array 是 struct xxx XXX[N] 宣告? copy_to_user 呼叫方法呢要問 code 就要把 code 貼出來,不要請人隔空抓藥...
作者: dces4212 (flawless)   2019-03-27 20:41:00
抱歉 原本想說只是個很直觀的array of struct跟struct的配置差別 所以就沒貼上來,等等補上!
作者: wens (文思)   2019-03-28 00:17:00
不太相干的事情: 不要用 VLA, 很容易爆 stack
作者: dces4212 (flawless)   2019-03-28 00:28:00
有爆過了哈哈 慘死 要做完整應該會根據資料結構算個上限16 KB真的不小心就爆掉..,只是現在遇到這問題實在不解.
作者: wens (文思)   2019-03-28 00:35:00
你出現錯誤的時候 g 是多少? 我覺得可能是你 stack 爆了去踩到 text section ...看 mm/usercopy.c 應該是沒大到踩到 text section 不然錯誤訊息不太一樣,而且中間踩到 unmapped page 應該會先炸看起來像是 x86 上超出 stack frame 之類的乖乖用 kmalloc 吧對吼... 應該要請你附 backtrace 跟解析過的行數才對XDarch_within_stack_frames 好像 x86 才有實作
作者: dces4212 (flawless)   2019-03-28 13:24:00
backtrace 是指 call stack 跟dump出的register那些嗎應該是只有x86有這實作 arch/下只看到x86
作者: wens (文思)   2019-03-28 15:56:00
對啊 # backtrace 是指 call stack 跟dump出的register
作者: dces4212 (flawless)   2019-03-28 21:32:00
補充一下,copy_to_user只有在fib__sequence用到
作者: xam (聽說)   2019-03-31 04:31:00
struct U64 fib[g + 1] 為什麼你這樣寫編譯會過?
作者: yvb   2019-03-31 10:04:00
樓上: google: VLA c99回原PO: 你確認過 wens 在 8 樓的問題了嗎?g=0 時, fib[0-1] => fib[-1] 是該被 usercopy 報 BUG(),但你確定 g=1 到 g=100 也報 BUG() ?
作者: xam (聽說)   2019-03-31 10:11:00
看起來kernel對vla的支援還有點問題https://m.slashdot.org/story/347741
作者: yvb   2019-03-31 10:14:00
另外, 既然for(...k<=g...)算到 fib[g], 為何是回 fib[g-1]?@xam: 嗯,要看原PO用的是gcc還是clang.若是clang也許有問題.又, 原PO用的是4.15, 要4.20才有設-Wvla對VLA給warning.@xam: 又看了一下那篇,指的是struct的member用到VLA有問題,而原PO的VLA是C99-style,所以clang支援.至於第1點, 只是 overhead 問題; 但第3點就不大明暸了...猜測是要做陣列大小檢查(還是直接改用kmalloc乾脆XD).
作者: xam (聽說)   2019-03-31 11:03:00
用了 kmalloc 就是避用 vla 啊
作者: yvb   2019-03-31 11:03:00
是說原PO的 fib[g+1] 其實大小只要 fib[3], 撘配 % 運算即可.
作者: xam (聽說)   2019-03-31 11:05:00
然後我猜直接 struct U64 fib[101] 應該也會正常....
作者: dces4212 (flawless)   2019-03-31 21:27:00
另外我發現我在g=0 時,fib[1].lsl = 1;這段expression也非法存取了.. 只是沒有panic
作者: yvb   2019-04-04 12:11:00
觸發BUG()就是因為arch_within_stack_frames()回傳BAD_STACK.超過16KB被panic: google "虛擬記憶體" "MMU" "分頁表" 幾項.fib[1].lsl = 1 可能寫到其它變數(a,tmp,k), 或變數間有空區.至於 fib[0]賦值後 copy失敗 ==> 程式碼是修改成怎樣?
作者: zack2004 (~夜晚的星空~)   2019-04-24 20:54:00
想知道為什麼原PO要用VLA?目的是什麼?Linux kernel目前已禁用VLA。且從需求來看,這函式不需要不定長度的暫存空間。https://bit.ly/2IJDnyT
作者: dces4212 (flawless)   2019-04-26 05:23:00
忽然想到好像不該用%phttps://www.mjmwired.net/kernel/Documentation/printk-formats.txt用px pK可能比較妥

Links booklink

Contact Us: admin [ a t ] ucptt.com