diff options
author | Mark Johnston <markj@FreeBSD.org> | 2018-11-13 20:07:55 +0000 |
---|---|---|
committer | Mark Johnston <markj@FreeBSD.org> | 2018-11-13 20:07:55 +0000 |
commit | 991666adc717e4f5fdf9854f67d240a00f6eb4ab (patch) | |
tree | a7d7ec5badaee53ae02f0aa4b4d3bd8f01efc83a /lib/libnv | |
parent | 8643808a68375a3be72eb79de218f90df3614b8b (diff) | |
download | src-991666adc717e4f5fdf9854f67d240a00f6eb4ab.tar.gz src-991666adc717e4f5fdf9854f67d240a00f6eb4ab.zip |
Ensure that libnv can be used when kern.trap_enotcap=1.
libnv used fcntl(fd, F_GETFL) to test whether fd is a valid file
descriptor. Aside from being racy, this check requires CAP_FCNTL
rights on fd. Instead, use fcntl(fd, F_GETFD), which does not require
any capability rights.
Also remove some redundant fd_is_valid() checks to avoid extra system
calls; in many cases we were performing this check immediately before
dup()ing the descriptor.
Reviewed by: cem, oshogbo (previous version)
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D17963
Notes
Notes:
svn path=/head/; revision=340408
Diffstat (limited to 'lib/libnv')
-rw-r--r-- | lib/libnv/common_impl.h | 11 | ||||
-rw-r--r-- | lib/libnv/msgio.c | 5 | ||||
-rw-r--r-- | lib/libnv/tests/nvlist_send_recv_test.c | 38 |
3 files changed, 42 insertions, 12 deletions
diff --git a/lib/libnv/common_impl.h b/lib/libnv/common_impl.h index a50902d221ce..69154466203a 100644 --- a/lib/libnv/common_impl.h +++ b/lib/libnv/common_impl.h @@ -34,6 +34,15 @@ #ifndef _COMMON_IMPL_H_ #define _COMMON_IMPL_H_ -#define fd_is_valid(fd) (fcntl((fd), F_GETFL) != -1 || errno != EBADF) +#include <errno.h> +#include <fcntl.h> +#include <stdbool.h> + +static inline bool +fd_is_valid(int fd) +{ + + return (fcntl(fd, F_GETFD) != -1 || errno != EBADF); +} #endif /* !_COMMON_IMPL_H_ */ diff --git a/lib/libnv/msgio.c b/lib/libnv/msgio.c index 300a437a7421..938bca81b0ac 100644 --- a/lib/libnv/msgio.c +++ b/lib/libnv/msgio.c @@ -66,11 +66,6 @@ msghdr_add_fd(struct cmsghdr *cmsg, int fd) PJDLOG_ASSERT(fd >= 0); - if (!fd_is_valid(fd)) { - errno = EBADF; - return (-1); - } - cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(fd)); diff --git a/lib/libnv/tests/nvlist_send_recv_test.c b/lib/libnv/tests/nvlist_send_recv_test.c index f4bc1c4464bc..1b673b5d4259 100644 --- a/lib/libnv/tests/nvlist_send_recv_test.c +++ b/lib/libnv/tests/nvlist_send_recv_test.c @@ -306,15 +306,12 @@ parent(int sock) CHECK(name == NULL); } -int -main(void) +static void +send_nvlist(void) { int status, socks[2]; pid_t pid; - printf("1..134\n"); - fflush(stdout); - if (socketpair(PF_UNIX, SOCK_STREAM, 0, socks) < 0) err(1, "socketpair() failed"); pid = fork(); @@ -326,7 +323,7 @@ main(void) /* Child. */ close(socks[0]); child(socks[1]); - return (0); + _exit(0); default: /* Parent. */ close(socks[1]); @@ -336,6 +333,35 @@ main(void) if (waitpid(pid, &status, 0) < 0) err(1, "waitpid() failed"); +} + +static void +send_closed_fd(void) +{ + nvlist_t *nvl; + int error, socks[2]; + + if (socketpair(PF_UNIX, SOCK_STREAM, 0, socks) < 0) + err(1, "socketpair() failed"); + + nvl = nvlist_create(0); + nvlist_add_descriptor(nvl, "fd", 12345); + error = nvlist_error(nvl); + CHECK(error == EBADF); + + error = nvlist_send(socks[1], nvl); + CHECK(error != 0 && errno == EBADF); +} + +int +main(void) +{ + + printf("1..136\n"); + fflush(stdout); + + send_nvlist(); + send_closed_fd(); return (0); } |