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 <[EMAIL PROTECTED]> wrote:
> The itf is actually addr variable . That was a typo while formatting
> code in the mail.
>
> Regards,
> Asim
>
> On 7/15/08, Asim <[EMAIL PROTECTED]> 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 <[EMAIL PROTECTED]> wrote:
>>> Can you be a bit more specific ?
>>>
>>> On Tue, Jul 15, 2008 at 9:55 PM, Asim <[EMAIL PROTECTED]> 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 [EMAIL PROTECTED]
>>>> 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 [EMAIL PROTECTED]
> Please read the FAQ at http://kernelnewbies.org/FAQ
>
>
--
Regards,
Peter Teoh
--
To unsubscribe from this list: send an email with
"unsubscribe kernelnewbies" to [EMAIL PROTECTED]
Please read the FAQ at http://kernelnewbies.org/FAQ