2017-03-18 22:14:16 +00:00
/*
* This demonstrates races : kernel may actually open other file
* than you read in the strace output .
2017-06-16 22:54:04 +00:00
* If you see a successful open of / etc / shadow ,
2017-03-18 22:14:16 +00:00
* you know you ' ve seen a race .
*
* $ gcc - Wall - O0 skodic . c - o skodic
* $ timeout 0.1 . . / strace - yeopen - o ' | grep " shadow.*= [0-9] " ' . / skodic
2000-02-01 16:12:33 +00:00
*/
2017-03-18 22:14:16 +00:00
# ifndef _GNU_SOURCE
# define _GNU_SOURCE 1
# endif
# include <errno.h>
# include <error.h>
# include <fcntl.h>
2000-02-01 16:12:33 +00:00
# include <stdio.h>
# include <stdlib.h>
2009-02-25 14:24:02 +00:00
# include <string.h>
2000-02-01 16:12:33 +00:00
# include <unistd.h>
# include <sys/mman.h>
2017-03-18 22:14:16 +00:00
int
main ( void )
2000-02-01 16:12:33 +00:00
{
2017-03-18 22:14:16 +00:00
FILE * fp = tmpfile ( ) ;
if ( ! fp )
error ( 1 , errno , " tmpfile " ) ;
int fd = fileno ( fp ) ;
size_t size = sysconf ( _SC_PAGESIZE ) ;
2009-02-25 14:24:02 +00:00
2017-03-18 22:14:16 +00:00
if ( ftruncate ( fd , size ) )
error ( 1 , errno , " ftruncate " ) ;
2009-02-25 14:24:02 +00:00
2017-03-18 22:14:16 +00:00
char * p = mmap ( NULL , size , PROT_READ | PROT_WRITE , MAP_SHARED , fd , 0 ) ;
if ( p = = MAP_FAILED )
error ( 1 , errno , " mmap " ) ;
fclose ( fp ) ;
fp = NULL ;
fd = - 1 ;
strcpy ( p , " /etc/shadow " ) ;
if ( open ( p , 0 ) > = 0 )
error ( 1 , 0 , p ) ;
pid_t pid = fork ( ) ;
if ( pid < 0 )
error ( 1 , errno , " fork " ) ;
if ( ! pid ) {
for ( ; ; ) {
strcpy ( p , " /etc/passwd " ) ;
strcpy ( p , " /etc/shadow " ) ;
2009-02-25 14:24:02 +00:00
}
} else {
2017-03-18 22:14:16 +00:00
for ( ; ; ) {
if ( ( fd = open ( p , 0 ) ) > = 0 )
2009-02-25 14:24:02 +00:00
close ( fd ) ;
2017-03-18 22:14:16 +00:00
}
2009-02-25 14:24:02 +00:00
}
return 0 ;
2000-02-01 16:12:33 +00:00
}