Fossil SCM
Further improvements to the defenses against being invoked without file descriptor 2 being open.
Commit
6dbaa67420c7c732b47a77fb59b0eab079203677
Parent
35ab16bc9e0f331…
1 file changed
+13
-4
+13
-4
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -689,14 +689,23 @@ | ||
| 689 | 689 | g.argv = zNewArgv; |
| 690 | 690 | } |
| 691 | 691 | zCmdName = g.argv[1]; |
| 692 | 692 | } |
| 693 | 693 | #ifndef _WIN32 |
| 694 | - /* Make sure open() will not return file descriptor 2. */ | |
| 695 | - { int nTry = 0; | |
| 696 | - while( !is_valid_fd(2) && nTry++ < 2 && open("/dev/null",O_WRONLY)>=0 ){} | |
| 697 | - if( !is_valid_fd(2) ){ | |
| 694 | + /* There is a bug in stunnel4 in which it sometimes starts up client | |
| 695 | + ** processes without first opening file descriptor 2 (standard error). | |
| 696 | + ** If this happens, and a subsequent open() of a database returns file | |
| 697 | + ** descriptor 2, and then an assert() fires and writes on fd 2, that | |
| 698 | + ** can corrupt the data file. To avoid this problem, make sure open() | |
| 699 | + ** will never return file descriptor 2 or less. */ | |
| 700 | + if( !is_valid_fd(2) ){ | |
| 701 | + int nTry = 0; | |
| 702 | + int fd = 0; | |
| 703 | + while( !is_valid_fd(2) | |
| 704 | + && (nTry++)<2 | |
| 705 | + && (fd = open("/dev/null",O_WRONLY))>=0 && fd<2 ){} | |
| 706 | + if( fd<2 && !is_valid_fd(2) ){ | |
| 698 | 707 | g.cgiOutput = 1; |
| 699 | 708 | g.httpOut = stdout; |
| 700 | 709 | g.fullHttpReply = !g.isHTTP; |
| 701 | 710 | fossil_fatal("file descriptor 2 is not open"); |
| 702 | 711 | } |
| 703 | 712 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -689,14 +689,23 @@ | |
| 689 | g.argv = zNewArgv; |
| 690 | } |
| 691 | zCmdName = g.argv[1]; |
| 692 | } |
| 693 | #ifndef _WIN32 |
| 694 | /* Make sure open() will not return file descriptor 2. */ |
| 695 | { int nTry = 0; |
| 696 | while( !is_valid_fd(2) && nTry++ < 2 && open("/dev/null",O_WRONLY)>=0 ){} |
| 697 | if( !is_valid_fd(2) ){ |
| 698 | g.cgiOutput = 1; |
| 699 | g.httpOut = stdout; |
| 700 | g.fullHttpReply = !g.isHTTP; |
| 701 | fossil_fatal("file descriptor 2 is not open"); |
| 702 | } |
| 703 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -689,14 +689,23 @@ | |
| 689 | g.argv = zNewArgv; |
| 690 | } |
| 691 | zCmdName = g.argv[1]; |
| 692 | } |
| 693 | #ifndef _WIN32 |
| 694 | /* There is a bug in stunnel4 in which it sometimes starts up client |
| 695 | ** processes without first opening file descriptor 2 (standard error). |
| 696 | ** If this happens, and a subsequent open() of a database returns file |
| 697 | ** descriptor 2, and then an assert() fires and writes on fd 2, that |
| 698 | ** can corrupt the data file. To avoid this problem, make sure open() |
| 699 | ** will never return file descriptor 2 or less. */ |
| 700 | if( !is_valid_fd(2) ){ |
| 701 | int nTry = 0; |
| 702 | int fd = 0; |
| 703 | while( !is_valid_fd(2) |
| 704 | && (nTry++)<2 |
| 705 | && (fd = open("/dev/null",O_WRONLY))>=0 && fd<2 ){} |
| 706 | if( fd<2 && !is_valid_fd(2) ){ |
| 707 | g.cgiOutput = 1; |
| 708 | g.httpOut = stdout; |
| 709 | g.fullHttpReply = !g.isHTTP; |
| 710 | fossil_fatal("file descriptor 2 is not open"); |
| 711 | } |
| 712 |