[问题] 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