Thanks Peter for the great explanation! I'm working towards modifiying the kernel by adding a new layer so luckily I have the change_page_attr_set available to me. Thanks, Asim On 7/15/08, Peter Teoh <htmldeveloper@xxxxxxxxx> wrote: > This is a feature of the Intel CPU - called the NX bit. Once turned > on, it is a hardware feature whereby u can specify whether the code is > made executeable or not. As of 2nd edition of Understanding Linux > Kernel, it is still mentioned that x86 cannot distinguished between > executeable and non-executable memory. But later Intel introduced > this bit. > > Lookup all the codes for implementing this in arch/x86/mm. > > For eg, init_32.c - u can specify to disable this feature via > "noexec=off" at the kernel bootup prompt. > > * Control non executable mappings. > * > * on Enable > * off Disable > */ > static int __init noexec_setup(char *str) > { > if (!str || !strcmp(str, "on")) { > if (cpu_has_nx) { > __supported_pte_mask |= _PAGE_NX; > disable_nx = 0; > } > } else { > if (!strcmp(str, "off")) { > disable_nx = 1; > __supported_pte_mask &= ~_PAGE_NX; > } else { > return -EINVAL; > > > Or in pageattr.c: > > /* > * Certain areas of memory on x86 require very specific protection flags, > * for example the BIOS area or kernel text. Callers don't always get this > * right (again, ioremap() on BIOS memory is not uncommon) so this function > * checks and fixes these known static required protection bits. > */ > static inline pgprot_t static_protections(pgprot_t prot, unsigned long > address, > unsigned long pfn) > { > pgprot_t forbidden = __pgprot(0); > > /* > * The BIOS area between 640k and 1Mb needs to be executable for > * PCI BIOS based config access (CONFIG_PCI_GOBIOS) support. > */ > if (within(pfn, BIOS_BEGIN >> PAGE_SHIFT, BIOS_END >> PAGE_SHIFT)) > pgprot_val(forbidden) |= _PAGE_NX; > > /* > * The kernel text needs to be executable for obvious reasons > * Does not cover __inittext since that is gone later on. On > * 64bit we do not enforce !NX on the low mapping > */ > if (within(address, (unsigned long)_text, (unsigned long)_etext)) > pgprot_val(forbidden) |= _PAGE_NX; > > /* > * The .rodata section needs to be read-only. Using the pfn > * catches all aliases. > */ > if (within(pfn, __pa((unsigned long)__start_rodata) >> PAGE_SHIFT, > __pa((unsigned long)__end_rodata) >> PAGE_SHIFT)) > pgprot_val(forbidden) |= _PAGE_RW; > > prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden)); > > return prot; > } > > Read the comment of this function - basically, it is saying that > certain ranges of the page frame, if it fall within a certain range of > the physical address, will have certain page protection properties > (set into the memory descriptor) - like read/write/executeable. > > And according to its definition in pgtable.h: > > #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) > #define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_NX) > #else > #define _PAGE_NX (_AT(pteval_t, 0)) > #endif > > Only 64-bit x86 have this feature enabled. > > What can u do about it? > > One way is to disable it via command line as mentioned above, another > way is understand enough of change_page_attr_set() (in > pageattr.c) to do what u want to do - but it is also a static > function, so inside your module this function is not visible to you. > > It is just a memory descriptor thing, so u can manipulate it any other > way u want to as well, but the TLB have to be flush, per-cpu. > > CMIW. > > Thanks. > > > On Wed, Jul 16, 2008 at 1:51 AM, Asim <linkasim@xxxxxxxxx> wrote: >> The itf is actually addr variable . That was a typo while formatting >> code in the mail. >> >> Regards, >> Asim >> >> On 7/15/08, Asim <linkasim@xxxxxxxxx> wrote: >>> I'm allocation some function pointers and they were not executable. I >>> wanted to make them executable. I was able to fix my problem. Let me >>> know if there is any bug in what I did. >>> >>> my_array_of _fn_pointers = kmalloc(sizeof >>> your_favourite_fn_ptr_struct_here, GFP_KERNEL); >>> >>> addr = my_array_of _fn_pointers ; >>> addr_end = (unsigned long) my_array_of _fn_pointers + (unsigned long) >>> sizeof(your_favourite_fn_ptr_struct_here); >>> >>> /* Make the memory allocated executable. */ >>> for (; addr < addr_end; addr += PAGE_SIZE) >>> change_page_attr(virt_to_page(itf), 1, PAGE_KERNEL_EXEC); >>> >>> printk ("Making the pages executable.\n"); >>> global_flush_tlb(); >>> >>> It seems to work fine so far. >>> >>> Regards, >>> Asim Kadav >>> >>> On 7/15/08, Sandeep K Sinha <sandeepksinha@xxxxxxxxx> wrote: >>>> Can you be a bit more specific ? >>>> >>>> On Tue, Jul 15, 2008 at 9:55 PM, Asim <linkasim@xxxxxxxxx> wrote: >>>>> Hi, >>>>> >>>>> I try to allocate memory to generate some executable code in memory. >>>>> But when i try to execute - I get the following error "kernel tried to >>>>> execute NX-protected page - exploit attempt? (uid: 0)". Is there some >>>>> different way to allocate executable memory (and not data). Kindly >>>>> help. >>>>> >>>>> Regards, >>>>> Asim >>>>> >>>>> -- >>>>> To unsubscribe from this list: send an email with >>>>> "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx >>>>> Please read the FAQ at http://kernelnewbies.org/FAQ >>>>> >>>>> >>>> >>>> >>>> >>>> -- >>>> Regards, >>>> Sandeep. >>>> >>>> >>>> >>>> >>>> >>>> >>>> "To learn is to change. Education is a process that changes the >>>> learner." >>>> >>> >> >> -- >> To unsubscribe from this list: send an email with >> "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx >> Please read the FAQ at http://kernelnewbies.org/FAQ >> >> > > > > -- > Regards, > Peter Teoh > -- To unsubscribe from this list: send an email with "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx Please read the FAQ at http://kernelnewbies.org/FAQ