two function addresses subtraction - c

I'm reading a piece of code about exploit in here. There is a statement going like this:
/*
FreeBSD <= 6.1 suffers from classical check/use race condition on SMP
systems in kevent() syscall, leading to kernel mode NULL pointer
dereference. It can be triggered by spawning two threads:
1st thread looping on open() and close() syscalls, and the 2nd thread
looping on kevent(), trying to add possibly invalid filedescriptor.
*/
static void kernel_code(void) {
struct thread *thread;
gotroot = 1;
asm(
"movl %%fs:0, %0"
: "=r"(thread)
);
thread->td_proc->p_ucred->cr_uid = 0;
#ifdef PRISON_BREAK
thread->td_proc->p_ucred->cr_prison = NULL;
#endif
return;
}
static void code_end(void) {
return;
}
int main() {
....
memcpy(0, &kernel_code, &code_end - &kernel_code);
....
}
I'm curious what's the meaning of this memcpy? What is the result of &code_end - &kernel_code?

This assumes that the function kernel_code() will end where somewhere before function code_end() starts. The memcpy() therefore copies kernel_code() to address 0. One assumes that some other aspect of the exploit results in a return or jump to address 0, thereby running kernel_code().

void * memcpy ( void * destination, const void * source, size_t num );
That memcpy will copy the function kernel_code to address 0 (NULL).

What the code is trying to exploit, is gaining root privilege, UID of 0, by two threads competing for the queue, do_thread/do_thread2.
By mmaping the contents of the address of the code_end function, with the address of kernel_code, copy the result into the buffer, to the address 0, on the condition that the code are adjacent to each other, thereby, as in effective user id of 0 aka root.
This C++ Ref page summarizes what memcpy is about.
void * memcpy ( void * destination, const void * source, size_t num );
Copies the values of num bytes from the location pointed to by source
directly to the memory block pointed to by destination.

Related

Program with while loop causes stack overflow, but only in x86 and only when injected into another process

I have an unfortunately convoluted problem that I am hopeful someone might be able to help me with.
I have written a reasonably large program that I have converted into position independent code (see here for reference: https://bruteratel.com/research/feature-update/2021/01/30/OBJEXEC/). Basically just meaning that the resulting exe (compiled using mingw) contains data only in the .text section, and thus can be injected into and ran from an arbitrary place in memory. I have successfully ported the program to this format and can compile it for both x86 and x64.
I created two "helper" exe's to run the PIC program, a local injector and a remote injector. The local injector runs the program by calling VirtualAlloc, memcpy, and CreateThread. The remote injector runs the program by calling CreateProcess (suspended), VirtualAllocEx, WriteProcessMemory, QueueAPCThread, and ResumeThread (the last two api's being called on pi.hThread which was returned from CreateProcess).
I am experiencing inconsistent results in the program depending on the architecture and method of execution.
x64 local: works
x64 inject: works
x86 local: works
x86 inject: fails; stack overflow
I have determined that my program is crashing in a while loop in a particular function. This function is used to format data contained in buffers (heap allocated) that are passed in as function args. The raw data buffer (IOBuf) contains a ~325k long string containing Base64 characters with spaces randomly placed throughout. The while loop in question iterates over this buffer and copies non-space characters to a second buffer (IntermedBuf), with the end goal being that IntermedBuf contains the full Base64 string in IOBuf minus the random spaces.
A few notes about the following code snippet:
Because the code is written to be position independent, all api's must be manually resolved which is why you see things like (SPRINTF)(Apis.sprintfFunc). I have resolved the addresses of each API in their respective DLL and have created typedef's for each API that is called. While odd, this is not in itself causing the issue as the code works fine in 3/4 of the situations.
Because this program is failing when injected, I cannot use print statements to debug, so I have added calls to MessageBoxA to pop up at certain places to determine contents of variables and/or if execution is reaching that part of the code.
The relevant code snippet is as follows:
char inter[] = {'I','n','t',' ',0};
char tools[100] = {0};
if (((STRCMP)Apis.strcmpFunc)(IntermedBuf, StringVars->b64Null) != 0)
{
int i = 0, j = 0, strLen = 0, lenIOBuf = ((STRLEN)Apis.strlenFunc)(IOBuf);
((SPRINTF)Apis.sprintfFunc)(tools, StringVars->poi, IOBuf);
((MESSAGEBOXA)Apis.MessageBoxAFunc)(NULL, tools, NULL, NULL);
((MEMSET)Apis.memsetFunc)(tools, 0, 100 * sizeof(char));
((SPRINTF)Apis.sprintfFunc)(tools, StringVars->poi, IntermedBuf);
((MESSAGEBOXA)Apis.MessageBoxAFunc)(NULL, tools, NULL, NULL);
char* locSpace;
while (j < lenIOBuf)
{
locSpace = ((STRSTR)Apis.strstrFunc)(IOBuf + j, StringVars->space);
if (locSpace == 0)
locSpace = IOBuf + lenIOBuf;
strLen = locSpace - IOBuf - j;
((MEMCPY)Apis.memcpyFunc)(IntermedBuf + i, IOBuf + j, strLen);
i += strLen, j += strLen + 1;
}
((MESSAGEBOXA)Apis.MessageBoxAFunc)(NULL, StringVars->here, NULL, NULL);
((MEMSET)Apis.memsetFunc)(IOBuf, 0, BUFFSIZE * sizeof(char));
The first two MessageBoxA calls successfully execute, each containing the address of IOBuf and IntermedBuf respectively. The last call to MessageBoxA, after the while loop, never comes, meaning the program is crashing in the while loop as it copies data from IOBuf to IntermedBuf.
I ran remote.exe which spawned a new WerFault.exe (I have tried with calc, notepad, several other processes with the same result) containing the PIC program, and stuck it into Windbg to try and get a better sense of what was happening. I found that after receiving the first two message boxes and clicking through them, WerFault crashes with a stack overflow caused by a call to strstr:
Examining the contents of the stack at crash time shows this:
Looking at the contents of IntermedBuf (which is one of the arguments passed to the strstr call) I can see that the program IS copying data from IOBuf to IntermedBuf and removing spaces as intended, however the program crashes after copying ~80k.
IOBuf (raw data):
IntermedBuf(After removing spaces)
My preliminary understanding of what is happening here is that strstr (and potentially memcpy) are pushing data to the stack with each call, and given the length of the loop (lengthIOBuf is ~325K, spaces occur randomly every 2-11 characters throught) the stack is overflowing before the while loop finishes and the stack unwinds. However this doesn't explain why this succeeds in x64 in both cases, and in x86 when the PIC program is running in a user-made program as opposed to injected into a legitimate process.
I have ran the x86 PIC program in the local injector, where it succeeds, and also attached Windbg to it in order to examine what is happening differently there. The stack similarly contains the same sort of pattern of characters as seen in the above screenshot, however later in the loop (because again the program succeeds), the stack appears to... jump? I examined the contents of the stack early into the while loop (having set bp on strstr) and see that it contains much the same pattern seen in the stack in the remote injector session:
I also added another MessageBox this time inside the while loop, set to pop when j > lenIOBuf - 500 in order to catch the program as it neared completion of the while loop.
char* locSpace;
while (j < lenIOBuf)
{
if (j > lenIOBuf - 500)
{
((MEMSET)Apis.memsetFunc)(tools, 0, 100 * sizeof(char));
((SPRINTF)Apis.sprintfFunc)(tools, StringVars->poi, IntermedBuf);
((MESSAGEBOXA)Apis.MessageBoxAFunc)(NULL, tools, NULL, NULL);
}
locSpace = ((STRSTR)Apis.strstrFunc)(IOBuf + j, StringVars->space);
if (locSpace == 0)
locSpace = IOBuf + lenIOBuf;
strLen = locSpace - IOBuf - j;
((MEMCPY)Apis.memcpyFunc)(IntermedBuf + i, IOBuf + j, strLen);
i += strLen, j += strLen + 1;
}
When this MessageBox popped, I paused execution and found that ESP was now 649fd80; previously it was around 13beb24?
So it appears that the stack relocated, or the local injector added more memory to the stack or something (I am embarassingly naive about this stuff). Looking at the "original" stack location at this stage in execution shows that the data there previously is still there at this point when the loop is near completion:
So bottom line, this code which runs successfully by all accounts in x64 local/remote and x86 local is crashing when ran in another process in x86. It appears that in the local injector case the stack fills in a similar fashion as in the remote injector where it crashes, however the local injector is relocating the stack or adding more stack space or something which isn't happening in the remote injector. Does anyone have any ideas why, or more importantly, how I could alter the code to achieve the goal of removing spaces from a large, arbitrary buffer in a different way where I might not encounter the overflow that I am currently?
Thanks for any help
typedef void*(WINAPI* MEMCPY)(void * destination, const void * source, size_t num);
typedef char*(WINAPI* STRSTR)(const char *haystack, const char *needle);
is wrong declarations. both this api used __cdecl calling convention - this mean that caller must up stack ( add esp,4*param_count) after call. but because you declare it as __stdcall (== WINAPI) compiler not generate add esp,4*param_count instruction. so you have unbalanced push for parameters.
you need use
typedef void * (__cdecl * MEMCPY)(void * _Dst, const void * _Src, _In_ size_t _MaxCount);
typedef char* (__cdecl* STRSTR)(_In_z_ char* const _String, _In_z_ char const* const _SubString);
and so on..
Familiar with what you are doing, and frankly I moved onto compiling some required functions (memcpy, etc) instead of manually looking them up and making external calls.
For example:
inline void* _memcpy(void* dest, const void* src, size_t count)
{
char *char_dest = (char *)dest;
char *char_src = (char *)src;
if ((char_dest <= char_src) || (char_dest >= (char_src+count)))
{
/* non-overlapping buffers */
while(count > 0)
{
*char_dest = *char_src;
char_dest++;
char_src++;
count--;
}
}
else
{
/* overlaping buffers */
char_dest = (char *)dest + count - 1;
char_src = (char *)src + count - 1;
while(count > 0)
{
*char_dest = *char_src;
char_dest--;
char_src--;
count--;
}
}
return dest;
}
inline char * _strstr(const char *s, const char *find)
{
char c, sc;
size_t len;
if ((c = *find++) != 0)
{
len = strlen(find);
do {
do {
if ((sc = *s++) == 0)
return 0;
} while (sc != c);
} while (strncmp(s, find, len) != 0);
s--;
}
return (char *)((size_t)s);
}
Credits for the above code from ReactOS. You can lookup the rest required (strlen, etc.)

How to create a process that runs a routine with variable number of parameters?

I know there are lots of questions here about functions that take a variable number of arguments. I also know there's lots of docs about stdarg.h and its macros. And I also know how printf-like functions take a variable number of arguments. I already tried each of those alternatives and they didn't help me. So, please, keep that in mind before marking this question as duplicate.
I'm working on the process management features of a little embedded operating system and I'm stuck on the design of a function that can create processes that run a function with a variable number of parameters. Here's a simplified version of how I want my API to looks like:
// create a new process
// * function is a pointer to the routine the process will run
// * nargs is the number of arguments the routine takes
void create(void* function, uint8_t nargs, ...);
void f1();
void f2(int i);
void f3(float f, int i, const char* str);
int main()
{
create(f1, 0);
create(f2, 1, 9);
create(f3, 3, 3.14f, 9, "string");
return 0;
}
And here is a pseudocode for the relevant part of the implementation of system call create:
void create(void* function, uint8_t nargs, ...)
{
process_stack = create_stack();
first_arg = &nargs + 1;
copy_args_list_to_process_stack(process_stack, first_arg);
}
Of course I'll need to know the calling convention in order to be able to copy from create's activation record to the new process stack, but that's not the problem. The problem is how many bytes do I need to copy. Even though I know how many arguments I need to copy, I don't know how much space each of those arguments occupy. So I don't know when to stop copying.
The Xinu Operating System does something very similar to what I want to do, but I tried hard to understand the code and didn't succeed. I'll transcript a very simplified version of the Xinu's create function here. Maybe someone understand and help me.
pid32 create(void* procaddr, uint32 ssize, pri16 priority, char *name, int32 nargs, ...)
{
int32 i;
uint32 *a; /* points to list of args */
uint32 *saddr; /* stack address */
saddr = (uint32 *)getstk(ssize); // return a pointer to the new process's stack
*saddr = STACKMAGIC; // STACKMAGIC is just a marker to detect stack overflow
// this is the cryptic part
/* push arguments */
a = (uint32 *)(&nargs + 1); /* start of args */
a += nargs -1; /* last argument */
for ( ; nargs > 4 ; nargs--) /* machine dependent; copy args */
*--saddr = *a--; /* onto created process's stack */
*--saddr = (long)procaddr;
for(i = 11; i >= 4; i--)
*--saddr = 0;
for(i = 4; i > 0; i--) {
if(i <= nargs)
*--saddr = *a--;
else
*--saddr = 0;
}
}
I got stuck on this line: a += nargs -1;. This should move the pointer a 4*(nargs - 1) ahead in memory, right? What if an argument's size is not 4 bytes? But that is just the first question. I also didn't understand the next lines of the code.
If you are writing an operating system, you also define the calling convention(s) right? Settle for argument sizes of sizeof(void*) and pad as necessary.

How do I use memcpy_toio/fromio?

I am working on a kernel module in C to talk to a PCIe card and I have allocated some io memory using pci_iomap, and I write/read there using ioread/write32.
This works but the performance is quite poor, and I read I could use block transfer through memcpy_toio/fromio instead of just doing 32b at a time.
To write, I am using iowrite32(buffer[i], privdata->registers + i);
To read, I do buffer[i] = ioread32(&privdata->registers[i]);
I tried to replace the for loops these are in with:
memcpy_toio(privdata->registers, buffer, 2048);
memcpy_fromio(buffer, privdata->registers, 2048);
If I only replace the write loop with memcpy_toio and I do the reading using ioread32, the program doesn't crash but the instruction doesn't seem to be doing anything (registers don't change);
Also, when I replace the read loop as well with the memcpy_fromio instruction, it crashes.
I was thinking it might be because the reads try to access the mem location while it is still being written to. Is there a way to flush the writes queue after either iowrite32 or memcpy_toio?
What am I doing wrong here?
memcpy_from/toio() can be used only if the I/O memory behaves like memory, i.e., if values can be read speculatively, and be written multiple times or out of order.
An I/O range marked as non-prefetchable does not support this.
I don't know if my suggestion is valid, the single ioread32 function is more efficient than memcpy, the read function only needs to read or write the PCI device once, while memcpy needs multiple times. The kernel provides functions such as ioread32_rep to replace the cumbersome for loop (essentially the same).If you need to pursue efficiency, you can try to use ioread32_rep, and you can try to use memcpy for reading and writing of variable length.
Which buffer type do you use?
Look at the implementation of memcpy_fromio() , memcpy_toio()
static inline void
memcpy_fromio(void *dst, volatile void __iomem *src, int count)
{
memcpy(dst, (void __force *) src, count);
}
static inline void
memcpy_toio(volatile void __iomem *dst, const void *src, int count)
{
memcpy((void __force *) dst, src, count);
}
Yo can see simple memcpy call.
And look at the iowrite32() and ioread32() implementations:
static inline void iowrite32(u32 val, void __iomem *p)
{
if (__is_PCI_addr(p))
val = _swapl(val);
__builtin_write32(p, val);
if (__is_PCI_MEM(p))
__flush_PCI_writes();
}
static inline unsigned int ioread32(void __iomem *p)
{
uint32_t ret = __builtin_read32(p);
if (__is_PCI_addr(p))
ret = _swapl(ret);
return ret;
}
As you can see memcpy_fromio() , memcpy_toio() are not suitable for working with PCIe devices.

C - shared memory - dynamic array inside shared struct

i'm trying to share a struct like this
example:
typedef struct {
int* a;
int b;
int c;
} ex;
between processes, the problem is that when I initialize 'a' with a malloc, it becomes private to the heap of the process that do this(or at least i think this is what happens). Is there any way to create a shared memory (with shmget, shmat) with this struct that works?
EDIT: I'm working on Linux.
EDIT: I have a process that initialize the buffer like this:
key_t key = ftok("gr", 'p');
int mid = shmget(key, sizeof(ex), IPC_CREAT | 0666);
ex* e = NULL;
status b_status = init(&e, 8); //init gives initial values to b c and allocate space for 'a' with a malloc
e = (ex*)shmat(mid, NULL, 0);
the other process attaches himself to the shared memory like this:
key_t key = ftok("gr", 'p');
int shmid = shmget(key, sizeof(ex), 0);
ex* e;
e = (ex*)shmat(shmid, NULL, 0);
and later get an element from a, in this case that in position 1
int i = get_el(e, 1);
First of all, to share the content pointed by your int *a field, you will need to copy the whole memory related to it. Thus, you will need a shared memory that can hold at least size_t shm_size = sizeof(struct ex) + get_the_length_of_your_ex();.
From now on, since you mentioned shmget and shmat, I will assume you run a Linux system.
The first step is the shared memory segment creation. It would be a good thing if you can determine an upper bound to the size of the int *a content. This way you would not have to create/delete the shared memory segment over and over again. But if you do so, an extra overhead to state how long is the actual data will be needed. I will assume that a simple size_t will do the trick for this purpose.
Then, after you created your segment, you must set the data correctly to make it hold what you want. Notice that while the physical address of the memory segment is always the same, when calling shmat you will get virtual pointers, which are only usable in the process that called shmat. The example code below should give you some tricks to do so.
#include <sys/types.h>
#include <sys/ipc.h>
/* Assume a cannot point towards an area larger than 4096 bytes. */
#define A_MAX_SIZE (size_t)4096
struct ex {
int *a;
int b;
int c;
}
int shm_create(void)
{
/*
* If you need to share other structures,
* You'll need to pass the key_t as an argument
*/
key_t k = ftok("/a/path/of/yours");
int shm_id = 0;
if (0 > (shm_id = shmget(
k, sizeof(struct ex) + A_MAX_SIZE + sizeof(size_t), IPC_CREAT|IPC_EXCL|0666))) {
/* An error occurred, add desired error handling. */
}
return shm_id;
}
/*
* Fill the desired shared memory segment with the structure
*/
int shm_fill(int shmid, struct ex *p_ex)
{
void *p = shmat(shmid, NULL, 0);
void *tmp = p;
size_t data_len = get_my_ex_struct_data_len(p_ex);
if ((void*)(-1) == p) {
/* Add desired error handling */
return -1;
}
memcpy(tmp, p_ex, sizeof(struct ex));
tmp += sizeof(struct ex);
memcpy(tmp, &data_len, sizeof(size_t);
tmp += 4;
memcpy(tmp, p_ex->a, data_len);
shmdt(p);
/*
* If you want to keep the reference so that
* When modifying p_ex anywhere, you update the shm content at the same time :
* - Don't call shmdt()
* - Make p_ex->a point towards the good area :
* p_ex->a = p + sizeof(struct ex) + sizeof(size_t);
* Never ever modify a without detaching the shm ...
*/
return 0;
}
/* Get the ex structure from a shm segment */
int shm_get_ex(int shmid, struct ex *p_dst)
{
void *p = shmat(shmid, NULL, SHM_RDONLY);
void *tmp;
size_t data_len = 0;
if ((void*)(-1) == p) {
/* Error ... */
return -1;
}
data_len = *(size_t*)(p + sizeof(struct ex))
if (NULL == (tmp = malloc(data_len))) {
/* No memory ... */
shmdt(p);
return -1;
}
memcpy(p_dst, p, sizeof(struct ex));
memcpy(tmp, (p + sizeof(struct ex) + sizeof(size_t)), data_len);
p_dst->a = tmp;
/*
* If you want to modify "globally" the structure,
* - Change SHM_RDONLY to 0 in the shmat() call
* - Make p_dst->a point to the good offset :
* p_dst->a = p + sizeof(struct ex) + sizeof(size_t);
* - Remove from the code above all the things made with tmp (malloc ...)
*/
return 0;
}
/*
* Detach the given p_ex structure from a shm segment.
* This function is useful only if you use the shm segment
* in the way I described in comment in the other functions.
*/
void shm_detach_struct(struct ex *p_ex)
{
/*
* Here you could :
* - alloc a local pointer
* - copy the shm data into it
* - detach the segment using the current p_ex->a pointer
* - assign your local pointer to p_ex->a
* This would save locally the data stored in the shm at the call
* Or if you're lazy (like me), just detach the pointer and make p_ex->a = NULL;
*/
shmdt(p_ex->a - sizeof(struct ex) - sizeof(size_t));
p_ex->a = NULL;
}
Excuse my laziness, it would be space-optimized to not copy at all the value of the int *a pointer of the struct ex since it is completely unused in the shared memory, but I spared myself extra-code to handle this (and some pointer checkings like the p_ex arguments integrity).
But when you are done, you must find a way to share the shm ID between your processes. This could be done using sockets, pipes ... Or using ftok with the same input.
The memory you allocate to a pointer using malloc() is private to that process. So, when you try to access the pointer in another process(other than the process which malloced it) you are likely going to access an invalid memory page or a memory page mapped in another process address space. So, you are likely to get a segfault.
If you are using the shared memory, you must make sure all the data you want to expose to other processes is "in" the shared memory segment and not private memory segments of the process.
You could try, leaving the data at a specified offset in the memory segment, which can be concretely defined at compile time or placed in a field at some known location in the shared memory segment.
Eg:
If you are doing this
char *mem = shmat(shmid2, (void*)0, 0);
// So, the mystruct type is at offset 0.
mystruct *structptr = (mystruct*)mem;
// Now we have a structptr, use an offset to get some other_type.
other_type *other = (other_type*)(mem + structptr->offset_of_other_type);
Other way would be to have a fixed size buffer to pass the information using the shared memory approach, instead of using the dynamically allocated pointer.
Hope this helps.
Are you working in Windows or Linux?
In any case what you need is a memory mapped file. Documentation with code examples here,
http://msdn.microsoft.com/en-us/library/aa366551%28VS.85%29.aspx
http://menehune.opt.wfu.edu/Kokua/More_SGI/007-2478-008/sgi_html/ch03.html
You need to use shared memory/memory mapped files/whatever your OS gives you.
In general, IPC and sharing memory between processes is quite OS dependent, especially in low-level languages like C (higher-level languages usually have libraries for that - for example, even C++ has support for it using boost).
If you are on Linux, I usually use shmat for small amount, and mmap (http://en.wikipedia.org/wiki/Mmap) for larger amounts.
On Win32, there are many approaches; the one I prefer is usually using page-file backed memory mapped files (http://msdn.microsoft.com/en-us/library/ms810613.aspx)
Also, you need to pay attention to where you are using these mechanism inside your data structures: as mentioned in the comments, without using precautions the pointer you have in your "source" process is invalid in the "target" process, and needs to be replaced/adjusted (IIRC, pointers coming from mmap are already OK(mapped); at least, under windows pointers you get out of MapViewOfFile are OK).
EDIT: from your edited example:
What you do here:
e = (ex*)shmat(mid, NULL, 0);
(other process)
int shmid = shmget(key, sizeof(ex), 0);
ex* e = (ex*)shmat(shmid, NULL, 0);
is correcty, but you need to do it for each pointer you have, not only for the "main" pointer to the struct. E.g. you need to do:
e->a = (int*)shmat(shmget(another_key, dim_of_a, IPC_CREAT | 0666), NULL, 0);
instead of creating the array with malloc.
Then, on the other process, you also need to do shmget/shmat for the pointer.
This is why, in the comments, I said that I usually prefer to pack the structs: so I do not need to go through the hassle to to these operations for every pointer.
Convert the struct:
typedef struct {
int b;
int c;
int a[];
} ex;
and then on parent process:
int mid = shmget(key, sizeof(ex) + arraysize*sizeof(int), 0666);
it should work.
In general, it is difficult to work with dynamic arrays inside structs in c, but in this way you are able to allocate the proper memory (this will also work in malloc: How to include a dynamic array INSIDE a struct in C?)

Problem with setjmp/longjmp

The code below is just not working.
Can anybody point out why
#define STACK_SIZE 1524
static void mt_allocate_stack(struct thread_struct *mythrd)
{
unsigned int sp = 0;
void *stck;
stck = (void *)malloc(STACK_SIZE);
sp = (unsigned int)&((stck));
sp = sp + STACK_SIZE;
while((sp % 8) != 0)
sp--;
#ifdef linux
(mythrd->saved_state[0]).__jmpbuf[JB_BP] = (int)sp;
(mythrd->saved_state[0]).__jmpbuf[JB_SP] = (int)sp-500;
#endif
}
void mt_sched()
{
fprintf(stdout,"\n Inside the mt_sched");
fflush(stdout);
if ( current_thread->state == NEW )
{
if ( setjmp(current_thread->saved_state) == 0 )
{
mt_allocate_stack(current_thread);
fprintf(stdout,"\n Jumping to thread = %u",current_thread->thread_id);
fflush(stdout);
longjmp(current_thread->saved_state, 2);
}
else
{
new_fns();
}
}
}
All I am trying to do is to run the new_fns() on a new stack. But is is showing segmentation fault at new_fns().
Can anybody point me out what's wrong.
Apart all other considerations, you are using "&stck" instead ok "stck" as stack! &stck points to the cell containing the POINTER TO the allocated stack
Then, some observations:
1) setjmp is not intended for this purpose: this code may work only on some systems, and perhaps only with som runtime library versions.
2) I think that BP should be evaluated in some other way. I suggest to check how you compiled composes a stack frame. I.e., on x86 platforms EBP points to the base of the local context, and at *EBP you can find the address of the base of the calling context. ESP points to EBP-SIZE_OF_LOCAL_CONTEXT, different compilers usually compute that size in a different way.
As far as I can see, you are implementig some sort of "fibers". If you are working on Win32, there is aready a set of function that implements in a safe way this functionality (see "fibers"). On linux I suggest you to have a look to "libfiber".
Regards

Resources