Writing to text segment

R

rahul

void foo(void) {
/* blah blah */
}

char buf[] = {....};
memcpy( (void *)&foo, buf, sizeof buf);

This thing is giving segmentation fault on RHEL 5/gcc 4.1. Is the text
segment protected? I am assuming foo has enough space for buf.
 
I

Ian Collins

rahul said:
void foo(void) {
/* blah blah */
}

char buf[] = {....};
memcpy( (void *)&foo, buf, sizeof buf);

This thing is giving segmentation fault on RHEL 5/gcc 4.1. Is the text
segment protected? I am assuming foo has enough space for buf.

I'm amazed you even managed to get it, what ever it is, to compile.

Post real code.
 
A

Antoninus Twink

This thing is giving segmentation fault on RHEL 5/gcc 4.1. Is the text
segment protected?

$ objdump -h a

a: file format elf32-i386

Sections:
Idx Name Size VMA LMA File off Algn
[snip]
12 .text 0000016c 080482f0 080482f0 000002f0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
[snip]

Yes, on sane operating systems the text segment does seem to be
read-only. Maybe your hacking attempts will fare better on Windows.
 
J

Jens Thoms Toerring

rahul said:
void foo(void) {
/* blah blah */
}
char buf[] = {....};
memcpy( (void *)&foo, buf, sizeof buf);
This thing is giving segmentation fault on RHEL 5/gcc 4.1. Is the text
segment protected? I am assuming foo has enough space for buf.

It invokes undefined behaviour by trying to write to memory you
don't own (the code for your program belong into this category).
(And a conversion between function and object pointers is also
not an operation defined by the C standard). One possible result
is that you get a segmentation fault. On a different system it
may work. So the answer is system-specific and thus better be
discussed in the appropriate group.

And yes, protecting the code from getting overwritten is usually
a good thing since it safes you from your worst mistakes. Self-
mofifying code inherently makes your program unportable and
thus system-specific, so it's reasonable not to bless it with
some special permission in the C standard. If it's possible on
a system let the implementation define the undefined behaviour.

Regards, Jens
 
R

rahul

rahul said:
void foo(void) {
/* blah blah */
}
char buf[] = {....};
memcpy( (void *)&foo, buf, sizeof buf);
This thing is giving segmentation fault on RHEL 5/gcc 4.1. Is the text
segment protected? I am assuming foo has enough space for buf.

I'm amazed you even managed to get it, what ever it is, to compile.

Post real code.

The code is real, just abridged. Would you elaborate why this should
not compile?
 
R

rahul

This thing is giving segmentation fault on RHEL 5/gcc 4.1. Is the text
segment protected?

$ objdump -h a

a: file format elf32-i386

Sections:
Idx Name Size VMA LMA File off Algn
[snip]
12 .text 0000016c 080482f0 080482f0 000002f0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
[snip]

Yes, on sane operating systems the text segment does seem to be
read-only. Maybe your hacking attempts will fare better on Windows.

Yup, objdump says .text is read only. Actually execution in .data
segment
generates fault in almost all architectures I have seen (including
Windows XP
;starting from SP2 - its called Data Execution Prevention). So, I
thought
may be self-modifying code can do the trick.
 
S

santosh

rahul said:
rahul said:
void foo(void) {
/* blah blah */
}
char buf[] = {....};
memcpy( (void *)&foo, buf, sizeof buf);
This thing is giving segmentation fault on RHEL 5/gcc 4.1. Is the
text segment protected? I am assuming foo has enough space for buf.

I'm amazed you even managed to get it, what ever it is, to compile.

Post real code.
The code is real, just abridged. Would you elaborate why this should
not compile?

Because it won't compile?

For short programs (especially when the OP does not know the exact place
where the bug first occurs), this group generally prefers a complete,
compilable program to be posted. This way the regulars can compile it
themselves; compiler diagnostics are a great help in troubleshooting.
Except it a minority of cases, it's very hard to pinpoint errors from
isolated code fragments, unless fortuitously, the error just happens to
be within the fragment. Even in that case the actual observed bug may
have been caused by other errors upstream.
 
R

rahul

rahul said:
rahul wrote:
void foo(void) {
/* blah blah */
}
char buf[] = {....};
memcpy( (void *)&foo, buf, sizeof buf);
This thing is giving segmentation fault on RHEL 5/gcc 4.1. Is the
text segment protected? I am assuming foo has enough space for buf.
I'm amazed you even managed to get it, what ever it is, to compile.
Post real code.
The code is real, just abridged. Would you elaborate why this should
not compile?

Because it won't compile?

For short programs (especially when the OP does not know the exact place
where the bug first occurs), this group generally prefers a complete,
compilable program to be posted. This way the regulars can compile it
themselves; compiler diagnostics are a great help in troubleshooting.
Except it a minority of cases, it's very hard to pinpoint errors from
isolated code fragments, unless fortuitously, the error just happens to
be within the fragment. Even in that case the actual observed bug may
have been caused by other errors upstream.


/* BEGIN bar.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SIZE 100

/* Just allocating enough space for copying */
int
bar (void) {
volatile int i = 1;
i = 2;
i = 3;
i = 4;
i = 5;
i = 6;
return i;
}

int
main (void) {
int fd = fopen ("foo.o", O_RDONLY);
int nread = 0;
int ret;
char buf[SIZE];
nread = read (fd, buf, SIZE);
memcpy ( (void *)&bar, (void *)buf, SIZE);
ret = bar();
return 0;
}

/* BEGIN foo.c */
int
foo (void) {
return 1;
}
/* foo.c compiled as Position Independent Code */

Is it good enough for you? This thing is just the skeleton of the real
code.

My problem was not related to compiling or running the program. My
question was about
the behavior as per standards when one writes to .text segment. I
already have got the answer.
..text is read-only ( at least in linux).
And can you tell me now why it is not supposed to compile?
 
I

Ian Collins

rahul said:
rahul said:
rahul wrote:
void foo(void) {
/* blah blah */
}
char buf[] = {....};
memcpy( (void *)&foo, buf, sizeof buf);
This thing is giving segmentation fault on RHEL 5/gcc 4.1. Is the
text segment protected? I am assuming foo has enough space for buf.
I'm amazed you even managed to get it, what ever it is, to compile.
Post real code.
The code is real, just abridged. Would you elaborate why this should
not compile?
Because it won't compile?

For short programs (especially when the OP does not know the exact place
where the bug first occurs), this group generally prefers a complete,
compilable program to be posted. This way the regulars can compile it
themselves; compiler diagnostics are a great help in troubleshooting.
Except it a minority of cases, it's very hard to pinpoint errors from
isolated code fragments, unless fortuitously, the error just happens to
be within the fragment. Even in that case the actual observed bug may
have been caused by other errors upstream.


/* BEGIN bar.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define SIZE 100

/* Just allocating enough space for copying */
int
bar (void) {
volatile int i = 1;
i = 2;
i = 3;
i = 4;
i = 5;
i = 6;
return i;
}

int
main (void) {
int fd = fopen ("foo.o", O_RDONLY);
int nread = 0;
int ret;
char buf[SIZE];
nread = read (fd, buf, SIZE);
memcpy ( (void *)&bar, (void *)buf, SIZE);
ret = bar();
return 0;
}

/* BEGIN foo.c */
int
foo (void) {
return 1;
}
/* foo.c compiled as Position Independent Code */

Is it good enough for you? This thing is just the skeleton of the real
code.
No, try again.

x.c: In function 'main':
x.c:21: error: 'O_RDONLY' undeclared (first use in this function)
x.c:21: error: (Each undeclared identifier is reported only once
x.c:21: error: for each function it appears in.)
x.c:21: warning: initialization makes integer from pointer without a cast
x.c:25: warning: implicit declaration of function 'read'
x.c:26: warning: ISO C forbids conversion of function pointer to object
pointer type
My problem was not related to compiling or running the program. My
question was about
the behavior as per standards when one writes to .text segment. I
already have got the answer.

The behaviour is undefined, the standard makes no mention of .text
segments, or any other segment.
 
R

rahul

rahul said:
rahul wrote:
rahul wrote:
void foo(void) {
/* blah blah */
}
char buf[] = {....};
memcpy( (void *)&foo, buf, sizeof buf);
This thing is giving segmentation fault on RHEL 5/gcc 4.1. Is the
text segment protected? I am assuming foo has enough space for buf.
I'm amazed you even managed to get it, what ever it is, to compile.
Post real code.
The code is real, just abridged. Would you elaborate why this should
not compile?
Because it won't compile?
For short programs (especially when the OP does not know the exact place
where the bug first occurs), this group generally prefers a complete,
compilable program to be posted. This way the regulars can compile it
themselves; compiler diagnostics are a great help in troubleshooting.
Except it a minority of cases, it's very hard to pinpoint errors from
isolated code fragments, unless fortuitously, the error just happens to
be within the fragment. Even in that case the actual observed bug may
have been caused by other errors upstream.
/* BEGIN bar.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
/* Just allocating enough space for copying */
int
bar (void) {
volatile int i = 1;
i = 2;
i = 3;
i = 4;
i = 5;
i = 6;
return i;
}
int
main (void) {
int fd = fopen ("foo.o", O_RDONLY);

fd is the wrong type.

FILE *fopen(const char * filename, const char * mode);

O_RDONLY isn't a portable macro. I don't have it.
int nread = 0;
int ret;
char buf[SIZE];
nread = read (fd, buf, SIZE);

read() isn't a portable function. I don't have it.
memcpy ( (void *)&bar, (void *)buf, SIZE);

&bar doesn't point to an object.

N869
7.21.2 Copying functions
7.21.2.1 The memcpy function

[#2] The memcpy function copies n characters from the object
pointed to by s2 into the object pointed to by s1.
ret = bar();
return 0;
}

Folks,
I didn't compile this code. I wrote it just like that to make the
context clear. Forgot a few headers ,wrote "fopen" instead of "open"
and
wrote it in GNU C rather than standard C.
Anyways, I will mark the code as not tested the next time.

So, to conclude, functions aren't objects and that makes memcpy
undefined. Apart from that, is there anything about execution part.
Say I manually
copy the bytes to location pointed by bar and then try to execute it.
 
I

Ian Collins

rahul said:
Folks,
I didn't compile this code. I wrote it just like that to make the
context clear. Forgot a few headers ,wrote "fopen" instead of "open"
and
wrote it in GNU C rather than standard C.
Anyways, I will mark the code as not tested the next time.
You should know better here in the home of the grumpy old men!
So, to conclude, functions aren't objects and that makes memcpy
undefined. Apart from that, is there anything about execution part.
Say I manually
copy the bytes to location pointed by bar and then try to execute it.
Completely undefined.

Some systems have code in ROM....

Some systems really do have incompatible function and data pointers.
 
W

Willem

Ian wrote:
) rahul wrote:
)>
)> Folks,
)> I didn't compile this code. I wrote it just like that to make the
)> context clear. Forgot a few headers ,wrote "fopen" instead of "open"
)> and
)> wrote it in GNU C rather than standard C.
)> Anyways, I will mark the code as not tested the next time.
)>
) You should know better here in the home of the grumpy old men!
)
)> So, to conclude, functions aren't objects and that makes memcpy
)> undefined. Apart from that, is there anything about execution part.
)> Say I manually
)> copy the bytes to location pointed by bar and then try to execute it.
)>
) Completely undefined.
)
) Some systems have code in ROM....
)
) Some systems really do have incompatible function and data pointers.

Some systems run on C interpreters, instead of compilers.


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
S

santosh

rahul wrote:

My problem was not related to compiling or running the program. My
question was about the behavior as per standards when one writes
to .text segment.

That's impossible to answer because the standard makes no mention of
the ".text" segment or any other segment for that matter. The standard
places few constraints on the runtime environment.
I already have got the answer. .text is read-only ( at least in
linux).

Yes. The behaviour of your program will vary with each implementation
simply because you are relying on features and guarantees that are
beyond standard C. On some systems for example your program will fail
to compile. On some systems it may compile but trigger a fault on being
run. On yet other systems it will compile and execute successfully. Any
other behaviour is also possible.
And can you tell me now why it is not supposed to compile?

What Ian Collins said won't compile was your _code_ _fragment_ posted
earlier. _This_ program may or may not compile. There is no way for us
to say, since it invokes undefined behaviour.
 
F

Flash Gordon

Willem wrote, On 11/06/08 09:36:
Ian wrote:
) rahul wrote:
)>
)> Folks,
)> I didn't compile this code. I wrote it just like that to make the
)> context clear. Forgot a few headers ,wrote "fopen" instead of "open"
)> and
)> wrote it in GNU C rather than standard C.
)> Anyways, I will mark the code as not tested the next time.
)>
) You should know better here in the home of the grumpy old men!
)
)> So, to conclude, functions aren't objects and that makes memcpy
)> undefined. Apart from that, is there anything about execution part.
)> Say I manually
)> copy the bytes to location pointed by bar and then try to execute it.
)>
) Completely undefined.
)
) Some systems have code in ROM....
)
) Some systems really do have incompatible function and data pointers.

Some systems run on C interpreters, instead of compilers.

Some systems have completely separate memory spaces for code and data.
So if your function foo is at address 0x400 and you try to read address
0x400 using a pointer you might get the contents of array bar which just
happens to have the same address!

The C standard leaves any attempt to convert between function pointers
and object (data) pointers undefined, so before you get as far as trying
to copy a function or call an array you have to invoke undefined behaviour.

I.e. there is absolutely no way to get even vaguely close to what the OP
wants without invoking undefined behaviour.

I.e. the OP should give up on standard C and go individually to the
groups for all the systems of interest and ask in each one how to do
what s/he wants.
 
W

Walter Roberson

Flash Gordon said:
The C standard leaves any attempt to convert between function pointers
and object (data) pointers undefined, so before you get as far as trying
to copy a function or call an array you have to invoke undefined behaviour.
I.e. there is absolutely no way to get even vaguely close to what the OP
wants without invoking undefined behaviour.

That second paragraph is not -exactly- true, at least not in C89.

In C89, the direction conversion between function pointers and
object pointers is left undefined, and like you say, that would
be "undefined behaviour".

However! If the function pointer is converted to an integer, and
the integer is then converted to an object pointer, then that would
be two operations that C89 explicitly permits, with both operation
having *implementation defined* behaviour. Thus, if one proceeds
that way, that would be "an attempt to convert between function
pointers and object (data) pointers", and it would only involve
implementation-defined behaviour rather than undefined behaviour.

Of course, implementation-defined behaviour is not necessarily
going to be -useful- behaviour. On a Harvard architecture it
would not be at all unreasonable that the result of this
conversion of a function pointer by way of an integer would be
a rogue pointer into data space rather than anything to do with
program space. So it is by no means a portable operation sequence.


(Yup, I have my fair share of confusion and mis-speaking about
"undefined behaviour" versus "implementation-defined behaviour".
This particular behaviour just happened to be one of the ones I remembered
and had my standard at hand to check.)
 
H

Harald van Dijk

However! If the function pointer is converted to an integer, and the
integer is then converted to an object pointer, then that would be two
operations that C89 explicitly permits, with both operation having
*implementation defined* behaviour.

Neither C89 nor C99 requires any integer type (even long/intmax_t or the
unsigned variants) to be large enough to be capable of holding the
converted address of a function. When the integer type is not large enough
to hold a converted pointer type, and you try to anyway, the behaviour is
undefined. Additionally, there is no way for a C program to verify whether
any integer type is large enough.

It's true that when supported, what you described is implementation-
defined, not undefined, but after verifying that the sizes match, so is
simply using memcpy to copy a function pointer to an object pointer. In
fact, that's something a strictly conforming program can do, since a
strictly conforming program is not able to check the required width of an
integer type, but is able to check whether sizeof(fp) == sizeof(p).

Then again, both methods result in undefined behaviour when using an
object pointer to access the bytes that make up a function anyway, so if
you don't do that, there's little point in the conversion itself, and if
you do, I don't think it's necessary to keep the conversion defined if the
rest already isn't.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top