楼主:
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:00array 是 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:00backtrace 是指 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:00struct 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作者: 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失败 ==> 程式码是修改成怎样?
楼主:
dces4212 (flawless)
2019-04-26 05:23:00