Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jewel: common: global-init: fixup chown of the run directory along with log and asok files #8754

Merged
merged 8 commits into from Jun 27, 2016
2 changes: 1 addition & 1 deletion src/common/admin_socket.cc
Expand Up @@ -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: "
Expand Down
5 changes: 5 additions & 0 deletions src/common/ceph_context.cc
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/common/ceph_context.h
Expand Up @@ -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 */
Expand Down
9 changes: 8 additions & 1 deletion src/common/common_init.cc
Expand Up @@ -12,6 +12,7 @@
*
*/

#include "common/admin_socket.h"
#include "common/ceph_argparse.h"
#include "common/ceph_context.h"
#include "common/ceph_crypto.h"
Expand Down Expand Up @@ -123,6 +124,12 @@ 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())) {
cct->get_admin_socket()->chown(cct->get_set_uid(), cct->get_set_gid());
}
}
72 changes: 58 additions & 14 deletions src/global/global_init.cc
Expand Up @@ -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,
Expand Down Expand Up @@ -128,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);
Expand Down Expand Up @@ -265,16 +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());
g_ceph_context->get_admin_socket()->chown(
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
Expand Down Expand Up @@ -305,15 +336,21 @@ 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) &&
(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;
}

// stop log thread
g_ceph_context->_log->flush();
g_ceph_context->_log->stop();
cct->_log->flush();
cct->_log->stop();
return 0;
}

Expand Down Expand Up @@ -341,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.
Expand All @@ -366,8 +403,15 @@ 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) &&
(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)
Expand Down