[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