bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Out of bounds va_arg access in rpl_fcntl


From: Bruno Haible
Subject: Re: Out of bounds va_arg access in rpl_fcntl
Date: Thu, 06 Sep 2018 00:19:45 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-134-generic; KDE/5.18.0; x86_64; ; )

Paul Eggert wrote:
> > I'm looking at a patch along these lines as well. I'm checking all possible
> > fcntl actions on all platforms, cross-checking with the info in their man
> > pages...
> 
> Thanks. What a pain, huh? And it'll get even more painful if the static 
> checkers 
> start checking the argument types. I can see Eric's point that it's not worth 
> the hassle.

It's not only about static checkers. The point is:
  1) C does not have a built-in mechanism for optional arguments.
     Therefore in order to know what arguments to consume, you MUST
     look at the values of the previous arguments. (Like with fprintf.)
  2) KLEE is not the first virtual machine that executes compiled C.
     There are also environments in JavaScript (emscripten) and in Lisp
     that execute compiled C. Yes, none of these other arguments so far
     emulates a POSIX environment including fcntl(), therefore KLEE is
     the first one. Others may follow.

Therefore I don't think a KLEE-specific annotation is the right approach.


Here's the table of all fcntl actions I could find, that are not marked
"for internal use" only. The proposed patch is below.

-------------------------------------------------------------------------------

Known to take 0 arguments:

F_GETFD               POSIX
F_GETFL               POSIX
F_GETOWN              POSIX
F_GETSIG              Android glibc
F_GETLEASE            Android glibc
F_GETPIPE_SZ          Android glibc
F_GET_SEALS           Android
F_CLOSEM              HP-UX NetBSD
F_SETFIFOENH          HP-UX
F_FULLFSYNC           Mac OS X
F_FREEZE_FS           Mac OS X
F_THAW_FS             Mac OS X
F_GETNOSIGPIPE        Mac OS X
F_GETCONFINED         Mac OS X
F_FLUSH_DATA          Mac OS X
F_CHKCLEAN            Mac OS X
F_BARRIERFSYNC        Mac OS X
F_GETPROTECTIONCLASS  Mac OS X
F_GETPROTECTIONLEVEL  Mac OS X
F_GETDEFAULTPROTLEVEL Mac OS X
F_RECYCLE             Mac OS X
F_MAXFD               NetBSD

Known to take 1 argument (int):

F_DUPFD               POSIX
F_DUPFD_CLOEXEC       POSIX
F_SETFD               POSIX
F_SETFL               POSIX
F_SETOWN              POSIX
F_SETSIG              Android glibc
F_SETLEASE            Android glibc
F_NOTIFY              Android glibc
F_DUP2FD              AIX FreeBSD Solaris
F_DUP2FD_CLOEXEC      FreeBSD Solaris
F_DUP2FD_CLOFORK      Solaris
F_SETPIPE_SZ          Android glibc
F_ADD_SEALS           Android
F_OPLKREG             IRIX
F_OPLKACK             IRIX
F_RDAHEAD             Mac OS X
F_NOCACHE             Mac OS X
F_GLOBAL_NOCACHE      Mac OS X
F_SETNOSIGPIPE        Mac OS X
F_SETCONFINED         Mac OS X
F_NODIRECT            Mac OS X
F_SINGLE_WRITER       Mac OS X
F_CHECK_OPENEVT       Mac OS X
F_SETPROTECTIONCLASS  Mac OS X
F_MOVEDATAEXTENTS     Mac OS X
F_MAKECOMPRESSED      Mac OS X
F_SETBACKINGSTORE     Mac OS X
F_DUPFD_CLOFORK       Solaris
F_GETXFL              Solaris
F_BADFD               Solaris

Known to take 1 argument (void *):
F_GETLK               POSIX
F_SETLK               POSIX
F_SETLKW              POSIX
F_GETLK64             AIX Android glibc HP-UX IRIX
F_SETLK64             AIX Android glibc HP-UX IRIX
F_SETLKW64            AIX Android glibc HP-UX IRIX
F_SETOWN_EX           Android glibc
F_GETOWN_EX           Android glibc
F_GETOWNER_UIDS       Android
F_OFD_GETLK           Android glibc Mac OS X
F_OFD_SETLK           Android glibc Mac OS X
F_OFD_SETLKW          Android glibc Mac OS X
F_GET_RW_HINT         Android
F_SET_RW_HINT         Android
F_GET_FILE_RW_HINT    Android
F_SET_FILE_RW_HINT    Android
F_OGETLK              FreeBSD
F_OSETLK              FreeBSD
F_OSETLKW             FreeBSD
F_SETLK_REMOTE        FreeBSD
F_GETTIMES            HP-UX
F_SETTIMES            HP-UX
F_SHARE               HP-UX Solaris
F_UNSHARE             HP-UX Solaris
F_GETMAP              HP-UX
F_ADVFS_OP            HP-UX
F_SETOPLOCK           HP-UX
F_SETOPLOCKW          HP-UX
F_ALLOCSP             IRIX Solaris
F_ALLOCSP64           IRIX
F_FREESP              IRIX Minix Solaris
F_FREESP64            IRIX
F_DIOINFO             IRIX
F_FSGETXATTR          IRIX
F_FSGETXATTRA         IRIX
F_FSSETXATTR          IRIX
F_GETBMAP             IRIX
F_GETBMAPA            IRIX
F_FSSETDM             IRIX
F_RESVSP              IRIX
F_RESVSP64            IRIX
F_UNRESVSP            IRIX
F_UNRESVSP64          IRIX
F_GETBIOSIZE          IRIX
F_SETBIOSIZE          IRIX
F_FSYNC               IRIX
F_FSYNC64             IRIX
F_OPLKSTAT            IRIX
F_PREALLOCATE         Mac OS X
F_RDADVISE            Mac OS X
F_READBOOTSTRAP       Mac OS X
F_WRITEBOOTSTRAP      Mac OS X
F_LOG2PHYS            Mac OS X
F_LOG2PHYS_EXT        Mac OS X
F_GETPATH             Mac OS X
F_PATHPKG_CHECK       Mac OS X
F_ADDSIGS             Mac OS X
F_SETLKWTIMEOUT       Mac OS X
F_OFD_SETLKWTIMEOUT   Mac OS X
F_GETLKPID            Mac OS X
F_OFD_GETLKPID        Mac OS X
F_PUNCHHOLE           Mac OS X
F_TRIM_ACTIVE_FILE    Mac OS X
F_SETSIZE             Mac OS X
F_ADDFILESIGS         Mac OS X
F_ADDFILESIGS_FOR_DYLD_SIM Mac OS X
F_ADDFILESIGS_RETURN  Mac OS X
F_CHECK_LV            Mac OS X
F_TRANSCODEKEY        Mac OS X
F_GETPATH_MTMINFO     Mac OS X

Unknown:

F_TSTLK               AIX
F_CANCELLK            Android
F_RGETLK              Cygwin IRIX
F_RSETLK              Cygwin IRIX
F_RSETLKW             Cygwin IRIX
F_CNVT                Cygwin
F_UNLKSYS             Cygwin
F_SHARE_RECOVER       HP-UX
F_GETCACHEPOLICY      HP-UX
F_REMOVEOPLOCK        HP-UX
F_HAVE_OPLOCK         HP-UX
F_SETLK_CIFS          HP-UX
F_SETLKW_CIFS         HP-UX
F_ADVISE              HP-UX
F_CHKFL               IRIX Solaris
F_SETBSDLK            IRIX
F_SETBSDLKW           IRIX
F_GETOPS              IRIX
F_DMAPI               IRIX
F_GETBDSATTR          IRIX
F_SETBDSATTR          IRIX
F_GETBMAPX            IRIX
F_GETPRIO             IRIX
F_SETPRIO             IRIX
F_MARKDEPENDENCY      Mac OS X
F_GETCODEDIR          Mac OS X
F_FINDSIGS            Mac OS X
F_ISSTREAM            Solaris
F_PRIV                Solaris
F_NPRIV               Solaris
F_QUOTACTL            Solaris
F_BLOCKS              Solaris
F_BLKSIZE             Solaris
F_REVOKE              Solaris
F_HASREMOTELOCKS      Solaris
F_SETLK_NBMAND        Solaris
F_SHARE_NBMAND        Solaris

-------------------------------------------------------------------------------


2018-09-05  Bruno Haible  <address@hidden>

        fcntl: Don't access nonexistent optional argument.
        Reported by Frank Busse <address@hidden> in
        <https://lists.gnu.org/archive/html/bug-gnulib/2018-09/msg00018.html>.
        * lib/fcntl.c (rpl_fcntl): For actions that don't take an argument,
        don't consume an argument. For actions that take an 'int' argument,
        consume an 'int' argument.

diff --git a/lib/fcntl.c b/lib/fcntl.c
index be65835..261559c 100644
--- a/lib/fcntl.c
+++ b/lib/fcntl.c
@@ -405,8 +405,183 @@ rpl_fcntl (int fd, int action, /* arg */...)
     default:
       {
 #if HAVE_FCNTL
-        void *p = va_arg (arg, void *);
-        result = fcntl (fd, action, p);
+        switch (action)
+          {
+          #ifdef F_BARRIERFSYNC                  /* macOS */
+          case F_BARRIERFSYNC:
+          #endif
+          #ifdef F_CHKCLEAN                      /* macOS */
+          case F_CHKCLEAN:
+          #endif
+          #ifdef F_CLOSEM                        /* NetBSD, HP-UX */
+          case F_CLOSEM:
+          #endif
+          #ifdef F_FLUSH_DATA                    /* macOS */
+          case F_FLUSH_DATA:
+          #endif
+          #ifdef F_FREEZE_FS                     /* macOS */
+          case F_FREEZE_FS:
+          #endif
+          #ifdef F_FULLFSYNC                     /* macOS */
+          case F_FULLFSYNC:
+          #endif
+          #ifdef F_GETCONFINED                   /* macOS */
+          case F_GETCONFINED:
+          #endif
+          #ifdef F_GETDEFAULTPROTLEVEL           /* macOS */
+          case F_GETDEFAULTPROTLEVEL:
+          #endif
+          #ifdef F_GETFD                         /* POSIX */
+          case F_GETFD:
+          #endif
+          #ifdef F_GETFL                         /* POSIX */
+          case F_GETFL:
+          #endif
+          #ifdef F_GETLEASE                      /* Linux */
+          case F_GETLEASE:
+          #endif
+          #ifdef F_GETNOSIGPIPE                  /* macOS */
+          case F_GETNOSIGPIPE:
+          #endif
+          #ifdef F_GETOWN                        /* POSIX */
+          case F_GETOWN:
+          #endif
+          #ifdef F_GETPIPE_SZ                    /* Linux */
+          case F_GETPIPE_SZ:
+          #endif
+          #ifdef F_GETPROTECTIONCLASS            /* macOS */
+          case F_GETPROTECTIONCLASS:
+          #endif
+          #ifdef F_GETPROTECTIONLEVEL            /* macOS */
+          case F_GETPROTECTIONLEVEL:
+          #endif
+          #ifdef F_GET_SEALS                     /* Linux */
+          case F_GET_SEALS:
+          #endif
+          #ifdef F_GETSIG                        /* Linux */
+          case F_GETSIG:
+          #endif
+          #ifdef F_MAXFD                         /* NetBSD */
+          case F_MAXFD:
+          #endif
+          #ifdef F_RECYCLE                       /* macOS */
+          case F_RECYCLE:
+          #endif
+          #ifdef F_SETFIFOENH                    /* HP-UX */
+          case F_SETFIFOENH:
+          #endif
+          #ifdef F_THAW_FS                       /* macOS */
+          case F_THAW_FS:
+          #endif
+            /* These actions take no argument.  */
+            result = fcntl (fd, action, NULL);
+            break;
+
+          #ifdef F_ADD_SEALS                     /* Linux */
+          case F_ADD_SEALS:
+          #endif
+          #ifdef F_BADFD                         /* Solaris */
+          case F_BADFD:
+          #endif
+          #ifdef F_CHECK_OPENEVT                 /* macOS */
+          case F_CHECK_OPENEVT:
+          #endif
+          #ifdef F_DUP2FD                        /* FreeBSD, AIX, Solaris */
+          case F_DUP2FD:
+          #endif
+          #ifdef F_DUP2FD_CLOEXEC                /* FreeBSD, Solaris */
+          case F_DUP2FD_CLOEXEC:
+          #endif
+          #ifdef F_DUP2FD_CLOFORK                /* Solaris */
+          case F_DUP2FD_CLOFORK:
+          #endif
+          #ifdef F_DUPFD                         /* POSIX */
+          case F_DUPFD:
+          #endif
+          #ifdef F_DUPFD_CLOEXEC                 /* POSIX */
+          case F_DUPFD_CLOEXEC:
+          #endif
+          #ifdef F_DUPFD_CLOFORK                 /* Solaris */
+          case F_DUPFD_CLOFORK:
+          #endif
+          #ifdef F_GETXFL                        /* Solaris */
+          case F_GETXFL:
+          #endif
+          #ifdef F_GLOBAL_NOCACHE                /* macOS */
+          case F_GLOBAL_NOCACHE:
+          #endif
+          #ifdef F_MAKECOMPRESSED                /* macOS */
+          case F_MAKECOMPRESSED:
+          #endif
+          #ifdef F_MOVEDATAEXTENTS               /* macOS */
+          case F_MOVEDATAEXTENTS:
+          #endif
+          #ifdef F_NOCACHE                       /* macOS */
+          case F_NOCACHE:
+          #endif
+          #ifdef F_NODIRECT                      /* macOS */
+          case F_NODIRECT:
+          #endif
+          #ifdef F_NOTIFY                        /* Linux */
+          case F_NOTIFY:
+          #endif
+          #ifdef F_OPLKACK                       /* IRIX */
+          case F_OPLKACK:
+          #endif
+          #ifdef F_OPLKREG                       /* IRIX */
+          case F_OPLKREG:
+          #endif
+          #ifdef F_RDAHEAD                       /* macOS */
+          case F_RDAHEAD:
+          #endif
+          #ifdef F_SETBACKINGSTORE               /* macOS */
+          case F_SETBACKINGSTORE:
+          #endif
+          #ifdef F_SETCONFINED                   /* macOS */
+          case F_SETCONFINED:
+          #endif
+          #ifdef F_SETFD                         /* POSIX */
+          case F_SETFD:
+          #endif
+          #ifdef F_SETFL                         /* POSIX */
+          case F_SETFL:
+          #endif
+          #ifdef F_SETLEASE                      /* Linux */
+          case F_SETLEASE:
+          #endif
+          #ifdef F_SETNOSIGPIPE                  /* macOS */
+          case F_SETNOSIGPIPE:
+          #endif
+          #ifdef F_SETOWN                        /* POSIX */
+          case F_SETOWN:
+          #endif
+          #ifdef F_SETPIPE_SZ                    /* Linux */
+          case F_SETPIPE_SZ:
+          #endif
+          #ifdef F_SETPROTECTIONCLASS            /* macOS */
+          case F_SETPROTECTIONCLASS:
+          #endif
+          #ifdef F_SETSIG                        /* Linux */
+          case F_SETSIG:
+          #endif
+          #ifdef F_SINGLE_WRITER                 /* macOS */
+          case F_SINGLE_WRITER:
+          #endif
+            /* These actions take an 'int' argument.  */
+            {
+              int x = va_arg (arg, int);
+              result = fcntl (fd, action, x);
+            }
+            break;
+
+          default:
+            /* Other actions take a pointer argument.  */
+            {
+              void *p = va_arg (arg, void *);
+              result = fcntl (fd, action, p);
+            }
+            break;
+          }
 #else
         errno = EINVAL;
 #endif




reply via email to

[Prev in Thread] Current Thread [Next in Thread]