gnupg_reopen_std - descriptor state problem

NIIBE Yutaka gniibe at fsij.org
Fri Sep 7 04:58:04 CEST 2018


Hello,

Marcin Gryszkalis <mg at fork.pl> wrote:
> I did some ktrace-ing and it seems that stdin has unexpected state:
> fstat(0) indicated EBADF but the desccriptor was not closed.
> After EBADF gnupg_reopen_std assumes it is closed and tries to reopen it to 
> /dev/null 
> (and in my case it gets new descriptor):
>
> 54974 gpg2     CALL  fstat(0,0x7fffffffdf70)
> 54974 gpg2     RET   fstat -1 errno 9 Bad file descriptor	
> 54974 gpg2     CALL  openat(AT_FDCWD,0x4aac8a,0<O_RDONLY>,<unused>0)
> 54974 gpg2     NAMI  "/dev/null"
> 54974 gpg2     RET   openat 5 <-- we don't get 0 but 5 (new file opened)
>
> 54974 gpg2     CALL  fstat(0x1,0x7fffffffdf70) <-- for stdout it's ok
> 54974 gpg2     STRU  struct stat {dev=74, ino=2, mode=010000, nlink=0, 
> uid=1004, gid=1003, rdev=0, atime=1536171587.677756000, 
> mtime=1536171587.677756000, ctime=1536171587.677756000, birthtime=0, 
> size=0, blksize=4096, blocks=0, flags=0x0 }
> 54974 gpg2     RET   fstat 0

Interesting.  Probably, the stdin is connected to the socket (which may
be already shutdown-ed), I don't know.

It seems that stdout is connected to named pipe, btw.

> I can't see any problems additional close() could cause - but I'm not sure 
> about all unix plaftorms. 
> Any comments?

I think that doing any operation on the fd (which retured EBADF) sounds
not healthy (even if it's close(2)).

I wonder if changes like following make sense to see if fd is valid or
not.  My theory is that fcntl is cheaper/simpler operation then fstat,
and might be better in this case.

diff --git a/common/sysutils.c b/common/sysutils.c
index 55a7ee9ec..899850403 100644
--- a/common/sysutils.c
+++ b/common/sysutils.c
@@ -552,13 +552,12 @@ void
 gnupg_reopen_std (const char *pgmname)
 {
 #if defined(HAVE_STAT) && !defined(HAVE_W32_SYSTEM)
-  struct stat statbuf;
   int did_stdin = 0;
   int did_stdout = 0;
   int did_stderr = 0;
   FILE *complain;
 
-  if (fstat (STDIN_FILENO, &statbuf) == -1 && errno ==EBADF)
+  if (fcntl (STDIN_FILENO, F_GETFD) == -1 && errno ==EBADF)
     {
       if (open ("/dev/null",O_RDONLY) == STDIN_FILENO)
 	did_stdin = 1;
@@ -566,7 +565,7 @@ gnupg_reopen_std (const char *pgmname)
 	did_stdin = 2;
     }
 
-  if (fstat (STDOUT_FILENO, &statbuf) == -1 && errno == EBADF)
+  if (fcntl (STDOUT_FILENO, F_GETFD) == -1 && errno == EBADF)
     {
       if (open ("/dev/null",O_WRONLY) == STDOUT_FILENO)
 	did_stdout = 1;
@@ -574,7 +573,7 @@ gnupg_reopen_std (const char *pgmname)
 	did_stdout = 2;
     }
 
-  if (fstat (STDERR_FILENO, &statbuf)==-1 && errno==EBADF)
+  if (fcntl (STDERR_FILENO, F_GETFD)==-1 && errno==EBADF)
     {
       if (open ("/dev/null", O_WRONLY) == STDERR_FILENO)
 	did_stderr = 1;
-- 



More information about the Gnupg-devel mailing list