From: Patrick Donnelly Date: Fri, 7 Sep 2018 21:19:38 +0000 (-0700) Subject: *: set missing CLOEXEC on opened fds X-Git-Tag: v12.2.9~49^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=refs%2Fpull%2F24310%2Fhead;p=ceph.git *: set missing CLOEXEC on opened fds Otherwise these descriptors may leak across execve() during e.g. MDS respawn. Fixes: http://tracker.ceph.com/issues/35850 Signed-off-by: Patrick Donnelly (cherry picked from commit 86dbd9e755ae0472db3d8c04bc444c502193dc13) Conflicts: CMakeLists.txt src/auth/Crypto.cc src/ceph_osd.cc src/common/CMakeLists.txt src/common/Preforker.h src/common/SubProcess.cc src/common/admin_socket.cc src/common/admin_socket_client.cc src/common/blkdev.cc src/crimson/CMakeLists.txt src/global/signal_handler.cc src/include/random.h src/include/uuid.h src/log/Log.cc src/mon/MonitorDBStore.h src/msg/simple/Accepter.cc src/os/bluestore/BlueStore.cc src/os/bluestore/bluestore_tool.cc src/os/filestore/FileStore.cc src/os/kstore/KStore.cc src/test/objectstore/test_bluefs.cc --- diff --git a/CMakeLists.txt b/CMakeLists.txt index c507dfaa2b92..69f750e5ab33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,6 +107,8 @@ CHECK_FUNCTION_EXISTS(fdatasync HAVE_FDATASYNC) CHECK_FUNCTION_EXISTS(strerror_r HAVE_STRERROR_R) CHECK_FUNCTION_EXISTS(name_to_handle_at HAVE_NAME_TO_HANDLE_AT) CHECK_FUNCTION_EXISTS(pipe2 HAVE_PIPE2) +CHECK_FUNCTION_EXISTS(accept4 HAVE_ACCEPT4) + set(CMAKE_REQUIRED_LIBRARIES pthread) CHECK_FUNCTION_EXISTS(pthread_spin_init HAVE_PTHREAD_SPINLOCK) CHECK_FUNCTION_EXISTS(pthread_set_name_np HAVE_PTHREAD_SET_NAME_NP) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 512abc24d75a..03758be2883a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -493,7 +493,6 @@ set(libcommon_files osd/OpRequest.cc common/blkdev.cc common/common_init.cc - common/pipe.c common/ceph_argparse.cc common/ceph_context.cc common/code_environment.cc diff --git a/src/auth/Crypto.cc b/src/auth/Crypto.cc index 0186b7b2255d..150052bfef17 100644 --- a/src/auth/Crypto.cc +++ b/src/auth/Crypto.cc @@ -12,6 +12,9 @@ */ #include +#include +#include + #include "Crypto.h" #ifdef USE_CRYPTOPP # include @@ -37,7 +40,7 @@ int get_random_bytes(char *buf, int len) { - int fd = TEMP_FAILURE_RETRY(::open("/dev/urandom", O_RDONLY)); + int fd = TEMP_FAILURE_RETRY(::open("/dev/urandom", O_RDONLY|O_CLOEXEC)); if (fd < 0) return -errno; int ret = safe_read_exact(fd, buf, len); diff --git a/src/ceph_osd.cc b/src/ceph_osd.cc index b2c845065854..efab291e6d9d 100644 --- a/src/ceph_osd.cc +++ b/src/ceph_osd.cc @@ -234,7 +234,7 @@ int main(int argc, const char **argv) { char fn[PATH_MAX]; snprintf(fn, sizeof(fn), "%s/type", g_conf->osd_data.c_str()); - int fd = ::open(fn, O_RDONLY); + int fd = ::open(fn, O_RDONLY|O_CLOEXEC); if (fd >= 0) { bufferlist bl; bl.read_fd(fd, 64); diff --git a/src/client/fuse_ll.cc b/src/client/fuse_ll.cc index 018653f7e6d7..5d0e81d7bb4b 100644 --- a/src/client/fuse_ll.cc +++ b/src/client/fuse_ll.cc @@ -404,7 +404,7 @@ static void fuse_ll_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name, cfuse->client->cct->_conf->fuse_multithreaded && cfuse->client->cct->_conf->fuse_syncfs_on_mksnap) { int err = 0; - int fd = ::open(cfuse->mountpoint, O_RDONLY | O_DIRECTORY); + int fd = ::open(cfuse->mountpoint, O_RDONLY | O_DIRECTORY | O_CLOEXEC); if (fd < 0) { err = errno; } else { diff --git a/src/common/HeartbeatMap.cc b/src/common/HeartbeatMap.cc index ae1f8e8faae7..f6822852da4f 100644 --- a/src/common/HeartbeatMap.cc +++ b/src/common/HeartbeatMap.cc @@ -165,7 +165,7 @@ void HeartbeatMap::check_touch_file() if (is_healthy()) { string path = m_cct->_conf->heartbeat_file; if (path.length()) { - int fd = ::open(path.c_str(), O_WRONLY|O_CREAT, 0644); + int fd = ::open(path.c_str(), O_WRONLY|O_CREAT|O_CLOEXEC, 0644); if (fd >= 0) { ::utimes(path.c_str(), NULL); ::close(fd); diff --git a/src/common/OutputDataSocket.cc b/src/common/OutputDataSocket.cc index bbee667f329f..f2244cde84b8 100644 --- a/src/common/OutputDataSocket.cc +++ b/src/common/OutputDataSocket.cc @@ -14,9 +14,9 @@ #include "common/OutputDataSocket.h" #include "common/errno.h" -#include "common/pipe.h" #include "common/safe_io.h" #include "include/compat.h" +#include "include/sock_compat.h" #include #include @@ -117,10 +117,10 @@ OutputDataSocket::~OutputDataSocket() std::string OutputDataSocket::create_shutdown_pipe(int *pipe_rd, int *pipe_wr) { int pipefd[2]; - int ret = pipe_cloexec(pipefd); - if (ret < 0) { + if (pipe_cloexec(pipefd) < 0) { + int e = errno; ostringstream oss; - oss << "OutputDataSocket::create_shutdown_pipe error: " << cpp_strerror(ret); + oss << "OutputDataSocket::create_shutdown_pipe error: " << cpp_strerror(e); return oss.str(); } @@ -142,7 +142,7 @@ std::string OutputDataSocket::bind_and_listen(const std::string &sock_path, int << (sizeof(address.sun_path) - 1); return oss.str(); } - int sock_fd = socket(PF_UNIX, SOCK_STREAM, 0); + int sock_fd = socket_cloexec(PF_UNIX, SOCK_STREAM, 0); if (sock_fd < 0) { int err = errno; ostringstream oss; @@ -150,14 +150,6 @@ std::string OutputDataSocket::bind_and_listen(const std::string &sock_path, int << "failed to create socket: " << cpp_strerror(err); return oss.str(); } - int r = fcntl(sock_fd, F_SETFD, FD_CLOEXEC); - if (r < 0) { - r = errno; - VOID_TEMP_FAILURE_RETRY(::close(sock_fd)); - ostringstream oss; - oss << "OutputDataSocket::bind_and_listen: failed to fcntl on socket: " << cpp_strerror(r); - return oss.str(); - } memset(&address, 0, sizeof(struct sockaddr_un)); address.sun_family = AF_UNIX; snprintf(address.sun_path, sizeof(address.sun_path), @@ -241,15 +233,15 @@ bool OutputDataSocket::do_accept() struct sockaddr_un address; socklen_t address_length = sizeof(address); ldout(m_cct, 30) << "OutputDataSocket: calling accept" << dendl; - int connection_fd = accept(m_sock_fd, (struct sockaddr*) &address, + int connection_fd = accept_cloexec(m_sock_fd, (struct sockaddr*) &address, &address_length); - ldout(m_cct, 30) << "OutputDataSocket: finished accept" << dendl; if (connection_fd < 0) { int err = errno; lderr(m_cct) << "OutputDataSocket: do_accept error: '" << cpp_strerror(err) << dendl; return false; } + ldout(m_cct, 30) << "OutputDataSocket: finished accept" << dendl; handle_connection(connection_fd); close_connection(connection_fd); diff --git a/src/common/Preforker.h b/src/common/Preforker.h index f6671a5d302d..a05a7dba404b 100644 --- a/src/common/Preforker.h +++ b/src/common/Preforker.h @@ -9,8 +9,10 @@ #include #include "include/assert.h" -#include "common/safe_io.h" #include "common/errno.h" +#include "common/safe_io.h" +#include "include/compat.h" +#include "include/sock_compat.h" /** * pre-fork fork/daemonize helper class @@ -34,22 +36,23 @@ public: int prefork(std::string &err) { assert(!forked); - int r = ::socketpair(AF_UNIX, SOCK_STREAM, 0, fd); std::ostringstream oss; + int r = socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, fd); if (r < 0) { - oss << "[" << getpid() << "]: unable to create socketpair: " << cpp_strerror(errno); + int e = errno; + oss << "[" << getpid() << "]: unable to create socketpair: " << cpp_strerror(e); err = oss.str(); - return r; + return (errno = e, -1); } forked = true; childpid = fork(); if (childpid < 0) { - r = -errno; - oss << "[" << getpid() << "]: unable to fork: " << cpp_strerror(errno); + int e = errno; + oss << "[" << getpid() << "]: unable to fork: " << cpp_strerror(e); err = oss.str(); - return r; + return (errno = e, -1); } if (is_child()) { ::close(fd[0]); diff --git a/src/common/admin_socket.cc b/src/common/admin_socket.cc index f5edc56472e1..62c05ce5026b 100644 --- a/src/common/admin_socket.cc +++ b/src/common/admin_socket.cc @@ -15,7 +15,6 @@ #include "common/admin_socket.h" #include "common/admin_socket_client.h" #include "common/errno.h" -#include "common/pipe.h" #include "common/safe_io.h" #include "common/version.h" #include "include/compat.h" @@ -25,6 +24,8 @@ // re-include our assert to clobber the system one; fix dout: #include "include/assert.h" +#include "include/compat.h" +#include "include/sock_compat.h" #define dout_subsys ceph_subsys_asok #undef dout_prefix @@ -121,10 +122,10 @@ AdminSocket::~AdminSocket() std::string AdminSocket::create_shutdown_pipe(int *pipe_rd, int *pipe_wr) { int pipefd[2]; - int ret = pipe_cloexec(pipefd); - if (ret < 0) { + if (pipe_cloexec(pipefd) < 0) { + int e = errno; ostringstream oss; - oss << "AdminSocket::create_shutdown_pipe error: " << cpp_strerror(ret); + oss << "AdminSocket::create_shutdown_pipe error: " << cpp_strerror(e); return oss.str(); } @@ -173,7 +174,7 @@ std::string AdminSocket::bind_and_listen(const std::string &sock_path, int *fd) << (sizeof(address.sun_path) - 1); return oss.str(); } - int sock_fd = socket(PF_UNIX, SOCK_STREAM, 0); + int sock_fd = socket_cloexec(PF_UNIX, SOCK_STREAM, 0); if (sock_fd < 0) { int err = errno; ostringstream oss; @@ -181,14 +182,6 @@ std::string AdminSocket::bind_and_listen(const std::string &sock_path, int *fd) << "failed to create socket: " << cpp_strerror(err); return oss.str(); } - int r = fcntl(sock_fd, F_SETFD, FD_CLOEXEC); - if (r < 0) { - r = errno; - VOID_TEMP_FAILURE_RETRY(::close(sock_fd)); - ostringstream oss; - oss << "AdminSocket::bind_and_listen: failed to fcntl on socket: " << cpp_strerror(r); - return oss.str(); - } memset(&address, 0, sizeof(struct sockaddr_un)); address.sun_family = AF_UNIX; snprintf(address.sun_path, sizeof(address.sun_path), @@ -299,15 +292,15 @@ bool AdminSocket::do_accept() struct sockaddr_un address; socklen_t address_length = sizeof(address); ldout(m_cct, 30) << "AdminSocket: calling accept" << dendl; - int connection_fd = accept(m_sock_fd, (struct sockaddr*) &address, + int connection_fd = accept_cloexec(m_sock_fd, (struct sockaddr*) &address, &address_length); - ldout(m_cct, 30) << "AdminSocket: finished accept" << dendl; if (connection_fd < 0) { int err = errno; lderr(m_cct) << "AdminSocket: do_accept error: '" << cpp_strerror(err) << dendl; return false; } + ldout(m_cct, 30) << "AdminSocket: finished accept" << dendl; char cmd[1024]; unsigned pos = 0; diff --git a/src/common/admin_socket_client.cc b/src/common/admin_socket_client.cc index 32eb66479c09..9886bba6c06d 100644 --- a/src/common/admin_socket_client.cc +++ b/src/common/admin_socket_client.cc @@ -12,12 +12,18 @@ * */ +#include +#include +#include +#include + #include "common/admin_socket.h" #include "common/errno.h" #include "common/safe_io.h" #include "common/admin_socket_client.h" -#include +#include "include/compat.h" +#include "include/sock_compat.h" using std::ostringstream; @@ -41,7 +47,7 @@ const char* get_rand_socket_path() static std::string asok_connect(const std::string &path, int *fd) { - int socket_fd = socket(PF_UNIX, SOCK_STREAM, 0); + int socket_fd = socket_cloexec(PF_UNIX, SOCK_STREAM, 0); if(socket_fd < 0) { int err = errno; ostringstream oss; diff --git a/src/common/buffer.cc b/src/common/buffer.cc index 5ad822f125ed..09dcc67b2797 100644 --- a/src/common/buffer.cc +++ b/src/common/buffer.cc @@ -2255,7 +2255,7 @@ void buffer::list::decode_base64(buffer::list& e) int buffer::list::read_file(const char *fn, std::string *error) { - int fd = TEMP_FAILURE_RETRY(::open(fn, O_RDONLY)); + int fd = TEMP_FAILURE_RETRY(::open(fn, O_RDONLY|O_CLOEXEC)); if (fd < 0) { int err = errno; std::ostringstream oss; @@ -2332,7 +2332,7 @@ int buffer::list::read_fd_zero_copy(int fd, size_t len) int buffer::list::write_file(const char *fn, int mode) { - int fd = TEMP_FAILURE_RETRY(::open(fn, O_WRONLY|O_CREAT|O_TRUNC, mode)); + int fd = TEMP_FAILURE_RETRY(::open(fn, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, mode)); if (fd < 0) { int err = errno; cerr << "bufferlist::write_file(" << fn << "): failed to open file: " diff --git a/src/common/compat.cc b/src/common/compat.cc index 18b75874ad05..7a6bf7212525 100644 --- a/src/common/compat.cc +++ b/src/common/compat.cc @@ -1,19 +1,34 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2011 New Dream Network + * Copyright (C) 2018 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ +#include #include #include -#include #include -#include -#include -#include #include +#include +#include +#include +#include +#include #if defined(__linux__) #include #endif -#include "include/compat.h" +#include "include/compat.h" +#include "include/sock_compat.h" #include "common/safe_io.h" // The type-value for a ZFS FS in fstatfs. @@ -76,3 +91,96 @@ int ceph_posix_fallocate(int fd, off_t offset, off_t len) { #endif } +int pipe_cloexec(int pipefd[2]) +{ +#if defined(HAVE_PIPE2) + return pipe2(pipefd, O_CLOEXEC); +#else + if (pipe(pipefd) == -1) + return -1; + + /* + * The old-fashioned, race-condition prone way that we have to fall + * back on if pipe2 does not exist. + */ + if (fcntl(pipefd[0], F_SETFD, FD_CLOEXEC) < 0) { + goto fail; + } + + if (fcntl(pipefd[1], F_SETFD, FD_CLOEXEC) < 0) { + goto fail; + } + + return 0; +fail: + int save_errno = errno; + VOID_TEMP_FAILURE_RETRY(close(pipefd[0])); + VOID_TEMP_FAILURE_RETRY(close(pipefd[1])); + return (errno = save_errno, -1); +#endif +} + + +int socket_cloexec(int domain, int type, int protocol) +{ +#ifdef SOCK_CLOEXEC + return socket(domain, type|SOCK_CLOEXEC, protocol); +#else + int fd = socket(domain, type, protocol); + if (fd == -1) + return -1; + + if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) + goto fail; + + return fd; +fail: + int save_errno = errno; + VOID_TEMP_FAILURE_RETRY(close(fd)); + return (errno = save_errno, -1); +#endif +} + +int socketpair_cloexec(int domain, int type, int protocol, int sv[2]) +{ +#ifdef SOCK_CLOEXEC + return socketpair(domain, type|SOCK_CLOEXEC, protocol, sv); +#else + int rc = socketpair(domain, type, protocol, sv); + if (rc == -1) + return -1; + + if (fcntl(sv[0], F_SETFD, FD_CLOEXEC) < 0) + goto fail; + + if (fcntl(sv[1], F_SETFD, FD_CLOEXEC) < 0) + goto fail; + + return 0; +fail: + int save_errno = errno; + VOID_TEMP_FAILURE_RETRY(close(sv[0])); + VOID_TEMP_FAILURE_RETRY(close(sv[1])); + return (errno = save_errno, -1); +#endif +} + +int accept_cloexec(int sockfd, struct sockaddr* addr, socklen_t* addrlen) +{ +#ifdef HAVE_ACCEPT4 + return accept4(sockfd, addr, addrlen, SOCK_CLOEXEC); +#else + int fd = accept(sockfd, addr, addrlen); + if (fd == -1) + return -1; + + if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) + goto fail; + + return fd; +fail: + int save_errno = errno; + VOID_TEMP_FAILURE_RETRY(close(fd)); + return (errno = save_errno, -1); +#endif +} diff --git a/src/common/config.cc b/src/common/config.cc index 88e3da9b50aa..b3a98a595f2e 100644 --- a/src/common/config.cc +++ b/src/common/config.cc @@ -59,7 +59,7 @@ int ceph_resolve_file_search(const std::string& filename_list, int ret = -ENOENT; list::iterator iter; for (iter = ls.begin(); iter != ls.end(); ++iter) { - int fd = ::open(iter->c_str(), O_RDONLY); + int fd = ::open(iter->c_str(), O_RDONLY|O_CLOEXEC); if (fd < 0) { ret = -errno; continue; diff --git a/src/common/pipe.c b/src/common/pipe.c deleted file mode 100644 index 7353cb77f79b..000000000000 --- a/src/common/pipe.c +++ /dev/null @@ -1,58 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -/* - * Ceph - scalable distributed file system - * - * Copyright (C) 2011 New Dream Network - * - * This is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1, as published by the Free Software - * Foundation. See file COPYING. - * - */ -#include "include/compat.h" - -#include -#include -#include - -int pipe_cloexec(int pipefd[2]) -{ - int ret; - -#if defined(HAVE_PIPE2) && defined(O_CLOEXEC) - ret = pipe2(pipefd, O_CLOEXEC); - if (ret == -1) - return -errno; - return 0; -#else - ret = pipe(pipefd); - if (ret == -1) - return -errno; - - /* - * The old-fashioned, race-condition prone way that we have to fall - * back on if O_CLOEXEC does not exist. - */ - ret = fcntl(pipefd[0], F_SETFD, FD_CLOEXEC); - if (ret == -1) { - ret = -errno; - goto out; - } - - ret = fcntl(pipefd[1], F_SETFD, FD_CLOEXEC); - if (ret == -1) { - ret = -errno; - goto out; - } - - return 0; - -out: - VOID_TEMP_FAILURE_RETRY(close(pipefd[0])); - VOID_TEMP_FAILURE_RETRY(close(pipefd[1])); - - return ret; -#endif -} diff --git a/src/common/pipe.h b/src/common/pipe.h deleted file mode 100644 index b57ec0cafd84..000000000000 --- a/src/common/pipe.h +++ /dev/null @@ -1,33 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -/* - * Ceph - scalable distributed file system - * - * Copyright (C) 2011 New Dream Network - * - * This is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1, as published by the Free Software - * Foundation. See file COPYING. - * - */ - -#ifndef CEPH_COMMON_PIPE_H -#define CEPH_COMMON_PIPE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/** Create a pipe and set both ends to have F_CLOEXEC - * - * @param pipefd pipe array, just as in pipe(2) - * @return 0 on success, errno otherwise - */ -int pipe_cloexec(int pipefd[2]); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/global/global_init.cc b/src/global/global_init.cc index a8d040d32fa8..126d3c59321d 100644 --- a/src/global/global_init.cc +++ b/src/global/global_init.cc @@ -395,7 +395,7 @@ void global_init_daemonize(CephContext *cct) int reopen_as_null(CephContext *cct, int fd) { - int newfd = open("/dev/null", O_RDONLY); + int newfd = open("/dev/null", O_RDONLY|O_CLOEXEC); if (newfd < 0) { int err = errno; lderr(cct) << __func__ << " failed to open /dev/null: " << cpp_strerror(err) @@ -413,6 +413,7 @@ int reopen_as_null(CephContext *cct, int fd) } // close newfd (we cloned it to target fd) VOID_TEMP_FAILURE_RETRY(close(newfd)); + // N.B. FD_CLOEXEC is cleared on fd (see dup2(2)) return 0; } diff --git a/src/global/pidfile.cc b/src/global/pidfile.cc index 14e5871872a3..6dd5a756957c 100644 --- a/src/global/pidfile.cc +++ b/src/global/pidfile.cc @@ -141,7 +141,7 @@ int pidfh::open(const md_config_t *conf) return -ENAMETOOLONG; int fd; - fd = ::open(pf_path, O_CREAT|O_RDWR, 0644); + fd = ::open(pf_path, O_CREAT|O_RDWR|O_CLOEXEC, 0644); if (fd < 0) { int err = errno; derr << __func__ << ": failed to open pid file '" diff --git a/src/global/signal_handler.cc b/src/global/signal_handler.cc index d4099e1e201e..5b28d37aa8db 100644 --- a/src/global/signal_handler.cc +++ b/src/global/signal_handler.cc @@ -231,7 +231,7 @@ struct SignalHandler : public Thread { : stop(false), lock("SignalHandler::lock") { // create signal pipe - int r = pipe(pipefd); + int r = pipe_cloexec(pipefd); assert(r == 0); r = fcntl(pipefd[0], F_SETFL, O_NONBLOCK); assert(r == 0); @@ -348,7 +348,7 @@ void SignalHandler::register_handler(int signum, signal_handler_t handler, bool safe_handler *h = new safe_handler; - r = pipe(h->pipefd); + r = pipe_cloexec(h->pipefd); assert(r == 0); r = fcntl(h->pipefd[0], F_SETFL, O_NONBLOCK); assert(r == 0); diff --git a/src/include/compat.h b/src/include/compat.h index eb384c2e1379..d9faf320647d 100644 --- a/src/include/compat.h +++ b/src/include/compat.h @@ -168,4 +168,6 @@ int ceph_posix_fallocate(int fd, off_t offset, off_t len); +int pipe_cloexec(int pipefd[2]); + #endif /* !CEPH_COMPAT_H */ diff --git a/src/include/denc.h b/src/include/denc.h index 823da640860b..0a81719e630f 100644 --- a/src/include/denc.h +++ b/src/include/denc.h @@ -92,7 +92,7 @@ struct denc_traits { snprintf(fn, sizeof(fn), \ ENCODE_STRINGIFY(ENCODE_DUMP_PATH) "/%s__%d.%x", #Type, \ getpid(), i++); \ - int fd = ::open(fn, O_WRONLY|O_TRUNC|O_CREAT, 0644); \ + int fd = ::open(fn, O_WRONLY|O_TRUNC|O_CREAT|O_CLOEXEC, 0644); \ if (fd >= 0) { \ size_t len = p.get_pos() - __denc_dump_pre; \ int r = ::write(fd, __denc_dump_pre, len); \ diff --git a/src/include/encoding.h b/src/include/encoding.h index 5dd62adce297..4889626f9097 100644 --- a/src/include/encoding.h +++ b/src/include/encoding.h @@ -139,7 +139,7 @@ WRITE_INTTYPE_ENCODER(int16_t, le16) break; \ char fn[PATH_MAX]; \ snprintf(fn, sizeof(fn), ENCODE_STRINGIFY(ENCODE_DUMP_PATH) "/%s__%d.%x", #cl, getpid(), i++); \ - int fd = ::open(fn, O_WRONLY|O_TRUNC|O_CREAT, 0644); \ + int fd = ::open(fn, O_WRONLY|O_TRUNC|O_CREAT|O_CLOEXEC, 0644); \ if (fd >= 0) { \ bufferlist sub; \ sub.substr_of(bl, pre_off, bl.length() - pre_off); \ diff --git a/src/include/sock_compat.h b/src/include/sock_compat.h index f9dc24b1ddc6..14b5efa1df2d 100644 --- a/src/include/sock_compat.h +++ b/src/include/sock_compat.h @@ -1,7 +1,19 @@ +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2018 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + */ + #ifndef CEPH_SOCK_COMPAT_H #define CEPH_SOCK_COMPAT_H #include "include/compat.h" +#include /* * This optimization may not be available on all platforms (e.g. OSX). @@ -24,4 +36,8 @@ # endif #endif +int socket_cloexec(int domain, int type, int protocol); +int socketpair_cloexec(int domain, int type, int protocol, int sv[2]); +int accept_cloexec(int sockfd, struct sockaddr* addr, socklen_t* addrlen); + #endif diff --git a/src/include/uuid.h b/src/include/uuid.h index 98ee4b70be1f..f72753d9f663 100644 --- a/src/include/uuid.h +++ b/src/include/uuid.h @@ -6,12 +6,13 @@ */ #include "encoding.h" + #include +#include #include #include #include -#include struct uuid_d { boost::uuids::uuid uuid; @@ -26,8 +27,8 @@ struct uuid_d { } void generate_random() { - boost::random::random_device rng("/dev/urandom"); - boost::uuids::basic_random_generator gen(&rng); + std::random_device rng; + boost::uuids::basic_random_generator gen(rng); uuid = gen(); } diff --git a/src/kv/MemDB.cc b/src/kv/MemDB.cc index d6af78b18270..6427f28a83a9 100644 --- a/src/kv/MemDB.cc +++ b/src/kv/MemDB.cc @@ -69,7 +69,7 @@ void MemDB::_save() dout(10) << __func__ << " Saving MemDB to file: "<< _get_data_fn().c_str() << dendl; int mode = 0644; int fd = TEMP_FAILURE_RETRY(::open(_get_data_fn().c_str(), - O_WRONLY|O_CREAT|O_TRUNC, mode)); + O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, mode)); if (fd < 0) { int err = errno; cerr << "write_file(" << _get_data_fn().c_str() << "): failed to open file: " @@ -95,7 +95,7 @@ int MemDB::_load() /* * Open file and read it in single shot. */ - int fd = TEMP_FAILURE_RETRY(::open(_get_data_fn().c_str(), O_RDONLY)); + int fd = TEMP_FAILURE_RETRY(::open(_get_data_fn().c_str(), O_RDONLY|O_CLOEXEC)); if (fd < 0) { int err = errno; cerr << "can't open " << _get_data_fn().c_str() << ": " diff --git a/src/log/Log.cc b/src/log/Log.cc index 5f7e23b4b048..88e10746cebe 100644 --- a/src/log/Log.cc +++ b/src/log/Log.cc @@ -4,6 +4,7 @@ #include "Log.h" #include +#include #include #include "common/errno.h" @@ -138,12 +139,11 @@ void Log::reopen_log_file() if (m_fd >= 0) VOID_TEMP_FAILURE_RETRY(::close(m_fd)); if (m_log_file.length()) { - m_fd = ::open(m_log_file.c_str(), O_CREAT|O_WRONLY|O_APPEND, 0644); + m_fd = ::open(m_log_file.c_str(), O_CREAT|O_WRONLY|O_APPEND|O_CLOEXEC, 0644); if (m_fd >= 0 && (m_uid || m_gid)) { - int r = ::fchown(m_fd, m_uid, m_gid); - if (r < 0) { - r = -errno; - cerr << "failed to chown " << m_log_file << ": " << cpp_strerror(r) + if (::fchown(m_fd, m_uid, m_gid) < 0) { + int e = errno; + std::cerr << "failed to chown " << m_log_file << ": " << cpp_strerror(e) << std::endl; } } diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 869f4b6d1477..38ab6996f581 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -11985,7 +11985,7 @@ int MDCache::dump_cache(boost::string_view fn, Formatter *f, dout(1) << "dump_cache to " << path << dendl; - fd = ::open(path, O_WRONLY|O_CREAT|O_EXCL, 0600); + fd = ::open(path, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, 0600); if (fd < 0) { derr << "failed to open " << path << ": " << cpp_strerror(errno) << dendl; return errno; diff --git a/src/mon/LogMonitor.cc b/src/mon/LogMonitor.cc index 2d692840ea1a..4987e67da5e7 100644 --- a/src/mon/LogMonitor.cc +++ b/src/mon/LogMonitor.cc @@ -185,7 +185,7 @@ void LogMonitor::update_from_paxos(bool *need_bootstrap) << "' logging " << p->second.length() << " bytes" << dendl; string log_file = channels.get_log_file(p->first); - int fd = ::open(log_file.c_str(), O_WRONLY|O_APPEND|O_CREAT, 0600); + int fd = ::open(log_file.c_str(), O_WRONLY|O_APPEND|O_CREAT|O_CLOEXEC, 0600); if (fd < 0) { int err = -errno; dout(1) << "unable to write to '" << log_file << "' for channel '" diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc index da1fac90edd2..9960dea46df4 100644 --- a/src/mon/Monitor.cc +++ b/src/mon/Monitor.cc @@ -5775,7 +5775,7 @@ int Monitor::write_default_keyring(bufferlist& bl) os << g_conf->mon_data << "/keyring"; int err = 0; - int fd = ::open(os.str().c_str(), O_WRONLY|O_CREAT, 0600); + int fd = ::open(os.str().c_str(), O_WRONLY|O_CREAT|O_CLOEXEC, 0600); if (fd < 0) { err = -errno; dout(0) << __func__ << " failed to open " << os.str() diff --git a/src/mon/MonitorDBStore.h b/src/mon/MonitorDBStore.h index 00e56a9d8fcd..5d3d81c00216 100644 --- a/src/mon/MonitorDBStore.h +++ b/src/mon/MonitorDBStore.h @@ -607,7 +607,7 @@ class MonitorDBStore if (!g_conf->mon_debug_dump_json) { dump_fd_binary = ::open( g_conf->mon_debug_dump_location.c_str(), - O_CREAT|O_APPEND|O_WRONLY, 0644); + O_CREAT|O_APPEND|O_WRONLY|O_CLOEXEC, 0644); if (dump_fd_binary < 0) { dump_fd_binary = -errno; derr << "Could not open log file, got " diff --git a/src/msg/Message.cc b/src/msg/Message.cc index 7763caf77cd5..629f3a6fd845 100644 --- a/src/msg/Message.cc +++ b/src/msg/Message.cc @@ -259,7 +259,7 @@ void Message::encode(uint64_t features, int crcflags) snprintf(fn, sizeof(fn), ENCODE_STRINGIFY(ENCODE_DUMP) "/%s__%d.%x", abi::__cxa_demangle(typeid(*this).name(), 0, 0, &status), getpid(), i++); - int fd = ::open(fn, O_WRONLY|O_TRUNC|O_CREAT, 0644); + int fd = ::open(fn, O_WRONLY|O_TRUNC|O_CREAT|O_CLOEXEC, 0644); if (fd >= 0) { bl.write_fd(fd); ::close(fd); diff --git a/src/msg/async/Event.cc b/src/msg/async/Event.cc index c101022882e8..35cf5ed5a907 100644 --- a/src/msg/async/Event.cc +++ b/src/msg/async/Event.cc @@ -14,6 +14,7 @@ * */ +#include "include/compat.h" #include "common/errno.h" #include "Event.h" @@ -141,9 +142,10 @@ int EventCenter::init(int n, unsigned i, const std::string &t) return 0; int fds[2]; - if (pipe(fds) < 0) { - lderr(cct) << __func__ << " can't create notify pipe" << dendl; - return -errno; + if (pipe_cloexec(fds) < 0) { + int e = errno; + lderr(cct) << __func__ << " can't create notify pipe: " << cpp_strerror(e) << dendl; + return -e; } notify_receive_fd = fds[0]; diff --git a/src/msg/async/EventEpoll.cc b/src/msg/async/EventEpoll.cc index 17f3a294659c..37b469736247 100644 --- a/src/msg/async/EventEpoll.cc +++ b/src/msg/async/EventEpoll.cc @@ -15,6 +15,7 @@ */ #include "common/errno.h" +#include #include "EventEpoll.h" #define dout_subsys ceph_subsys_ms @@ -37,6 +38,14 @@ int EpollDriver::init(EventCenter *c, int nevent) << cpp_strerror(errno) << dendl; return -errno; } + if (::fcntl(epfd, F_SETFD, FD_CLOEXEC) == -1) { + int e = errno; + ::close(epfd); + lderr(cct) << __func__ << " unable to set cloexec: " + << cpp_strerror(e) << dendl; + + return -e; + } size = nevent; diff --git a/src/msg/async/PosixStack.cc b/src/msg/async/PosixStack.cc index 5fb975ae906e..91693050950a 100644 --- a/src/msg/async/PosixStack.cc +++ b/src/msg/async/PosixStack.cc @@ -31,6 +31,7 @@ #include "common/dout.h" #include "common/simple_spin.h" #include "msg/Messenger.h" +#include "include/compat.h" #include "include/sock_compat.h" #define dout_subsys ceph_subsys_ms @@ -187,12 +188,11 @@ int PosixServerSocketImpl::accept(ConnectedSocket *sock, const SocketOptions &op assert(sock); sockaddr_storage ss; socklen_t slen = sizeof(ss); - int sd = ::accept(_fd, (sockaddr*)&ss, &slen); + int sd = accept_cloexec(_fd, (sockaddr*)&ss, &slen); if (sd < 0) { return -errno; } - handler.set_close_on_exec(sd); int r = handler.set_nonblock(sd); if (r < 0) { ::close(sd); @@ -233,7 +233,6 @@ int PosixWorker::listen(entity_addr_t &sa, const SocketOptions &opt, return -errno; } - net.set_close_on_exec(listen_sd); r = net.set_socket_options(listen_sd, opt.nodelay, opt.rcbuf_size); if (r < 0) { ::close(listen_sd); diff --git a/src/msg/async/net_handler.cc b/src/msg/async/net_handler.cc index 99ca1f32d927..4e9a2bcbec30 100644 --- a/src/msg/async/net_handler.cc +++ b/src/msg/async/net_handler.cc @@ -22,8 +22,10 @@ #include #include "net_handler.h" -#include "common/errno.h" #include "common/debug.h" +#include "common/errno.h" +#include "include/compat.h" +#include "include/sock_compat.h" #define dout_subsys ceph_subsys_ms #undef dout_prefix @@ -36,7 +38,7 @@ int NetHandler::create_socket(int domain, bool reuse_addr) int s; int r = 0; - if ((s = ::socket(domain, SOCK_STREAM, 0)) == -1) { + if ((s = socket_cloexec(domain, SOCK_STREAM, 0)) == -1) { r = errno; lderr(cct) << __func__ << " couldn't create socket " << cpp_strerror(r) << dendl; return -r; @@ -82,22 +84,6 @@ int NetHandler::set_nonblock(int sd) return 0; } -void NetHandler::set_close_on_exec(int sd) -{ - int flags = fcntl(sd, F_GETFD, 0); - if (flags < 0) { - int r = errno; - lderr(cct) << __func__ << " fcntl(F_GETFD): " - << cpp_strerror(r) << dendl; - return; - } - if (fcntl(sd, F_SETFD, flags | FD_CLOEXEC)) { - int r = errno; - lderr(cct) << __func__ << " fcntl(F_SETFD): " - << cpp_strerror(r) << dendl; - } -} - int NetHandler::set_socket_options(int sd, bool nodelay, int size) { int r = 0; diff --git a/src/msg/async/net_handler.h b/src/msg/async/net_handler.h index c4fb73ee2914..1904237724fe 100644 --- a/src/msg/async/net_handler.h +++ b/src/msg/async/net_handler.h @@ -27,7 +27,6 @@ namespace ceph { int create_socket(int domain, bool reuse_addr=false); explicit NetHandler(CephContext *c): cct(c) {} int set_nonblock(int sd); - void set_close_on_exec(int sd); int set_socket_options(int sd, bool nodelay, int size); int connect(const entity_addr_t &addr, const entity_addr_t& bind_addr); diff --git a/src/msg/async/rdma/RDMAConnectedSocketImpl.cc b/src/msg/async/rdma/RDMAConnectedSocketImpl.cc index 66dc488cccf3..38480d4a94e3 100644 --- a/src/msg/async/rdma/RDMAConnectedSocketImpl.cc +++ b/src/msg/async/rdma/RDMAConnectedSocketImpl.cc @@ -180,7 +180,6 @@ int RDMAConnectedSocketImpl::try_connect(const entity_addr_t& peer_addr, const S if (tcp_fd < 0) { return -errno; } - net.set_close_on_exec(tcp_fd); int r = net.set_socket_options(tcp_fd, opts.nodelay, opts.rcbuf_size); if (r < 0) { diff --git a/src/msg/async/rdma/RDMAServerSocketImpl.cc b/src/msg/async/rdma/RDMAServerSocketImpl.cc index 6e473d12ea7c..c1b9b0bb5e2f 100644 --- a/src/msg/async/rdma/RDMAServerSocketImpl.cc +++ b/src/msg/async/rdma/RDMAServerSocketImpl.cc @@ -17,6 +17,9 @@ #include "msg/async/net_handler.h" #include "RDMAStack.h" +#include "include/compat.h" +#include "include/sock_compat.h" + #define dout_subsys ceph_subsys_ms #undef dout_prefix #define dout_prefix *_dout << " RDMAServerSocketImpl " @@ -46,7 +49,6 @@ int RDMAServerSocketImpl::listen(entity_addr_t &sa, const SocketOptions &opt) if (rc < 0) { goto err; } - net.set_close_on_exec(server_setup_socket); rc = ::bind(server_setup_socket, sa.get_sockaddr(), sa.get_sockaddr_len()); if (rc < 0) { @@ -79,12 +81,11 @@ int RDMAServerSocketImpl::accept(ConnectedSocket *sock, const SocketOptions &opt assert(sock); sockaddr_storage ss; socklen_t slen = sizeof(ss); - int sd = ::accept(server_setup_socket, (sockaddr*)&ss, &slen); + int sd = accept_cloexec(server_setup_socket, (sockaddr*)&ss, &slen); if (sd < 0) { return -errno; } - net.set_close_on_exec(sd); int r = net.set_nonblock(sd); if (r < 0) { ::close(sd); diff --git a/src/msg/simple/Accepter.cc b/src/msg/simple/Accepter.cc index d177793c5b0c..a2c26ef19718 100644 --- a/src/msg/simple/Accepter.cc +++ b/src/msg/simple/Accepter.cc @@ -13,6 +13,7 @@ */ #include "include/compat.h" +#include "include/sock_compat.h" #include #include #include @@ -40,33 +41,19 @@ * Accepter */ -static int set_close_on_exec(int fd) -{ - int flags = fcntl(fd, F_GETFD, 0); - if (flags < 0) { - return errno; - } - if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC)) { - return errno; - } - return 0; -} - int Accepter::create_selfpipe(int *pipe_rd, int *pipe_wr) { int selfpipe[2]; - int ret = ::pipe2(selfpipe, (O_CLOEXEC|O_NONBLOCK)); - if (ret == 0) { - for (size_t i = 0; i < std::size(selfpipe); i++) { - int f = fcntl(selfpipe[i], F_GETFL); - ceph_assert(f != -1); - f = fcntl(selfpipe[i], F_SETFL, f | O_NONBLOCK); - ceph_assert(f != -1); - } - } - if (ret < 0 ) { + if (pipe_cloexec(selfpipe) < 0) { + int e = errno; lderr(msgr->cct) << __func__ << " unable to create the selfpipe: " - << cpp_strerror(errno) << dendl; - return -errno; + << cpp_strerror(e) << dendl; + return -e; + } + for (size_t i = 0; i < 2; i++) { + int rc = fcntl(selfpipe[i], F_GETFL); + assert(rc != -1); + rc = fcntl(selfpipe[i], F_SETFL, rc | O_NONBLOCK); + assert(rc != -1); } *pipe_rd = selfpipe[0]; *pipe_wr = selfpipe[1]; @@ -92,19 +79,14 @@ int Accepter::bind(const entity_addr_t &bind_addr, const set& avoid_ports) } /* socket creation */ - listen_sd = ::socket(family, SOCK_STREAM, 0); - ldout(msgr->cct,10) << __func__ << " socket sd: " << listen_sd << dendl; + listen_sd = socket_cloexec(family, SOCK_STREAM, 0); if (listen_sd < 0) { + int e = errno; lderr(msgr->cct) << __func__ << " unable to create socket: " - << cpp_strerror(errno) << dendl; - return -errno; - } - - if (set_close_on_exec(listen_sd)) { - lderr(msgr->cct) << __func__ << " unable to set_close_exec(): " - << cpp_strerror(errno) << dendl; + << cpp_strerror(e) << dendl; + return -e; } - + ldout(msgr->cct,10) << __func__ << " socket sd: " << listen_sd << dendl; // use whatever user specified (if anything) entity_addr_t listen_addr = bind_addr; @@ -337,20 +319,16 @@ void *Accepter::entry() // accept sockaddr_storage ss; socklen_t slen = sizeof(ss); - int sd = ::accept(listen_sd, (sockaddr*)&ss, &slen); + int sd = accept_cloexec(listen_sd, (sockaddr*)&ss, &slen); if (sd >= 0) { - int r = set_close_on_exec(sd); - if (r) { - ldout(msgr->cct,1) << __func__ << " set_close_on_exec() failed " - << cpp_strerror(r) << dendl; - } errors = 0; ldout(msgr->cct,10) << __func__ << " incoming on sd " << sd << dendl; msgr->add_accept_pipe(sd); } else { + int e = errno; ldout(msgr->cct,0) << __func__ << " no incoming connection? sd = " << sd - << " errno " << errno << " " << cpp_strerror(errno) << dendl; + << " errno " << e << " " << cpp_strerror(e) << dendl; if (++errors > 4) break; } diff --git a/src/msg/simple/Pipe.cc b/src/msg/simple/Pipe.cc index c0cb24fc12a7..eec90f5b0219 100644 --- a/src/msg/simple/Pipe.cc +++ b/src/msg/simple/Pipe.cc @@ -35,6 +35,7 @@ #include "auth/cephx/CephxProtocol.h" #include "auth/AuthSessionHandler.h" +#include "include/compat.h" #include "include/sock_compat.h" // Constant to limit starting sequence number to 2^31. Nothing special about it, just a big number. PLR @@ -1021,10 +1022,11 @@ int Pipe::connect() ::close(sd); // create socket? - sd = ::socket(peer_addr.get_family(), SOCK_STREAM, 0); + sd = socket_cloexec(peer_addr.get_family(), SOCK_STREAM, 0); if (sd < 0) { - rc = -errno; - lderr(msgr->cct) << "connect couldn't create socket " << cpp_strerror(rc) << dendl; + int e = errno; + lderr(msgr->cct) << "connect couldn't create socket " << cpp_strerror(e) << dendl; + rc = -e; goto fail; } diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index 61cea28cabbc..07dbe7cae33d 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -4207,7 +4207,7 @@ int BlueStore::_open_path() return -EINVAL; } assert(path_fd < 0); - path_fd = TEMP_FAILURE_RETRY(::open(path.c_str(), O_DIRECTORY)); + path_fd = TEMP_FAILURE_RETRY(::open(path.c_str(), O_DIRECTORY|O_CLOEXEC)); if (path_fd < 0) { int r = -errno; derr << __func__ << " unable to open " << path << ": " << cpp_strerror(r) @@ -4236,7 +4236,7 @@ int BlueStore::_write_bdev_label(CephContext *cct, z.zero(); bl.append(std::move(z)); - int fd = TEMP_FAILURE_RETRY(::open(path.c_str(), O_WRONLY)); + int fd = TEMP_FAILURE_RETRY(::open(path.c_str(), O_WRONLY|O_CLOEXEC)); if (fd < 0) { fd = -errno; derr << __func__ << " failed to open " << path << ": " << cpp_strerror(fd) @@ -4261,7 +4261,7 @@ int BlueStore::_read_bdev_label(CephContext* cct, string path, bluestore_bdev_label_t *label) { dout(10) << __func__ << dendl; - int fd = TEMP_FAILURE_RETRY(::open(path.c_str(), O_RDONLY)); + int fd = TEMP_FAILURE_RETRY(::open(path.c_str(), O_RDONLY|O_CLOEXEC)); if (fd < 0) { fd = -errno; derr << __func__ << " failed to open " << path << ": " << cpp_strerror(fd) @@ -4561,7 +4561,7 @@ void BlueStore::_close_alloc() int BlueStore::_open_fsid(bool create) { assert(fsid_fd < 0); - int flags = O_RDWR; + int flags = O_RDWR|O_CLOEXEC; if (create) flags |= O_CREAT; fsid_fd = ::openat(path_fd, "fsid", flags, 0644); @@ -5265,7 +5265,7 @@ int BlueStore::_setup_block_symlink_or_file( dout(20) << __func__ << " name " << name << " path " << epath << " size " << size << " create=" << (int)create << dendl; int r = 0; - int flags = O_RDWR; + int flags = O_RDWR|O_CLOEXEC; if (create) flags |= O_CREAT; if (epath.length()) { diff --git a/src/os/bluestore/KernelDevice.cc b/src/os/bluestore/KernelDevice.cc index 7e740968f3f2..e58749133271 100644 --- a/src/os/bluestore/KernelDevice.cc +++ b/src/os/bluestore/KernelDevice.cc @@ -67,13 +67,13 @@ int KernelDevice::open(const string& p) int r = 0; dout(1) << __func__ << " path " << path << dendl; - fd_direct = ::open(path.c_str(), O_RDWR | O_DIRECT); + fd_direct = ::open(path.c_str(), O_RDWR | O_DIRECT | O_CLOEXEC); if (fd_direct < 0) { r = -errno; derr << __func__ << " open got: " << cpp_strerror(r) << dendl; return r; } - fd_buffered = ::open(path.c_str(), O_RDWR); + fd_buffered = ::open(path.c_str(), O_RDWR | O_CLOEXEC); if (fd_buffered < 0) { r = -errno; derr << __func__ << " open got: " << cpp_strerror(r) << dendl; diff --git a/src/os/bluestore/NVMEDevice.cc b/src/os/bluestore/NVMEDevice.cc index 72e5db9aea31..a5fc53ab87eb 100644 --- a/src/os/bluestore/NVMEDevice.cc +++ b/src/os/bluestore/NVMEDevice.cc @@ -874,7 +874,7 @@ int NVMEDevice::open(const string& p) dout(1) << __func__ << " path " << p << dendl; string serial_number; - int fd = ::open(p.c_str(), O_RDONLY); + int fd = ::open(p.c_str(), O_RDONLY | O_CLOEXEC); if (fd < 0) { r = -errno; derr << __func__ << " unable to open " << p << ": " << cpp_strerror(r) diff --git a/src/os/bluestore/PMEMDevice.cc b/src/os/bluestore/PMEMDevice.cc index bb8ffc4d2e5b..2d62b54f989f 100644 --- a/src/os/bluestore/PMEMDevice.cc +++ b/src/os/bluestore/PMEMDevice.cc @@ -62,7 +62,7 @@ int PMEMDevice::open(const string& p) int r = 0; dout(1) << __func__ << " path " << path << dendl; - fd = ::open(path.c_str(), O_RDWR); + fd = ::open(path.c_str(), O_RDWR | O_CLOEXEC); if (fd < 0) { r = -errno; derr << __func__ << " open got: " << cpp_strerror(r) << dendl; diff --git a/src/os/bluestore/bluestore_tool.cc b/src/os/bluestore/bluestore_tool.cc index db55868692e4..1320df831b83 100644 --- a/src/os/bluestore/bluestore_tool.cc +++ b/src/os/bluestore/bluestore_tool.cc @@ -361,7 +361,7 @@ int main(int argc, char **argv) } } else { v += "\n"; - int fd = ::open(p.c_str(), O_CREAT|O_TRUNC|O_WRONLY, 0600); + int fd = ::open(p.c_str(), O_CREAT|O_TRUNC|O_WRONLY|O_CLOEXEC, 0600); if (fd < 0) { cerr << "error writing " << p << ": " << cpp_strerror(errno) << std::endl; @@ -491,7 +491,7 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } string path = out_dir + "/" + dir + "/" + file; - int fd = ::open(path.c_str(), O_CREAT|O_WRONLY|O_TRUNC, 0644); + int fd = ::open(path.c_str(), O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC, 0644); if (fd < 0) { r = -errno; cerr << "open " << path << " failed: " << cpp_strerror(r) << std::endl; diff --git a/src/os/filestore/BtrfsFileStoreBackend.cc b/src/os/filestore/BtrfsFileStoreBackend.cc index 8718432ec671..840dce8a592d 100644 --- a/src/os/filestore/BtrfsFileStoreBackend.cc +++ b/src/os/filestore/BtrfsFileStoreBackend.cc @@ -69,7 +69,7 @@ int BtrfsFileStoreBackend::detect_features() // clone_range? if (m_filestore_btrfs_clone_range) { - int fd = ::openat(get_basedir_fd(), "clone_range_test", O_CREAT|O_WRONLY, 0600); + int fd = ::openat(get_basedir_fd(), "clone_range_test", O_CREAT|O_WRONLY|O_CLOEXEC, 0600); if (fd >= 0) { if (::unlinkat(get_basedir_fd(), "clone_range_test", 0) < 0) { r = -errno; @@ -108,7 +108,7 @@ int BtrfsFileStoreBackend::detect_features() r = -errno; dout(0) << "detect_feature: failed to create simple subvolume " << vol_args.name << ": " << cpp_strerror(r) << dendl; } - int srcfd = ::openat(get_basedir_fd(), vol_args.name, O_RDONLY); + int srcfd = ::openat(get_basedir_fd(), vol_args.name, O_RDONLY|O_CLOEXEC); if (srcfd < 0) { r = -errno; dout(0) << "detect_feature: failed to open " << vol_args.name << ": " << cpp_strerror(r) << dendl; @@ -445,7 +445,7 @@ int BtrfsFileStoreBackend::rollback_to(const string& name) snprintf(s, sizeof(s), "%s/%s", get_basedir_path().c_str(), name.c_str()); // roll back - vol_args.fd = ::open(s, O_RDONLY); + vol_args.fd = ::open(s, O_RDONLY|O_CLOEXEC); if (vol_args.fd < 0) { ret = -errno; dout(0) << "rollback_to: error opening '" << s << "': " << cpp_strerror(ret) << dendl; diff --git a/src/os/filestore/FileJournal.cc b/src/os/filestore/FileJournal.cc index 6482317fce3d..06d92339face 100644 --- a/src/os/filestore/FileJournal.cc +++ b/src/os/filestore/FileJournal.cc @@ -71,7 +71,7 @@ int FileJournal::_open(bool forwrite, bool create) << cpp_strerror(err) << dendl; } } - fd = TEMP_FAILURE_RETRY(::open(fn.c_str(), flags, 0644)); + fd = TEMP_FAILURE_RETRY(::open(fn.c_str(), flags|O_CLOEXEC, 0644)); if (fd < 0) { int err = errno; dout(2) << "FileJournal::_open unable to open journal " diff --git a/src/os/filestore/FileStore.cc b/src/os/filestore/FileStore.cc index fd7f1cc3812c..dd3d1045e2b3 100644 --- a/src/os/filestore/FileStore.cc +++ b/src/os/filestore/FileStore.cc @@ -293,7 +293,7 @@ int FileStore::lfn_open(const coll_t& cid, goto fail; } - r = ::open((*path)->path(), flags, 0644); + r = ::open((*path)->path(), flags|O_CLOEXEC, 0644); if (r < 0) { r = -errno; dout(10) << "error opening file " << (*path)->path() << " with flags=" @@ -818,7 +818,7 @@ int FileStore::mkfs() uuid_d old_omap_fsid; dout(1) << "mkfs in " << basedir << dendl; - basedir_fd = ::open(basedir.c_str(), O_RDONLY); + basedir_fd = ::open(basedir.c_str(), O_RDONLY|O_CLOEXEC); if (basedir_fd < 0) { ret = -errno; derr << __FUNC__ << ": failed to open base dir " << basedir << ": " << cpp_strerror(ret) << dendl; @@ -827,7 +827,7 @@ int FileStore::mkfs() // open+lock fsid snprintf(fsid_fn, sizeof(fsid_fn), "%s/fsid", basedir.c_str()); - fsid_fd = ::open(fsid_fn, O_RDWR|O_CREAT, 0644); + fsid_fd = ::open(fsid_fn, O_RDWR|O_CREAT|O_CLOEXEC, 0644); if (fsid_fd < 0) { ret = -errno; derr << __FUNC__ << ": failed to open " << fsid_fn << ": " << cpp_strerror(ret) << dendl; @@ -942,7 +942,7 @@ int FileStore::mkfs() if (backend->can_checkpoint()) { // create snap_1 too - current_fd = ::open(current_fn.c_str(), O_RDONLY); + current_fd = ::open(current_fn.c_str(), O_RDONLY|O_CLOEXEC); assert(current_fd >= 0); char s[NAME_MAX]; snprintf(s, sizeof(s), COMMIT_SNAP_ITEM, 1ull); @@ -967,7 +967,7 @@ int FileStore::mkfs() int omap_fsid_fd; char omap_fsid_fn[PATH_MAX]; snprintf(omap_fsid_fn, sizeof(omap_fsid_fn), "%s/osd_uuid", omap_dir.c_str()); - omap_fsid_fd = ::open(omap_fsid_fn, O_RDWR|O_CREAT, 0644); + omap_fsid_fd = ::open(omap_fsid_fn, O_RDWR|O_CREAT|O_CLOEXEC, 0644); if (omap_fsid_fd < 0) { ret = -errno; derr << __FUNC__ << ": failed to open " << omap_fsid_fn << ": " << cpp_strerror(ret) << dendl; @@ -1043,7 +1043,7 @@ int FileStore::mkjournal() int ret; char fn[PATH_MAX]; snprintf(fn, sizeof(fn), "%s/fsid", basedir.c_str()); - int fd = ::open(fn, O_RDONLY, 0644); + int fd = ::open(fn, O_RDONLY|O_CLOEXEC, 0644); if (fd < 0) { int err = errno; derr << __FUNC__ << ": open error: " << cpp_strerror(err) << dendl; @@ -1125,7 +1125,7 @@ bool FileStore::test_mount_in_use() // verify fs isn't in use - fsid_fd = ::open(fn, O_RDWR, 0644); + fsid_fd = ::open(fn, O_RDWR|O_CLOEXEC, 0644); if (fsid_fd < 0) return 0; // no fsid, ok. bool inuse = lock_fsid() < 0; @@ -1140,7 +1140,7 @@ bool FileStore::is_rotational() if (backend) { rotational = backend->is_rotational(); } else { - int fd = ::open(basedir.c_str(), O_RDONLY); + int fd = ::open(basedir.c_str(), O_RDONLY|O_CLOEXEC); if (fd < 0) return true; struct statfs st; @@ -1164,7 +1164,7 @@ bool FileStore::is_journal_rotational() if (backend) { journal_rotational = backend->is_journal_rotational(); } else { - int fd = ::open(journalpath.c_str(), O_RDONLY); + int fd = ::open(journalpath.c_str(), O_RDONLY|O_CLOEXEC); if (fd < 0) return true; struct statfs st; @@ -1212,7 +1212,7 @@ int FileStore::_detect_fs() int x = rand(); int y = x+1; snprintf(fn, sizeof(fn), "%s/xattr_test", basedir.c_str()); - int tmpfd = ::open(fn, O_CREAT|O_WRONLY|O_TRUNC, 0700); + int tmpfd = ::open(fn, O_CREAT|O_WRONLY|O_TRUNC|O_CLOEXEC, 0700); if (tmpfd < 0) { int ret = -errno; derr << __FUNC__ << ": unable to create " << fn << ": " << cpp_strerror(ret) << dendl; @@ -1389,7 +1389,7 @@ int FileStore::upgrade() int FileStore::read_op_seq(uint64_t *seq) { - int op_fd = ::open(current_op_seq_fn.c_str(), O_CREAT|O_RDWR, 0644); + int op_fd = ::open(current_op_seq_fn.c_str(), O_CREAT|O_RDWR|O_CLOEXEC, 0644); if (op_fd < 0) { int r = -errno; assert(!m_filestore_fail_eio || r != -EIO); @@ -1445,7 +1445,7 @@ int FileStore::mount() // get fsid snprintf(buf, sizeof(buf), "%s/fsid", basedir.c_str()); - fsid_fd = ::open(buf, O_RDWR, 0644); + fsid_fd = ::open(buf, O_RDWR|O_CLOEXEC, 0644); if (fsid_fd < 0) { ret = -errno; derr << __FUNC__ << ": error opening '" << buf << "': " @@ -1508,7 +1508,7 @@ int FileStore::mount() } // open some dir handles - basedir_fd = ::open(basedir.c_str(), O_RDONLY); + basedir_fd = ::open(basedir.c_str(), O_RDONLY|O_CLOEXEC); if (basedir_fd < 0) { ret = -errno; derr << __FUNC__ << ": failed to open " << basedir << ": " @@ -1618,7 +1618,7 @@ int FileStore::mount() } initial_op_seq = 0; - current_fd = ::open(current_fn.c_str(), O_RDONLY); + current_fd = ::open(current_fn.c_str(), O_RDONLY|O_CLOEXEC); if (current_fd < 0) { ret = -errno; derr << __FUNC__ << ": error opening: " << current_fn << ": " << cpp_strerror(ret) << dendl; @@ -1669,7 +1669,7 @@ int FileStore::mount() << dendl; }else{ // if osd_uuid exists, compares osd_uuid with fsid - omap_fsid_fd = ::open(omap_fsid_buf, O_RDONLY, 0644); + omap_fsid_fd = ::open(omap_fsid_buf, O_RDONLY|O_CLOEXEC, 0644); if (omap_fsid_fd < 0) { ret = -errno; derr << __FUNC__ << ": error opening '" << omap_fsid_buf << "': " @@ -2366,7 +2366,7 @@ void FileStore::_set_global_replay_guard(const coll_t& cid, char fn[PATH_MAX]; get_cdir(cid, fn, sizeof(fn)); - int fd = ::open(fn, O_RDONLY); + int fd = ::open(fn, O_RDONLY|O_CLOEXEC); if (fd < 0) { int err = errno; derr << __FUNC__ << ": " << cid << " error " << cpp_strerror(err) << dendl; @@ -2400,7 +2400,7 @@ int FileStore::_check_global_replay_guard(const coll_t& cid, { char fn[PATH_MAX]; get_cdir(cid, fn, sizeof(fn)); - int fd = ::open(fn, O_RDONLY); + int fd = ::open(fn, O_RDONLY|O_CLOEXEC); if (fd < 0) { dout(10) << __FUNC__ << ": " << cid << " dne" << dendl; return 1; // if collection does not exist, there is no guard, and we can replay. @@ -2432,7 +2432,7 @@ void FileStore::_set_replay_guard(const coll_t& cid, { char fn[PATH_MAX]; get_cdir(cid, fn, sizeof(fn)); - int fd = ::open(fn, O_RDONLY); + int fd = ::open(fn, O_RDONLY|O_CLOEXEC); if (fd < 0) { int err = errno; derr << __FUNC__ << ": " << cid << " error " << cpp_strerror(err) << dendl; @@ -2491,7 +2491,7 @@ void FileStore::_close_replay_guard(const coll_t& cid, { char fn[PATH_MAX]; get_cdir(cid, fn, sizeof(fn)); - int fd = ::open(fn, O_RDONLY); + int fd = ::open(fn, O_RDONLY|O_CLOEXEC); if (fd < 0) { int err = errno; derr << __FUNC__ << ": " << cid << " error " << cpp_strerror(err) << dendl; @@ -2564,7 +2564,7 @@ int FileStore::_check_replay_guard(const coll_t& cid, const SequencerPosition& s char fn[PATH_MAX]; get_cdir(cid, fn, sizeof(fn)); - int fd = ::open(fn, O_RDONLY); + int fd = ::open(fn, O_RDONLY|O_CLOEXEC); if (fd < 0) { dout(10) << __FUNC__ << ": " << cid << " dne" << dendl; return 1; // if collection does not exist, there is no guard, and we can replay. @@ -3791,10 +3791,10 @@ int FileStore::_do_copy_range(int from, int to, uint64_t srcoff, uint64_t len, u #ifdef CEPH_HAVE_SPLICE if (backend->has_splice()) { int pipefd[2]; - if (pipe(pipefd) < 0) { - r = -errno; - derr << " pipe " << " got " << cpp_strerror(r) << dendl; - return r; + if (pipe_cloexec(pipefd) < 0) { + int e = errno; + derr << " pipe " << " got " << cpp_strerror(e) << dendl; + return -e; } loff_t dstpos = dstoff; @@ -4921,7 +4921,7 @@ int FileStore::_collection_set_bits(const coll_t& c, int bits) char n[PATH_MAX]; int r; int32_t v = bits; - int fd = ::open(fn, O_RDONLY); + int fd = ::open(fn, O_RDONLY|O_CLOEXEC); if (fd < 0) { r = -errno; goto out; @@ -4942,7 +4942,7 @@ int FileStore::collection_bits(const coll_t& c) int r; char n[PATH_MAX]; int32_t bits; - int fd = ::open(fn, O_RDONLY); + int fd = ::open(fn, O_RDONLY|O_CLOEXEC); if (fd < 0) { bits = r = -errno; goto out; diff --git a/src/os/filestore/GenericFileStoreBackend.cc b/src/os/filestore/GenericFileStoreBackend.cc index 3ed4e4b5d941..b21e3437f2e6 100644 --- a/src/os/filestore/GenericFileStoreBackend.cc +++ b/src/os/filestore/GenericFileStoreBackend.cc @@ -70,7 +70,7 @@ GenericFileStoreBackend::GenericFileStoreBackend(FileStore *fs): { // NOTE: the below won't work on btrfs; we'll assume rotational. string fn = get_basedir_path(); - int fd = ::open(fn.c_str(), O_RDONLY); + int fd = ::open(fn.c_str(), O_RDONLY|O_CLOEXEC); if (fd < 0) { return; } @@ -91,7 +91,7 @@ GenericFileStoreBackend::GenericFileStoreBackend(FileStore *fs): { // NOTE: the below won't work on btrfs; we'll assume rotational. string fn = get_journal_path(); - int fd = ::open(fn.c_str(), O_RDONLY); + int fd = ::open(fn.c_str(), O_RDONLY|O_CLOEXEC); if (fd < 0) { return; } @@ -115,7 +115,7 @@ int GenericFileStoreBackend::detect_features() char fn[PATH_MAX]; snprintf(fn, sizeof(fn), "%s/fiemap_test", get_basedir_path().c_str()); - int fd = ::open(fn, O_CREAT|O_RDWR|O_TRUNC, 0644); + int fd = ::open(fn, O_CREAT|O_RDWR|O_TRUNC|O_CLOEXEC, 0644); if (fd < 0) { fd = -errno; derr << "detect_features: unable to create " << fn << ": " << cpp_strerror(fd) << dendl; @@ -218,9 +218,10 @@ int GenericFileStoreBackend::detect_features() int pipefd[2]; loff_t off_in = 0; int r; - if ((r = pipe(pipefd)) < 0) - dout(0) << "detect_features: splice pipe met error " << cpp_strerror(errno) << dendl; - else { + if (pipe_cloexec(pipefd) < 0) { + int e = errno; + dout(0) << "detect_features: splice pipe met error " << cpp_strerror(e) << dendl; + } else { lseek(fd, 0, SEEK_SET); r = splice(fd, &off_in, pipefd[1], NULL, 10, 0); if (!(r < 0 && errno == EINVAL)) { diff --git a/src/os/filestore/LFNIndex.cc b/src/os/filestore/LFNIndex.cc index b3e451f62b1f..2befe38d5dd5 100644 --- a/src/os/filestore/LFNIndex.cc +++ b/src/os/filestore/LFNIndex.cc @@ -169,7 +169,7 @@ int LFNIndex::collection_list_partial(const ghobject_t &start, int LFNIndex::fsync_dir(const vector &path) { maybe_inject_failure(); - int fd = ::open(get_full_path_subdir(path).c_str(), O_RDONLY); + int fd = ::open(get_full_path_subdir(path).c_str(), O_RDONLY|O_CLOEXEC); if (fd < 0) return -errno; FDCloser f(fd); @@ -897,7 +897,7 @@ int LFNIndex::lfn_unlink(const vector &path, } } string full_path = get_full_path(path, mangled_name); - int fd = ::open(full_path.c_str(), O_RDONLY); + int fd = ::open(full_path.c_str(), O_RDONLY|O_CLOEXEC); if (fd < 0) return -errno; FDCloser f(fd); diff --git a/src/os/kstore/KStore.cc b/src/os/kstore/KStore.cc index f7a4214a83e2..6f8b642c6648 100755 --- a/src/os/kstore/KStore.cc +++ b/src/os/kstore/KStore.cc @@ -676,7 +676,7 @@ void KStore::_shutdown_logger() int KStore::_open_path() { assert(path_fd < 0); - path_fd = ::open(path.c_str(), O_DIRECTORY); + path_fd = ::open(path.c_str(), O_DIRECTORY|O_CLOEXEC); if (path_fd < 0) { int r = -errno; derr << __func__ << " unable to open " << path << ": " << cpp_strerror(r) diff --git a/src/rgw/rgw_http_client.cc b/src/rgw/rgw_http_client.cc index 32f6498b07a7..e8522f511e25 100644 --- a/src/rgw/rgw_http_client.cc +++ b/src/rgw/rgw_http_client.cc @@ -2,6 +2,7 @@ // vim: ts=8 sw=2 smarttab #include "include/compat.h" +#include "common/errno.h" #include @@ -1013,21 +1014,19 @@ int RGWHTTPManager::complete_requests() int RGWHTTPManager::set_threaded() { - int r = pipe(thread_pipe); - if (r < 0) { - r = -errno; - ldout(cct, 0) << "ERROR: pipe() returned errno=" << r << dendl; - return r; + if (pipe_cloexec(thread_pipe) < 0) { + int e = errno; + ldout(cct, 0) << "ERROR: pipe(): " << cpp_strerror(e) << dendl; + return -e; } // enable non-blocking reads - r = ::fcntl(thread_pipe[0], F_SETFL, O_NONBLOCK); - if (r < 0) { - r = -errno; - ldout(cct, 0) << "ERROR: fcntl() returned errno=" << r << dendl; + if (::fcntl(thread_pipe[0], F_SETFL, O_NONBLOCK) < 0) { + int e = errno; + ldout(cct, 0) << "ERROR: fcntl(): " << cpp_strerror(e) << dendl; TEMP_FAILURE_RETRY(::close(thread_pipe[0])); TEMP_FAILURE_RETRY(::close(thread_pipe[1])); - return r; + return -e; } #ifdef HAVE_CURL_MULTI_WAIT diff --git a/src/test/objectstore/test_bluefs.cc b/src/test/objectstore/test_bluefs.cc index 93213d161617..ebf664074d93 100644 --- a/src/test/objectstore/test_bluefs.cc +++ b/src/test/objectstore/test_bluefs.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "global/global_init.h" #include "common/ceph_argparse.h" @@ -14,6 +15,8 @@ #include "common/errno.h" #include +#include + #include "os/bluestore/BlueFS.h" string get_temp_bdev(uint64_t size)