Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I would like to know if i can execute a code piece sitting inside the heap space?

share|improve this question
1  
If your question is about how to branch to a piece of code in a particular programming language, ask on Stack Overflow. –  Gilles Jan 6 '11 at 8:23

2 Answers 2

On some hardware (like HP's HP-PA CPUs) it's far more difficult, and on others (like DEC Alpha CPU) you have to do an instruction cache flush first, but yes, in general, you can execute code on the heap. The following is a reasonably decent C language program that executes code "on the heap".

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>

/* $Id: cpup4.c,v 1.2 1999/02/25 05:12:53 bediger Exp bediger $ */

typedef int (*fxptr)(
                int, int, int (*)(const char *, ...),
                void *,
                void *(*)(void *, const void *, size_t),
                void *(*)(size_t),
                void (*)(void *),
                size_t
);

char *signal_string(int sig);
void  signal_handler(int sig);
int   main(int ac, char **av);
int copyup(
                int i,
                int j,
                int (*xptr)(const char *, ...),
                void *yptr,
                void *(*bptr)(void *, const void *, size_t),
                void *(*mptr)(size_t),
                void (*ffptr)(void *),
                size_t  size
);
void f2(void);

/* return a string for the most common signals this program
 * will generate.  Probably could replace this with strerror()
 */
char *
signal_string(sig)
                int sig;
{
                char *bpr = "Don't know what signal";

                switch (sig)
                {
                case SIGILL:
                                bpr = "Illegal instruction";
                                break;
                case SIGSEGV:
                                bpr = "Segmentation violation";
                                break;
                case SIGBUS:
                                bpr = "Bus error";
                                break;
                }

                return bpr;
}

/* Use of fprintf() seems sketchy.  I think that signal_handler() doesn't
 * need special compiler treatment like generating Position Independent
 * Code.  It stays in one place, and the kernel knows that place.
 */
void
signal_handler(int sig)
{
                (void)fprintf(
                                stderr,
                                "%s: sig = 0x%x\n",
                                signal_string(sig),
                                sig
                );

                exit(99);
}

int
main(int ac, char **av)
{
                int i, j;

                /* check to see if cmd line has a number on it */
                if (ac < 2) {
                                printf("not enough arguments\n");
                                exit(99);
                }
                /* install 3 different signal handlers - avoid core dumps */
                if (-1 == (i = (long)signal(SIGSEGV, signal_handler)))
                {
                                perror("Installing SIGSEGV signal failed");
                                exit(33);
                }
                if (-1 == (i = (long)signal(SIGILL, signal_handler)))
                {
                                perror("Installing SIGILL signal handler failed");
                                exit(33);
                }
                if (-1 == (i = (long)signal(SIGBUS, signal_handler)))
                {
                                perror("Installing SIGBUS signal handler failed");
                                exit(33);
                }

                setbuf(stdout, NULL);

                /*
                 * print out addresses of original functions so there is something to
                 * reference during recursive function copying and calling 
                 */
                printf(
           "main = %p, copyup %p, memcpy %p, malloc %p, printf %p, free %p, size %ld\n",
           main, copyup, memcpy, malloc, printf, free, (size_t)f2 - (size_t)copyup);

                if ((i = atoi(*(av + 1))) < 1) {
                                printf(" i = %d, i must be > 1\n", i);
                                exit(99);
                }

                printf(" going for %d recursions\n", i);

                j = copyup(1, i, printf, copyup, memcpy, malloc, free, (size_t)f2 - (size_t)copyup);

                printf("copyup at %p returned %d\n", copyup, j);


                return 1;
}

int
copyup(
                int i, int j,
                int   (*xptr)(const char *, ...),
                void *yptr,
                void *(*bptr)(void *, const void*, size_t),
                void *(*mptr)(size_t),
                void  (*ffptr)(void *),
                size_t   size
)
{
                fxptr fptr;
                int k;

                if (i == j)
                {
                                (*xptr)("function at %p got to %d'th copy\n", yptr, i);
                                return i;
                } else
                                (*xptr)("function at %p, i = %d, j = %d\n", yptr, i, j);

                if (!(fptr = (fxptr)(*mptr)(size)))
                {
                                (*xptr)("ran out of memory allocating new function\n");
                                return -1;
                }

                (*bptr)(fptr, yptr, size);

                k = (*fptr)(i + 1, j, xptr, (void *)fptr, bptr, mptr, ffptr, size);

                (*xptr)("function at %p got %d back from function at %p\n",
                                yptr, k, fptr);

                (*ffptr)(fptr);

                return (k + 1);
}

void f2(void) {return;}
share|improve this answer
    
i have tried this, but i dont understand why i get a segmentation fault for all values other than 1. –  Sen Jan 13 '11 at 15:07
    
An argument of 1 just executes the function - although the function will create a copy of itself on the heap, it does not execute the heap-copy. I don't know why you get a segmentation violation. Can you give some more details about compiler, CPU, OS, etc etc? –  Bruce Ediger Jan 18 '11 at 17:13

Maybe. If the heap is executable, you can branch to that code. But some unix variants make the heap space non-executable, so as to make exploits of some security vulnerabilities such as buffer overflows more difficult (then even if you can inject code into a program, you might not be able to branch to it). (See the linked article for a discussion of unix variants and their configuration.) Also some processor architectures have separate caches for code and data, so you may need to issue a cache flush instruction. All in all, this isn't something you want to do by hand.

There is a standard unix API to load and execute code, which will do what it takes to make the loaded code executable: dlopen. The code has to be loaded from a file.

Just-in-time compilers typically try to find faster interfaces than dlopen. They have to manage the highly platform-dependent ways of ensuring code executability.

EDIT: Thanks to Bruce Ediger for reminding me of the need to flush the cache.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.