[Click Android Development] bftb0:
mainfram3 -

Here's three suggestions that might help - you'll have to do the testing though since I have an Eris :(

1) run it more often (jobs per second)

Instead of: while `true` ; do ./m6 ; done

do while ./m6 ; do : ; done

launching the executable "true" takes a lot of time - compared to using just the return value from m6 inside the shell loop you are already running.

2) Try a short timing loop with a variable delay right before the ptrace(...ATTACH) call, something like

int i,j,counts;
counts = 8 + ((unsigned) child) & 0x3; // or 32 + 0xf, or 128 + 0x1f ... you get the idea
for (i=0,j=0; i< counts; i++) { j += i }

( Note you will have to do something in the parent code later with the variable "j" to prevent the compiler from optimizing it away ... how about printf("WIN with sqrt(2*%d) delay loops\n", j)? Just make sure to do it after the ptrace() - I don't think you want any system calls between the fork() and ptrace() )

3) Try to do this with a "quiet phone" - running other things by hand will certainly have some effect... but it will be nearly impossible to reproduce by you ... or any of the crowd looking over your shoulders.

I did some timing measurements last night by compiling a few variations of code that look like

clock_gettime((clockid_t) CLOCK_REALTIME, &(ts0) );

for (i=0; i<256; i++) { do_some_thing; }

clock_gettime((clockid_t) CLOCK_REALTIME, &(ts1) );

with the following sort of results for "do_some_thing"

~55 usec/call: usleep(1) or nanosleep(20) // way too long?

~700 nsec/call: pid = getpid(); // perhaps too long?

~120 nsec/call: j += i; // in the ballpark?

Since (in principle) a 500 Mhz processor should be doing in the neighborhood of 500 opcodes per microsecond, 50 usecs seems way too long - 25,000 opcodes... so I wouldn't bother with usleep() or nanosleep(). Even the simplest of system calls, getpid(), takes nearly 1 usec (500 opcodes). Since execve() finds out about whether or not an executable file is a suid file pretty early in process of loading an executable, the race happens pretty early in the life of the child.

Since you are trying to get "inside a race", the behavior you will get will depend on everything else that is running on the phone, since the process scheduler in the kernel is trying to divide time up fairly between execution threads. So, from run to run, the delay between the fork() and ptrace() will vary randomly, (as will the amount of time the child is spending to get into its' race condition) ... but it will still have a certain "average" value.

The idea is to try and experimentally figure out what that average value of delay works best. You could hard code loop counts and recompile for each test, but it might be easier to program the executable to read a loop count out of a config file during startup - that will be a little work to code it up initially, but once you get it done it will save you time compiling and pushing.

Think of it this way - over lots of runs, you'll get a distribution of delays, maybe like a "bell curve". You want the center of the bell curve to land right in the (unknown) sweet spot of delay. Without any delay loop, perhaps the race condition is happening somewhere in the tails of that bell curve - it happens "once in a while".

Adding some "scatter" in the delay loop with that psuedo-random "child & mask" trick might only help initially - once you (experimentally) close in on an average number of counts to use in the delay loop, adding additional scatter won't help at all.

greets

bftb0