Date: Thu, 22 Mar 2012 20:10:39 +0000 From: Eric Saint-Etienne <eric.saintetienne@gmail.com> To: Ryan Stone <rysto32@gmail.com> Cc: freebsd-hackers@freebsd.org Subject: Re: malloc pages map to user space Message-ID: <CACJX%2B5079mShMOyEpgXz8C%2B_M9zui6ew_kGwRHb1tEv_aCpvbA@mail.gmail.com> In-Reply-To: <CACJX%2B511wZyKVXeYqUQ3v6Uh0ZN83TbBZT7CC6V6N0jTsibD-w@mail.gmail.com> References: <CACJX%2B52DPPYea5k6QxQ6WQ62GEA9YHGr4y=ETUpPArNL83kh5w@mail.gmail.com> <CACJX%2B535YeOwWZodE1w8jiECKbDgyBbZgYDd=M31NwyTMTx83g@mail.gmail.com> <CACJX%2B51Po_RfhUF7Ba1VT0XLfLWQYWFmnRBRcNuDp%2B3nh_AopQ@mail.gmail.com> <CAFMmRNxvLz9G73Kn2BXq9WG5-0ZcTN%2BSumawWDzz5DRj=hN4PQ@mail.gmail.com> <CACJX%2B511wZyKVXeYqUQ3v6Uh0ZN83TbBZT7CC6V6N0jTsibD-w@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
Here is some code which fails with malloc < 1 page and sometimes succeeds with large mallocs (> 16 pages) What's wrong? #include <sys/param.h> #include <sys/proc.h> #include <sys/conf.h> #include <sys/module.h> #include <sys/sysent.h> #include <sys/kernel.h> #include <sys/systm.h> #include <sys/sysproto.h> #include <sys/resourcevar.h> // Copyright: skeleton took from an older post on the freebsd list #include <vm/vm.h> #include <vm/pmap.h> #include <vm/vm_map.h> #include <vm/vm_extern.h> #include <vm/vm_param.h> #include <vm/vm_kern.h> #include <vm/vm_object.h> #include <vm/vm_page.h> MALLOC_DEFINE(M_FIVEG_SYSC, "fiveg_sysc", "fiveg_sysc test"); struct args { unsigned char **p; }; /* String to be located in maped buffer */ #define SIZE PAGE_SIZE // 1 page always fail static void initialize_array(char *p) { int i; for (i = 0; i < 26; i++) p[i] = i+'a'; p[26] = '!'; p[27] = '\0'; } static vm_offset_t addr; // allocated/freed at module load/unload /* Syscall func */ static int syscf(struct thread *td, void *sa) { vm_offset_t user_addr; /* User space address */ struct args *uap = (struct args*) sa; struct proc *procp = (struct proc *)td->td_proc; struct vmspace *vms = procp->p_vmspace; vm_map_t map; int result; vm_object_t object; vm_ooffset_t objoffset; vm_map_entry_t entry; vm_pindex_t pindex; vm_prot_t prot; boolean_t wired; map = kernel_map; // it always return data within kmeme anyway uprintf("KERNEL string is '%s' (%p)\n", (char*) addr, (void*) addr); result = vm_map_lookup(&map, addr, VM_PROT_ALL, &entry, &object, &pindex, &prot, &wired); if (result != KERN_SUCCESS) { uprintf("KERNEL vm_map_lookup failed (%d)\n", result); return ENOMEM; } vm_map_lookup_done(map, entry); if (object == kernel_object) uprintf("object is kernel_object\n"); else if (object == kmem_object) uprintf("object is kmem_object\n"); else uprintf("object=%p (not kmem, not kernel)\n", object); uprintf("entry=%p\n", entry); /* Offset in vm_object */ objoffset = addr - entry->start + entry->offset; user_addr = 0; result = vm_map_find(&vms->vm_map, object, objoffset, (vm_offset_t *) &user_addr, SIZE, VMFS_ANY_SPACE, VM_PROT_RW, VM_PROT_RW, 0); if (result != KERN_SUCCESS) uprintf("vm_map_find failed: %d\n", result); else { *uap->p = (char*) user_addr; uprintf("KERNEL ---> Syscall: user_addr for allocating space = 0x%lx\n", user_addr); } return result; } /* Sysent entity for syscall */ static struct sysent sc_sysent = { 1, /* Number of arguments */ syscf /* Syscall function */ }; //static struct sysent *old_sysent; /* Offset in sysent[] */ static int offset = NO_SYSCALL; /* Loader */ static int load (struct module *m, int cmd, void *something) { int error = 0; switch(cmd){ case MOD_LOAD: //MALLOC(addr, vm_offset_t, SIZE, M_FIVEG_SYSC, M_WAITOK | M_ZERO); addr = (vm_offset_t) malloc(SIZE, M_FIVEG_SYSC, M_WAITOK); initialize_array((char*) addr); uprintf("KERNEL Module with sysc loaded. Offset = %d \n", offset); break; case MOD_UNLOAD: free((void*) addr, M_FIVEG_SYSC); uprintf("KERNEL Module with sysc unloaded. Offset = %d \n", offset); break; default: error = EOPNOTSUPP; break; } return (error); /* Syscall macro*/ SYSCALL_MODULE(fiveg_sysc, &offset, &sc_sysent, load, NULL); /* eof */ ------------------------------------------------ -- USERLAND PROGRAM ------------------------------------------------ #include <stdio.h> #include <stdlib.h> #include <limits.h> #include <sys/syscall.h> #include <sys/types.h> #include <sys/module.h> int main(int argc, char *argv[]) { int sysc_num, error; struct module_stat mstat; /* This Variable will save the addres of remapped buffer */ unsigned char *some_var = NULL; /* Pointer to pointer to remapped buffer */ unsigned char **p = &some_var; /* Search module with system call */ mstat.version = sizeof(mstat); if (!(modstat(modfind("sys/fiveg_sysc"), &mstat))){ /* Our module */ sysc_num = mstat.data.intval; printf("USER: Module found, Syscall number = %d \n", sysc_num); /* make system call */ error = syscall(sysc_num, p); if (error != 0) { printf("USER: an error occured: %d\n", error); return -1; } /* Read the string from remapped buffer */ printf("USER: p = %p\n", p); printf("USER: *p = %p\n", *p); printf("USER: String = %s\n", *p); } else printf("USER: Module seems to be not loaded! \n"); return 0; } /* eof */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CACJX%2B5079mShMOyEpgXz8C%2B_M9zui6ew_kGwRHb1tEv_aCpvbA>