From 770ae9eecf5c8e064529efec29020f38a3675a63 Mon Sep 17 00:00:00 2001 From: Karol Mroz Date: Sat, 23 Apr 2016 13:32:45 +0200 Subject: [PATCH 1/8] ceph-context: add function to set init flags Signed-off-by: Karol Mroz (cherry picked from commit aecab14089bcfd33d6a18adabede6a54040460d4) --- src/common/ceph_context.cc | 5 +++++ src/common/ceph_context.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/common/ceph_context.cc b/src/common/ceph_context.cc index e873c9f8783c5..c8dab36dac6f1 100644 --- a/src/common/ceph_context.cc +++ b/src/common/ceph_context.cc @@ -641,6 +641,11 @@ uint32_t CephContext::get_module_type() const return _module_type; } +void CephContext::set_init_flags(int flags) +{ + _init_flags = flags; +} + int CephContext::get_init_flags() const { return _init_flags; diff --git a/src/common/ceph_context.h b/src/common/ceph_context.h index cdb66f58343a4..a455a0c8efdcb 100644 --- a/src/common/ceph_context.h +++ b/src/common/ceph_context.h @@ -84,6 +84,7 @@ class CephContext { /* Get the module type (client, mon, osd, mds, etc.) */ uint32_t get_module_type() const; + void set_init_flags(int flags); int get_init_flags() const; /* Get the PerfCountersCollection of this CephContext */ From d4afe947578a7ae4956a99fbc9350920e2239e0b Mon Sep 17 00:00:00 2001 From: Karol Mroz Date: Sat, 23 Apr 2016 13:35:02 +0200 Subject: [PATCH 2/8] global-init: add a path chown wrapper function Signed-off-by: Karol Mroz (cherry picked from commit 860977b105595dbb50320a30dc0edb922279cb00) --- src/global/global_init.cc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/global/global_init.cc b/src/global/global_init.cc index 5460eef30dc13..9e9d6aa91c8d2 100644 --- a/src/global/global_init.cc +++ b/src/global/global_init.cc @@ -60,6 +60,26 @@ static const char* c_str_or_null(const std::string &str) return str.c_str(); } +static int chown_path(const std::string &pathname, const uid_t owner, const gid_t group, + const std::string &uid_str, const std::string &gid_str) +{ + const char *pathname_cstr = c_str_or_null(pathname); + + if (!pathname_cstr) { + return 0; + } + + int r = ::chown(pathname_cstr, owner, group); + + if (r < 0) { + r = -errno; + cerr << "warning: unable to chown() " << pathname << " as " + << uid_str << ":" << gid_str << ": " << cpp_strerror(r) << std::endl; + } + + return r; +} + void global_pre_init(std::vector < const char * > *alt_def_args, std::vector < const char* >& args, uint32_t module_type, code_environment_t code_env, From f7e6b3cf9c363a3a65da4e176c7324d027352420 Mon Sep 17 00:00:00 2001 From: Karol Mroz Date: Sat, 23 Apr 2016 13:36:01 +0200 Subject: [PATCH 3/8] global-init: check init flags and set accordingly If init flags have changed between the time ceph context was instantiated and now, update them. This can happen, for example, if between manual global_pre_init() and global_init() calls, a daemon adds modifies it's init flags. Signed-off-by: Karol Mroz (cherry picked from commit a0ad13db7aba95537808a570ad4c90f6ac4ca0b8) --- src/global/global_init.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/global/global_init.cc b/src/global/global_init.cc index 9e9d6aa91c8d2..f91a2d1d0adb4 100644 --- a/src/global/global_init.cc +++ b/src/global/global_init.cc @@ -148,6 +148,12 @@ void global_init(std::vector < const char * > *alt_def_args, } first_run = false; + // Verify flags have not changed if global_pre_init() has been called + // manually. If they have, update them. + if (g_ceph_context->get_init_flags() != flags) { + g_ceph_context->set_init_flags(flags); + } + // signal stuff int siglist[] = { SIGPIPE, 0 }; block_signals(siglist, NULL); From c2075448f052ef7e49bc95c1f8240c2ff559b5ae Mon Sep 17 00:00:00 2001 From: Karol Mroz Date: Sat, 23 Apr 2016 13:40:08 +0200 Subject: [PATCH 4/8] common-init: chown admin socket after service thread started Signed-off-by: Karol Mroz (cherry picked from commit 206585c1d0fc6826c91f7830cde8ded86288abef) --- src/common/common_init.cc | 13 ++++++++++++- src/global/global_init.cc | 3 --- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/common/common_init.cc b/src/common/common_init.cc index b1f716557564d..9f7ec20e40103 100644 --- a/src/common/common_init.cc +++ b/src/common/common_init.cc @@ -12,6 +12,7 @@ * */ +#include "common/admin_socket.h" #include "common/ceph_argparse.h" #include "common/ceph_context.h" #include "common/ceph_crypto.h" @@ -123,6 +124,16 @@ void common_init_finish(CephContext *cct) { cct->init_crypto(); - if (!(cct->get_init_flags() & CINIT_FLAG_NO_DAEMON_ACTIONS)) + int flags = cct->get_init_flags(); + if (!(flags & CINIT_FLAG_NO_DAEMON_ACTIONS)) cct->start_service_thread(); + + if ((flags & CINIT_FLAG_DEFER_DROP_PRIVILEGES) && + (cct->get_set_uid() || cct->get_set_gid())) { + // FIXME: Changing ownership of a socket file via the fd does not work as + // expected. The socket file is listed as owned by the same + // 'user:group' which the daemon that created the socket had during + // open(). + cct->get_admin_socket()->chown(cct->get_set_uid(), cct->get_set_gid()); + } } diff --git a/src/global/global_init.cc b/src/global/global_init.cc index f91a2d1d0adb4..34c12d80ebc5a 100644 --- a/src/global/global_init.cc +++ b/src/global/global_init.cc @@ -297,9 +297,6 @@ void global_init(std::vector < const char * > *alt_def_args, g_ceph_context->_log->chown_log_file( g_ceph_context->get_set_uid(), g_ceph_context->get_set_gid()); - g_ceph_context->get_admin_socket()->chown( - g_ceph_context->get_set_uid(), - g_ceph_context->get_set_gid()); } } From 5681b78ac74728db70a89bc86845a74ff7d81217 Mon Sep 17 00:00:00 2001 From: Karol Mroz Date: Sat, 23 Apr 2016 13:47:58 +0200 Subject: [PATCH 5/8] global-init: chown run dir Also performs log file chown() operations if permission drop has been deferred. Documents that admin socket chown() happen in the common init path. Signed-off-by: Karol Mroz (cherry picked from commit 9d513793b3fe4b7e1402e36a4a675553edd6f317) --- src/global/global_init.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/global/global_init.cc b/src/global/global_init.cc index 34c12d80ebc5a..18980c95ab090 100644 --- a/src/global/global_init.cc +++ b/src/global/global_init.cc @@ -291,13 +291,21 @@ void global_init(std::vector < const char * > *alt_def_args, if (priv_ss.str().length()) { dout(0) << priv_ss.str() << dendl; + } - if (g_ceph_context->get_set_uid() || g_ceph_context->get_set_gid()) { - // fix ownership on log, asok files. this is sadly a bit of a hack :( - g_ceph_context->_log->chown_log_file( - g_ceph_context->get_set_uid(), - g_ceph_context->get_set_gid()); - } + if ((flags & CINIT_FLAG_DEFER_DROP_PRIVILEGES) && + (g_ceph_context->get_set_uid() || g_ceph_context->get_set_gid())) { + // Fix ownership on log files and run directories if needed. + // Admin socket files are chown()'d during the common init path _after_ + // the service thread has been started. This is sadly a bit of a hack :( + chown_path(g_conf->run_dir, + g_ceph_context->get_set_uid(), + g_ceph_context->get_set_gid(), + g_ceph_context->get_set_uid_string(), + g_ceph_context->get_set_gid_string()); + g_ceph_context->_log->chown_log_file( + g_ceph_context->get_set_uid(), + g_ceph_context->get_set_gid()); } // Now we're ready to complain about config file parse errors From 2bc41945ca6a8e8e8e852ae0b7e888bc223dd7a3 Mon Sep 17 00:00:00 2001 From: Karol Mroz Date: Sat, 23 Apr 2016 13:54:45 +0200 Subject: [PATCH 6/8] global-init: chown pid files Signed-off-by: Karol Mroz (cherry picked from commit 9c82d8466a264c0f07fd3ec4cc58c1ddb88cc84f) --- src/global/global_init.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/global/global_init.cc b/src/global/global_init.cc index 18980c95ab090..4d7addf2918f6 100644 --- a/src/global/global_init.cc +++ b/src/global/global_init.cc @@ -339,6 +339,12 @@ int global_init_prefork(CephContext *cct) if (pidfile_write(g_conf) < 0) exit(1); + if ((cct->get_init_flags() & CINIT_FLAG_DEFER_DROP_PRIVILEGES) && + (cct->get_set_uid() || cct->get_set_gid())) { + chown_path(conf->pid_file, cct->get_set_uid(), cct->get_set_gid(), + cct->get_set_uid_string(), cct->get_set_gid_string()); + } + return -1; } @@ -399,6 +405,12 @@ void global_init_postfork_start(CephContext *cct) if (pidfile_write(g_conf) < 0) exit(1); + + if ((cct->get_init_flags() & CINIT_FLAG_DEFER_DROP_PRIVILEGES) && + (cct->get_set_uid() || cct->get_set_gid())) { + chown_path(conf->pid_file, cct->get_set_uid(), cct->get_set_gid(), + cct->get_set_uid_string(), cct->get_set_gid_string()); + } } void global_init_postfork_finish(CephContext *cct) From 3963de78635d760924a36eeb1e8b7782dd5a276e Mon Sep 17 00:00:00 2001 From: Karol Mroz Date: Sat, 23 Apr 2016 13:55:18 +0200 Subject: [PATCH 7/8] global-init: fixup inconsistent use of ceph ctx and conf Signed-off-by: Karol Mroz (cherry picked from commit 088cc66a94886130df647976050c9d98fcd7572e) --- src/global/global_init.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/global/global_init.cc b/src/global/global_init.cc index 4d7addf2918f6..38636df404b53 100644 --- a/src/global/global_init.cc +++ b/src/global/global_init.cc @@ -336,7 +336,7 @@ int global_init_prefork(CephContext *cct) const md_config_t *conf = cct->_conf; if (!conf->daemonize) { - if (pidfile_write(g_conf) < 0) + if (pidfile_write(conf) < 0) exit(1); if ((cct->get_init_flags() & CINIT_FLAG_DEFER_DROP_PRIVILEGES) && @@ -349,8 +349,8 @@ int global_init_prefork(CephContext *cct) } // stop log thread - g_ceph_context->_log->flush(); - g_ceph_context->_log->stop(); + cct->_log->flush(); + cct->_log->stop(); return 0; } @@ -378,7 +378,7 @@ void global_init_daemonize(CephContext *cct) void global_init_postfork_start(CephContext *cct) { // restart log thread - g_ceph_context->_log->start(); + cct->_log->start(); /* This is the old trick where we make file descriptors 0, 1, and possibly 2 * point to /dev/null. @@ -403,7 +403,8 @@ void global_init_postfork_start(CephContext *cct) exit(1); } - if (pidfile_write(g_conf) < 0) + const md_config_t *conf = cct->_conf; + if (pidfile_write(conf) < 0) exit(1); if ((cct->get_init_flags() & CINIT_FLAG_DEFER_DROP_PRIVILEGES) && From 6c1163cd6e39ba293be1be4a3f82e60fd054a348 Mon Sep 17 00:00:00 2001 From: Karol Mroz Date: Mon, 25 Apr 2016 17:24:07 +0200 Subject: [PATCH 8/8] admin-socket: use chown instead of fchown fchown() returns success, but does not change asok file ownership. chown() does. Signed-off-by: Karol Mroz (cherry picked from commit 3d051a58cc117ff79d4cdd768603d1dec8ca7f60) --- src/common/admin_socket.cc | 2 +- src/common/common_init.cc | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/common/admin_socket.cc b/src/common/admin_socket.cc index aedaed584ef61..40fa12fd36f7c 100644 --- a/src/common/admin_socket.cc +++ b/src/common/admin_socket.cc @@ -290,7 +290,7 @@ void* AdminSocket::entry() void AdminSocket::chown(uid_t uid, gid_t gid) { if (m_sock_fd >= 0) { - int r = ::fchown(m_sock_fd, uid, gid); + int r = ::chown(m_path.c_str(), uid, gid); if (r < 0) { r = -errno; lderr(m_cct) << "AdminSocket: failed to chown socket: " diff --git a/src/common/common_init.cc b/src/common/common_init.cc index 9f7ec20e40103..d4ed4f964dfb0 100644 --- a/src/common/common_init.cc +++ b/src/common/common_init.cc @@ -130,10 +130,6 @@ void common_init_finish(CephContext *cct) if ((flags & CINIT_FLAG_DEFER_DROP_PRIVILEGES) && (cct->get_set_uid() || cct->get_set_gid())) { - // FIXME: Changing ownership of a socket file via the fd does not work as - // expected. The socket file is listed as owned by the same - // 'user:group' which the daemon that created the socket had during - // open(). cct->get_admin_socket()->chown(cct->get_set_uid(), cct->get_set_gid()); } }