Sample source code from "Linux kernel programming"

read Robert Love’s book, chapter 5 on system calls, and found this simple example a little dubious:

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; ... } 

As we see, "buf" is an object of type "unsigned long" and defined on the kernel stack, that is, its initial value is probably garbage. In any case, is it really to copy len bytes on the stack where buf is, i.e. Can he rewrite something useful? Perhaps this is only good for this particular example?

+8
c linux-kernel
source share
2 answers

This is very doubtful. In fact, this is completely dangerous. I will give the author the opportunity to doubt here, because they are just trying to show how copy_from_user and copy_to_user , but they really should have given an example that was not so dangerous.

Especially since the book stinks lyrical about how you should be especially careful:

System calls must carefully check all of their parameters to ensure that they are valid and legal.The system call is made in the kernel-space, and if the user can pass invalid input to the kernel without restrictions, system security and stability can be affected.

and then gives the user the ability to completely invalidate the kernel :-)


Text from the copy I am in:

Consider an example of a system call that uses both copy_from_user() and copy_to_user() . This syscall, silly_copy() , is completely useless; it copies data from its first parameter to the second. This is suboptimal because it includes an intermediate and an extraneous copy in the kernel space without amplification. But this helps illustrate the point.

 /* * 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; } 

Besides the crash of checking parameters, I am pretty sure that the last parameter SYSCALL_DEFINE3 does not contain a comma (although this will be just a typo).

A better example, without having to allocate arbitrary memory, would be line by line:

 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; } 

Anyone who is trying to implement this system call would be useful to distract from this specific example in the book, although I assume that at least it will give you good kernel debugging experience :-)

+15
source share
 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.BM"); strcpy(p1 , "Mithun.V"); mempool_free( p0 , mempool); printk(KERN_ALERT"%s",p0); printk(KERN_ALERT"%s",p1); } 
0
source share

All Articles