From ead347f898ef27e6f1ea7ba0160f57d1ee5f8823 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Fri, 9 Aug 2024 17:09:13 -0700 Subject: [PATCH 1/2] Reduce duplication in fcntl() wrapper implementation Add a function that takes a va_list argument to avoid duplication the switch statement. While touching this, also use __libsys_interposing_slot() directly instead of indirecting through __libc_interposing_slot(). --- lib/libsys/fcntl.c | 55 ++++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/lib/libsys/fcntl.c b/lib/libsys/fcntl.c index b8d837889613..124297ba1680 100644 --- a/lib/libsys/fcntl.c +++ b/lib/libsys/fcntl.c @@ -49,20 +49,19 @@ #include #include "libc_private.h" -#pragma weak fcntl -int -fcntl(int fd, int cmd, ...) +typedef int (*fcntl_func)(int, int, intptr_t); + +static int +call_fcntl(fcntl_func fn, int fd, int cmd, va_list ap) { - va_list args; intptr_t arg; - va_start(args, cmd); switch (cmd) { case F_GETLK: case F_SETLK: case F_SETLKW: case F_KINFO: - arg = va_arg(args, intptr_t); + arg = va_arg(ap, intptr_t); break; case F_GETFD: @@ -74,13 +73,26 @@ fcntl(int fd, int cmd, ...) break; default: - arg = va_arg(args, int); + arg = va_arg(ap, int); break; } + + return (fn(fd, cmd, arg)); +} + +#pragma weak fcntl +int +fcntl(int fd, int cmd, ...) +{ + va_list args; + int result; + fcntl_func fn = (fcntl_func)*__libsys_interposing_slot(INTERPOS_fcntl); + + va_start(args, cmd); + result = call_fcntl(fn, fd, cmd, args); va_end(args); - return (((int (*)(int, int, intptr_t)) - *(__libc_interposing_slot(INTERPOS_fcntl)))(fd, cmd, arg)); + return (result); } #ifdef __CHERI_PURE_CAPABILITY__ @@ -90,31 +102,12 @@ int _fcntl(int fd, int cmd, ...) { va_list args; - intptr_t arg; + int result; va_start(args, cmd); - switch (cmd) { - case F_GETLK: - case F_SETLK: - case F_SETLKW: - case F_KINFO: - arg = va_arg(args, intptr_t); - break; - - case F_GETFD: - case F_GETFL: - case F_GETOWN: - case F_GET_SEALS: - case F_ISUNIONSTACK: - arg = 0; - break; - - default: - arg = va_arg(args, int); - break; - } + result = call_fcntl(__sys_fcntl, fd, cmd, args); va_end(args); - return (__sys_fcntl(fd, cmd, arg)); + return (result); } #endif From 8da52eec1d6f8008b72995153164b27e784e88a2 Mon Sep 17 00:00:00 2001 From: Alex Richardson Date: Sun, 11 Aug 2024 09:19:00 -0700 Subject: [PATCH 2/2] Introduce vfcntl() This is a variant of fcntl that takes a va_list instead of variadic arguments and can be used to safely interpose fcntl by libraries such as epoll-shim that would otherwise have to reimplement the logic inside fcntl.c to avoid reading incorrect arguments for CheriBSD. See https://github.com/jiixyj/epoll-shim/pull/36 --- lib/libsys/Symbol.sys.map | 3 ++- lib/libsys/fcntl.2 | 3 +++ lib/libsys/fcntl.c | 18 ++++++++++++++---- sys/sys/fcntl.h | 1 + 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/lib/libsys/Symbol.sys.map b/lib/libsys/Symbol.sys.map index 36f79d6d0b72..64f0117b55e2 100644 --- a/lib/libsys/Symbol.sys.map +++ b/lib/libsys/Symbol.sys.map @@ -383,7 +383,8 @@ FBSD_1.7 { }; FBSD_1.8 { - kcmp; + kcmp; + vfcntl; }; FBSDprivate_1.0 { diff --git a/lib/libsys/fcntl.2 b/lib/libsys/fcntl.2 index b5d4abe35aeb..9a1202721f0c 100644 --- a/lib/libsys/fcntl.2 +++ b/lib/libsys/fcntl.2 @@ -37,6 +37,9 @@ .In fcntl.h .Ft int .Fn fcntl "int fd" "int cmd" "..." +.In stdarg.h +.Ft int +.Fn vfcntl "int fd" "int cmd" "va_list ap" .Sh DESCRIPTION The .Fn fcntl diff --git a/lib/libsys/fcntl.c b/lib/libsys/fcntl.c index 124297ba1680..e2047339bb9f 100644 --- a/lib/libsys/fcntl.c +++ b/lib/libsys/fcntl.c @@ -43,10 +43,12 @@ * CHERI CHANGES END */ -#include -#include #include #include + +#include +#include + #include "libc_private.h" typedef int (*fcntl_func)(int, int, intptr_t); @@ -80,16 +82,24 @@ call_fcntl(fcntl_func fn, int fd, int cmd, va_list ap) return (fn(fd, cmd, arg)); } +#pragma weak fcntl +int +vfcntl(int fd, int cmd, va_list ap) +{ + fcntl_func fn = (fcntl_func)*__libsys_interposing_slot(INTERPOS_fcntl); + + return (call_fcntl(fn, fd, cmd, ap)); +} + #pragma weak fcntl int fcntl(int fd, int cmd, ...) { va_list args; int result; - fcntl_func fn = (fcntl_func)*__libsys_interposing_slot(INTERPOS_fcntl); va_start(args, cmd); - result = call_fcntl(fn, fd, cmd, args); + result = vfcntl(fd, cmd, args); va_end(args); return (result); diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h index 143824558fc2..3e1b2b38e6e1 100644 --- a/sys/sys/fcntl.h +++ b/sys/sys/fcntl.h @@ -376,6 +376,7 @@ int open(const char *, int, ...); int creat(const char *, mode_t); int fcntl(int, int, ...); #if __BSD_VISIBLE +int vfcntl(int, int, __va_list); int flock(int, int); int fspacectl(int, int, const struct spacectl_range *, int, struct spacectl_range *);