[oss] [Lab 03][Task 4] volatile keyword

Lucian Cojocar cojocar at rosedu.org
Tue Oct 28 22:11:49 EET 2014


On 10/28/2014 01:43 PM, Lucian Mogosanu wrote:
> On Tue, Oct 28, 2014 at 02:22:57PM +0200, Alex Teaca wrote:
>> Hello,
>>
>> I see in get_got routine that the plt_ptr, got_min and got_max
>> variables are marked with the volatile keyword.
>> What is its purpose, is there a danger  for these variables
>> to be modified, and the compiler don't see it ?
> 
> Not sure about got_min and got_max, but plt_ptr *must* be volatile. What the
> volatile keyword does is it tells the compiler to not make any assumptions
> about the data stored at that particular pointer (e.g. the compiler could make
> the assumption that the value at plt_ptr doesn't change during execution, when
> in fact it does/it may, only this is done transparently by the OS when some
> plt-linked library function gets called).
> 


got_{min,max} should not be volatile, error on our side.

The PLT is actually code (trampoline code, but still code), so plt_ptr
points to code region, no need for volatile keyword here, so another
error on our side.

The case that Lucian is mentioning relates with the GOT, the GOT is the
only one that the 'OS' changes during execution, basically, the GOT
holds the offsets (which are runtime information) of the called symbols.
For this, we *should have marked* the 'got_start' pointer volatile,
however, the code still works (even with -O3). Why is that?

Let's look at how got_start is used, after it is computed.

"""
get_got_for_sleep(void)
{
	...
	memcpy(old_got, got_start, size);
	sleep(1);
	memcpy(new_got, got_start, size);
	...
}

"""

The call of sleep function is a 'sequence point'[1], meaning that all
"the side effects of previous evaluations will have been performed".
Memcopy is not a 'pure'[2] function, meaning that it has side effects.
So this guarantees that memcpy will be actually called two times, with
got_start as second parameter. Anyway, this behavior does not need
advanced explanation.

The second usage of got_start is here:

"""
	*got_sleep = *got_puts;
	*got_kill = *got_system;

	my_func();

"""
So another sequence point.

But how we can show that volatile can be useful?

Use the code from here[3]. If you computed the offsets correctly and if
compiled with O3, the code should block when got_start is not volatile
and it should 'unblock' when got_start is volatile.

P.S. [3]s/'sleep plt'/'sleep ptr'/g
P.P.S you may want to disable ASLR in order to get the same address of
sleep function each time the binary is loaded.
P(3).S Here are some things that might go wrong with volatile[4], even
at compiler level.

Hope this helps,
Lucian

[1]http://en.wikipedia.org/wiki/Sequence_point
[2]http://en.wikipedia.org/wiki/Pure_function
[3]http://paste.debian.net/129140
[4]http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf

LucianC


More information about the oss mailing list