正在阅读Robert Love的书,第5章关于系统调用,并发现这个简单的例子有点可疑:
asmlinkage long sys_silly_copy(unsigned long *src, unsigned long *dst, unsigned long len)
{
unsigned long buf;
if (copy_from_user(&buf, src, len))
return -EFAULT;
...
}
正如我们所见'buf'是'unsigned long'类型的对象并在内核堆栈上定义,即它的初始值可能是垃圾。无论如何,在buf所在的堆栈中复制'len'字节是有效的,即它可以覆盖有用的东西吗?也许这只适用于这个特定的例子?
答案 0 :(得分:15)
非常有问题。事实上,这是非常危险的。我会在这里给作者带来疑问,因为他们只是试图展示copy_from_user
和copy_to_user
是如何工作的,但他们确实应该提供一个不那么危险的例子。
特别是,因为这本书对你如何必须要格外小心抒情:
系统调用必须仔细验证其所有参数,以确保它们有效并且 合法。系统调用在内核空间运行,如果用户可以将无效输入传入 内核没有约束,系统的安全性和稳定性都会受到影响。
然后为用户提供了一种完全消灭内核的方法: - )
我所说的副本中的文字说明:
让我们考虑使用
copy_from_user()
和copy_to_user()
的示例系统调用。这个系统调用silly_copy()
完全没用;它将数据从其第一个参数复制到第二个参数中。这是次优的,因为它涉及到内核空间的中间和无关副本,无法获得。但它有助于说明这一点。
/*
* silly_copy - pointless syscall that copies the len bytes from
* ‘src’ to ‘dst’ using the kernel as an intermediary in the copy.
* Intended as an example of copying to and from the kernel.
*/
SYSCALL_DEFINE3(silly_copy,
unsigned long *, src,
unsigned long *, dst,
unsigned long len)
{
unsigned long buf;
/* copy src, which is in the user’s address space, into buf */
if (copy_from_user(&buf, src, len))
return -EFAULT;
/* copy buf into dst, which is in the user’s address space */
if (copy_to_user(dst, &buf, len))
return -EFAULT;
/* return amount of data copied */
return len;
}
除了不检查参数的灾难性故障之外,我很确定SYSCALL_DEFINE3
的最后一个参数缺少一个逗号(虽然这只是一个错字)。
一个更好的例子,不必分配任意内存,将是:
SYSCALL_DEFINE3(silly_copy,
unsigned long *, src,
unsigned long *, dst,
unsigned long, len)
{
unsigned long buf[64]; /* Buffer for chunks */
unsigned long lenleft = len; /* Remaining size */
unsigned long chunklen = sizeof(buf); /* Initial chunk length */
/* Loop handling chunk sizes */
while (lenleft > 0) {
/* Change chunk length on last chunk */
if (lenleft < chunklen) chunklen = lenleft;
/* copy src(user) to buf(kernel) then dst(user) */
if (copy_from_user(buf, src, chunklen)) return -EFAULT;
if (copy_to_user(dst, buf, chunklen)) return -EFAULT;
/* Adjust pointers and remaining size */
src += chunklen; dst += chunklen; lenleft -= chunklen;
}
/* return amount of data copied */
return len;
}
任何试图实现该系统调用的人都建议远离书中的特定样本,尽管我认为,至少它会给你一些良好的内核调试经验: - )
答案 1 :(得分:0)
int init_module(void)
{
mempool_t *mempool;
struct kmem_cache *kmem_cache;
void *p0 , *p1;
kmem_cache = kmem_cache_create("Ashrama" ,100 , 0 ,SLAB_PANIC ,NULL);
mempool = mempool_create(4 , mempool_alloc_slab , mempool_free_slab , kmem_cache);
p0 = mempool_alloc(mempool, SLAB_PANIC);
p1 = mempool_alloc(mempool , SLAB_PANIC);
strcpy(p0 , "Ranjan.B.M");
strcpy(p1 , "Mithun.V");
mempool_free( p0 , mempool);
printk(KERN_ALERT"%s",p0);
printk(KERN_ALERT"%s",p1);
}