allocate memory in userspace
Hi,
I am a kernel newbie and i am writing a module. I need to allocate some memory in userspace because i want to access syscalls like open(), lstat() etc. I need to call these methods in the kernel, and in my special case there is no other way, but i do not want to reimplement all the syscalls.
I read that it should be possible, but i cannot find any example or recipe on how to do it. It should work with do_mmap() and fd=-1 and MAP_ANON, but i jusst can't get it to work.
Do you now any working example, or a good reference for the do_mmap() call?
Thanks in advance,
-timo
Signature · 1 line
gpg key fingerprint = 6832 C8EC D823 4059 0CD1 6FBF 9383 7DBD 109E 98DC
Quoted 8 lines · Timo Benk
Hi,
I am a kernel newbie and i am writing a module. I need to allocate some memory in userspace because i want to access syscalls like
open(),lstat()etc. I need to call these methods in the kernel, and in my special case there is no other way, but i do not want to reimplement all the syscalls.
So use the C library and call malloc()
Quoted 4 lines
I read that it should be possible, but i cannot find any example or recipe on how to do it. It should work with
do_mmap()and fd=-1 andMAP_ANON, but i jusst can't get it to work.
void *malloc(size_t size)
{
void *result;
if (size == 0)
return NULL;
result = mmap((void *) 0, size + sizeof(size_t), PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
if (result == MAP_FAILED)
return 0;
* (size_t *) result = size;
return(result + sizeof(size_t));
}void * calloc(size_t nelem, size_t size)
{
void *result;
result = malloc(size * nelem);
if (result)
memset(result, 0, nelem * size);
return result;
}void *realloc(void *ptr, size_t size)
{
void *newptr = NULL;
if (size > 0) {
newptr = malloc(size);
if (newptr && ptr) {
memcpy(newptr, ptr, * ((size_t *) (ptr - sizeof(size_t))));
free(ptr);
}
}
else {
free(ptr);
}
return newptr;
}void free(void *ptr)
{
if (ptr) {
ptr -= sizeof(size_t);
munmap(ptr, * (size_t *) ptr);
}
}-Erik
--
Erik B. Andersen http://codepoet-consulting.com/
--This message was written using 73% post-consumer electrons--
Quoted 12 lines · Erik Andersen
void *malloc(size_t size)
{ void *result; if (size == 0) return NULL; result = mmap((void *) 0, size + sizeof(size_t), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); if (result == MAP_FAILED) return 0; * (size_t *) result = size; return(result + sizeof(size_t)); }
This looks like a very bad idea. Userspace allocators should make some attempt at avoiding diving into the kernel at every allocation like this. Also, they should be intelligent enough to get around TASK_UNMAPPED_BASE. Wilson's allocator survey has an excellent discussion of the issues. Doug Lea has a better example of a userspace memory allocator.
Cheers,
Bill
Quoted 12 lines · Erik Andersen
Quoted 12 lines
void *malloc(size_t size)
{ void *result; if (size == 0) return NULL; result = mmap((void *) 0, size + sizeof(size_t), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); if (result == MAP_FAILED) return 0; * (size_t *) result = size; return(result + sizeof(size_t)); }
Quoted 2 lines · William Lee Irwin III
This looks like a very bad idea. Userspace allocators should make some attempt at avoiding diving into the kernel at every allocation like this.
Sorry, I also forgot the rather severe internal fragmentation this is likely to suffer due to page-level restrictions on mmap's operation.
Cheers,
Bill
Quoted 14 lines · William Lee Irwin III
Quoted 4 lines · Erik Andersen
Quoted 4 lines
void *malloc(size_t size)
{ void *result; if (size == 0)Quoted 8 lines
Quoted 8 lines
return NULL; result = mmap((void *) 0, size + sizeof(size_t), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); if (result == MAP_FAILED) return 0; * (size_t *) result = size; return(result + sizeof(size_t)); }
Quoted 6 lines
Quoted 2 lines · William Lee Irwin III
This looks like a very bad idea. Userspace allocators should make some attempt at avoiding diving into the kernel at every allocation like this.
Sorry, I also forgot the rather severe internal fragmentation this is likely to suffer due to page-level restrictions on mmap's operation.
Of course. No question there -- actually using such an allocator (with a standard linux kernel) would be a terrible idea. I was merely providing a trivial answer to his question on how to use mmap to allocate memory.
-Erik
--
Erik B. Andersen http://codepoet-consulting.com/
--This message was written using 73% post-consumer electrons--
Why don't you just exec a process?
Quoted 22 lines · Timo Benk
Hi,
I am a kernel newbie and i am writing a module. I need to allocate some memory in userspace because i want to access syscalls like
open(),lstat()etc. I need to call these methods in the kernel, and in my special case there is no other way, but i do not want to reimplement all the syscalls.I read that it should be possible, but i cannot find any example or recipe on how to do it. It should work with
do_mmap()and fd=-1 andMAP_ANON, but i jusst can't get it to work.Do you now any working example, or a good reference for the
do_mmap()call?Thanks in advance,
-timo
Re: allocate memory in userspace (Answer)
In reply to Timo BenkHi,
I found the following function in arch/i386/kernel/sys_i386.c:
---<snip>---
/* common code for old and new mmaps */
long do_mmap2
(
unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff
)
{
int error = -EBADF;
struct file * file = NULL;
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
if (!(flags & MAP_ANONYMOUS)) {
file = fget(fd);
if (!file)
goto out;
}
down_write(¤t->mm->mmap_sem);
error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
up_write(¤t->mm->mmap_sem);
if (file)
fput(file);
out:
return error;
}---<snap>---
the following code works for me(of course
don't forget to munmap the memory).
---<snip>---
char *userspace;
char kernelspace[2048];
userspace = (char*)do_mmap2
(
0,
2048,
PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANON,
-1,
0
);
copy_to_user( userspace, "/dev/hda", 9 );
copy_from_user( kernelspace, userspace, 9 );
printk("%s\n",kernelspace);---<snap>---
Hope that helps any other struggling newbie:-)
-timo
Signature · 1 line
gpg key fingerprint = 6832 C8EC D823 4059 0CD1 6FBF 9383 7DBD 109E 98DC
Re: allocate memory in userspace (Answer)
As stated by Andy Kleen this is not a good solution. This is his post to the topic:
----<snip>----
Quoted 9 lines
I am a kernel newbie and i am writing a module. I need to allocate some memory in userspace because i want to access syscalls like
open(),lstat()etc. I need to call these methods in the kernel, and in my special case there is no other way, but i do not want to reimplement all the syscalls.I read that it should be possible, but i cannot find any example or recipe on how to do it.
mm_segment_t oldfs = get_fs();set_fs(KERNEL_DS);
ret = sys_yoursyscall(kernelargs ...)set_fs(oldfs);
Do not even think about using mmap or accessing sys_call_table for this. Your other post was so tasteless that it would be good if you retracted it with a followup because it would be very bad to have such an bad example
in the l-k archives open to innocent search machine users uncommented.
-Andi
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
----<snap>-----
Quoted 63 lines · Timo Benk
Hi,
I found the following function in
arch/i386/kernel/sys_i386.c:---<snip>---
/* common code for old and new mmaps */
longdo_mmap2
(
unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags,
unsigned long fd, unsigned long pgoff
){ int error = -EBADF; struct file * file = NULL; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); if (!(flags & MAP_ANONYMOUS)) { file = fget(fd); if (!file) goto out; } down_write(¤t->mm->mmap_sem); error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up_write(¤t->mm->mmap_sem); if (file) fput(file); out: return error; }---<snap>---
the following code works for me(of course don't forget to munmap the memory). ---<snip>---
char *userspace; char kernelspace[2048]; userspace = (char*)do_mmap2 ( 0, 2048, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0 ); copy_to_user( userspace, "/dev/hda", 9 ); copy_from_user( kernelspace, userspace, 9 ); printk("%s\n",kernelspace);---<snap>---
Hope that helps any other struggling newbie:-)
-timo
Signature · 1 line
gpg key fingerprint = 6832 C8EC D823 4059 0CD1 6FBF 9383 7DBD 109E 98DC
Signature · 1 line
gpg key fingerprint = 6832 C8EC D823 4059 0CD1 6FBF 9383 7DBD 109E 98DC
Quoted 6 lines · Timo Benk
Hi,
I am a kernel newbie and i am writing a module. I need to allocate some memory in userspace because i want to access syscalls like
open(),lstat()etc.
I need to call these methods in the kernel, and in
my special case there is no other way, but i do not want to reimplement all the syscalls.
What are you trying to do with this module? If you are needing to use syscalls like open(), you are probably trying to do something that is forbidden in kernel space. For example, trying to read a configuration file.
Recommended reading:
http://www.linux.org.uk/~ajh/ols2002_proceedings.pdf.gz
The chapter named "How NOT to write kernel drivers", especially sections 7 and 8.
--
Brian Gerst