From: Omer Anson <oaanson@gmail.com>
To: musl@lists.openwall.com
Cc: Omer Anson <oaanson@gmail.com>
Subject: [PATCH] Be more precise using va_arg in fcntl
Date: Mon, 19 Jun 2017 21:10:43 +0300 [thread overview]
Message-ID: <1497895843-4631-1-git-send-email-oaanson@gmail.com> (raw)
Currently, fcntl automatically calls va_arg with type unsigned long,
regardless of the actual invoked command, and therefore ignoring whether
such an argument exists, or its type.
According to the C standard[1][2], calling va_arg if the types do not match,
or beyond the end of the parameter list, causes an undefined behaviour.
This change modifies fcntl to try and call va_arg only when necessary,
and with the correct parameter type. It relies on the cmd argument to
know what's the expected command. In case the cmd is unknown, it falls
back to the previous behaviour.
[1] http://www.open-std.org/jtc1/sc22/wg14/www/standards
[2] http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdarg.h.html
---
src/fcntl/fcntl.c | 72 ++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 56 insertions(+), 16 deletions(-)
diff --git a/src/fcntl/fcntl.c b/src/fcntl/fcntl.c
index ce615d0..9d6b2cc 100644
--- a/src/fcntl/fcntl.c
+++ b/src/fcntl/fcntl.c
@@ -5,24 +5,40 @@
#include "syscall.h"
#include "libc.h"
+#define GET_ARG_MACRO(type) ({ \
+ va_list ap; \
+ va_start(ap, cmd); \
+ type __arg = va_arg(ap, type); \
+ va_end(ap); \
+ __arg; \
+ })
+
int fcntl(int fd, int cmd, ...)
{
- unsigned long arg;
- va_list ap;
- va_start(ap, cmd);
- arg = va_arg(ap, unsigned long);
- va_end(ap);
- if (cmd == F_SETFL) arg |= O_LARGEFILE;
- if (cmd == F_SETLKW) return syscall_cp(SYS_fcntl, fd, cmd, (void *)arg);
- if (cmd == F_GETOWN) {
+ switch (cmd) {
+ case F_GETFD:
+ case F_GETFL:
+ case F_GETSIG:
+ case F_GETLEASE:
+ case F_GET_SEALS:
+ case F_GETPIPE_SZ:
+ return syscall(SYS_fcntl, fd, cmd);
+ case F_GETOWN: {
struct f_owner_ex ex;
int ret = __syscall(SYS_fcntl, fd, F_GETOWN_EX, &ex);
- if (ret == -EINVAL) return __syscall(SYS_fcntl, fd, cmd, (void *)arg);
+ if (ret == -EINVAL) return __syscall(SYS_fcntl, fd, cmd);
if (ret) return __syscall_ret(ret);
return ex.type == F_OWNER_PGRP ? -ex.pid : ex.pid;
}
- if (cmd == F_DUPFD_CLOEXEC) {
- int ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg);
+ case F_SETFL: {
+ int arg = GET_ARG_MACRO(int);
+ arg |= O_LARGEFILE;
+ return syscall(SYS_fcntl, fd, cmd, arg);
+ }
+ case F_DUPFD_CLOEXEC: {
+ int ret;
+ int arg = GET_ARG_MACRO(int);
+ ret = __syscall(SYS_fcntl, fd, F_DUPFD_CLOEXEC, arg);
if (ret != -EINVAL) {
if (ret >= 0)
__syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC);
@@ -37,13 +53,37 @@ int fcntl(int fd, int cmd, ...)
if (ret >= 0) __syscall(SYS_fcntl, ret, F_SETFD, FD_CLOEXEC);
return __syscall_ret(ret);
}
- switch (cmd) {
- case F_SETLK:
+ case F_DUPFD:
+ case F_SETFD:
+ case F_SETSIG:
+ case F_SETLEASE:
+ case F_ADD_SEALS:
+ case F_SETOWN:
+ case F_SETPIPE_SZ:
+ case F_NOTIFY: {
+ int arg = GET_ARG_MACRO(int);
+ return syscall(SYS_fcntl, fd, cmd, arg);
+ }
case F_GETLK:
+ case F_SETLK:
+ case F_OFD_SETLK:
+ case F_OFD_GETLK: {
+ struct flock * arg = GET_ARG_MACRO(struct flock *);
+ return syscall(SYS_fcntl, fd, cmd, arg);
+ }
+ case F_OFD_SETLKW:
+ case F_SETLKW: {
+ struct flock * arg = GET_ARG_MACRO(struct flock *);
+ return syscall_cp(SYS_fcntl, fd, cmd, arg);
+ }
case F_GETOWN_EX:
- case F_SETOWN_EX:
- return syscall(SYS_fcntl, fd, cmd, (void *)arg);
- default:
+ case F_SETOWN_EX: {
+ struct f_owner_ex * arg = GET_ARG_MACRO(struct f_owner_ex *);
return syscall(SYS_fcntl, fd, cmd, arg);
}
+ default: {
+ unsigned long arg = GET_ARG_MACRO(unsigned long);
+ return syscall(SYS_fcntl, fd, cmd, arg);
+ }
+ }
}
--
2.4.11
next reply other threads:[~2017-06-19 18:10 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-06-19 18:10 Omer Anson [this message]
2017-06-21 1:08 ` Rich Felker
2017-06-21 17:22 ` Omer Anson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1497895843-4631-1-git-send-email-oaanson@gmail.com \
--to=oaanson@gmail.com \
--cc=musl@lists.openwall.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/musl/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).