Hello,

Could anyone please comment the issue described below:
Valgrind shows "invalid write" for memory allocated on the stack while the 
program runs normally.
I've attached a reproducer for this problem,
During the run two errors show in valgrind.log,
However only the second one is relevant (is the same as the one I have in code)

There are more details in my previous posts on this subject.
Attching once again

Thank you in advance,
Masha.

-----Original Message-----
From: Masha Naret (mnaret) 
Sent: Wednesday, July 17, 2013 12:10 PM
To: 'Philippe Waroquiers'; 'lopre...@gmail.com'
Cc: 'valgrind-users@lists.sourceforge.net'; Yanai, Omer (oya...@nds.com)
Subject: RE: [Valgrind-users] Valgrind shows "Invalid write os size 4" for 
memory allocated for the stack

Hello,
Attaching the reproducer - please compile it with gcc -g tmpthread.c -o 
tmpthread -lpthread And then run: tmpthread argsFile Also attached argsFile and 
valgrind log.

There are two "Invalid write" errors in the log, but only the second one seems 
to be the same as in the original program.

Some more explanation:
In the original program I noticed valgrind reported the problem when the stack, 
while growing, grew from area with permissions 'rwx' to area with permissions 
'rw'.
The difference in premissions happened since each time thread stack is created, 
it's lower and upper part are protected with mprotect(NONE) and when it's out 
of use the protection is set back to READ | WRITE.
(exactly as in reproducer)
However, when running the program with valgrind, for some reason initially the 
all the momery is set to 'rwx'.
Which is weird, since normally the memory for the stack shouldn't have the 'x' 
permission.
When running the program without valgrind, there's no memory with 'rwx', only 
'rw'

If I modify the original program to restore also EXEC persmission, valgrind 
doesn't report any error, however this doesn't seem like a correct thing to do.
The same happens with the reproducer.
If you modify the code of the function restoring permissions to add PROT_EXEC 
persmissions :

static void ReleaseThreadStack(int stacksize, void** stackbase) {
    int ret = 0;
    void* ptStack = NULL;

    //remove protection
    ptStack = *stackbase - STACK_GUARD_SIZE;
    ret = mprotect(ptStack, STACK_GUARD_SIZE, PROT_READ | PROT_WRITE | 
PROT_EXEC );
    ptStack = *stackbase + stacksize;
    ret = mprotect(ptStack, STACK_GUARD_SIZE, PROT_READ | PROT_WRITE  | 
PROT_EXEC);

    return;
}

The second "invalid write" problem will disappear!

If there’s need of any further logs, please let me know, I’ll send you valgrind 
debugger outputs.

Thank you very much for your support,
Masha.

-----Original Message-----
From: Philippe Waroquiers [mailto:philippe.waroqui...@skynet.be]
Sent: Wednesday, June 12, 2013 10:44 PM
To: Masha Naret (mnaret)
Cc: valgrind-users@lists.sourceforge.net
Subject: Re: [Valgrind-users] Valgrind shows "Invalid write os size 4" for 
memory allocated for the stack

On Mon, 2013-06-10 at 01:23 -0700, mnaret wrote:
> Hello,
> Recently I'm getting lot's of "invalid read/invalid write" valgrind 
> errors which point out at memory allocated for the stack. However the 
> code doesn't crush and finish running successfully.
> I'm trying to understand where the error comes from - and will be 
> grateful fo any help wih this issue.
Do you have a small (compilable) reproducer ?
Philippe


Attachment: valgrind.log
Description: valgrind.log

Attachment: argsFile
Description: argsFile

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <string.h>


#define PAGE_SIZE         4096
#define STACK_GUARD_SIZE  16384
#define STACK_SIZE        32768
#define STACK_TOTAL_SIZE  524288
#define THREAD_NUM        120

static int CreateThreadStack(int stacksize, void** stackbase, void* total);
static void ReleaseThreadStack(int stacksize, void** stackbase);
void* thread_func(void* arg);
static void rec_func(int num);
static void allocateForFunc(void** ptMem);
static void FreeAllMem(void** ptMem);

void* thread_func(void* id)
{
    
    int* num;
    num = (int*)id;
//    printf("Entering rec_func with parameter %d\n", *num);
    rec_func(*num);
}

static void rec_func(int num)
{
    int i;
    int arr[num];
    for (i=0; i<num; i++)
    {
        arr[i] = i;
    }
    if (num == 0)
    {
        return;
    }
    else
    {
        //printf("Calling rec_func with %d\n", num-1);
        num = num-1;
        rec_func(num);
    }
}


int main(int argc, char *argv[])
{
    int ret = 0;
    pthread_attr_t th_attr;
    int stacksize = STACK_SIZE;
    void* stackbase;
    pthread_t threadId;
    int num = 0;
    char* filename;
    FILE *fp;
    ssize_t read = 0;
    char* line = NULL;
    size_t len = 0;
    int i, j, k;
    int status;
    void* ptMem;
    int thrInd = 0;
    

    if (argc == 2)
    {
        //open file
        fp = fopen(argv[1], "r");
        allocateForFunc(&ptMem);
        if (ptMem != NULL)
        {
            while((read = getline(&line, &len, fp)) != -1)
            {
                int i=0;
                num = atoi(line);
            
                ret = pthread_attr_init(&th_attr);
                status = CreateThreadStack(stacksize, &stackbase, ptMem);
                if (!status)
                {
                    printf("exited for num=%d\n", num);
                    pthread_attr_destroy(&th_attr);
                }
                else
                {
                    pthread_attr_setstack(&th_attr, (void *)stackbase, 
(size_t)stacksize);
                    pthread_create(&(threadId), &(th_attr), thread_func, 
(void*)(&num));

                    pthread_join(threadId, NULL);
                    ReleaseThreadStack(stacksize, &stackbase);
       
                    pthread_attr_destroy(&th_attr);
                }
            }
        }
        FreeAllMem(&ptMem);
        fclose(fp);
               
    }
    
    return 0;
}

static void allocateForFunc(void** ptMem)
{
    int ret = posix_memalign(ptMem, (size_t)PAGE_SIZE, 
(size_t)STACK_TOTAL_SIZE);
}

static void FreeAllMem(void** ptMem)
{
   free(*ptMem);    
}


static int CreateThreadStack(int stacksize, void** stackbase, void* totalPtr)
{
    int ret = 0;
    void* ptStack = NULL;
    char* error_msg[128] = {'\0'};
    int status = 1;
    static void* locPtr = NULL;
    
   
    if ((locPtr + stacksize+2*STACK_GUARD_SIZE >= totalPtr + STACK_TOTAL_SIZE) 
|| (locPtr == NULL))
    {
        locPtr = totalPtr;
    }
    ptStack = locPtr;
    *stackbase = ptStack+STACK_GUARD_SIZE;

    //protect
    ret = mprotect(ptStack, STACK_GUARD_SIZE, PROT_NONE);
    ptStack += (stacksize + STACK_GUARD_SIZE);
    ret = mprotect(ptStack, STACK_GUARD_SIZE, PROT_NONE);

    memset(*stackbase, 0, stacksize);
    printf("stackbase: %p\n", *stackbase);
    locPtr = locPtr + 4096;

    return status;

}


static void ReleaseThreadStack(int stacksize, void** stackbase)
{
    int ret = 0;
    void* ptStack = NULL;

    //remove protection
    ptStack = *stackbase - STACK_GUARD_SIZE;
    ret = mprotect(ptStack, STACK_GUARD_SIZE, PROT_READ | PROT_WRITE );
    ptStack = *stackbase + stacksize;
    ret = mprotect(ptStack, STACK_GUARD_SIZE, PROT_READ | PROT_WRITE );

    return;
}
------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk
_______________________________________________
Valgrind-users mailing list
Valgrind-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/valgrind-users

Reply via email to