From 997d0bc5a657aa481166d58aa4cb2620ba6b67c0 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 30 Nov 2011 19:14:26 +0300 Subject: [PATCH] * Fix reopening of logs in case of privilleged run. --- src/logger.c | 69 +++++++++++++++++++++++++++++++++++++--------------- src/logger.h | 14 +++++++++++ src/main.c | 63 ++++++++++++++++++++++++++++++++--------------- src/main.h | 3 +++ 4 files changed, 110 insertions(+), 39 deletions(-) diff --git a/src/logger.c b/src/logger.c index 07b0eca34..219f04cac 100644 --- a/src/logger.c +++ b/src/logger.c @@ -117,7 +117,7 @@ direct_write_log_line (rspamd_logger_t *rspamd_log, void *data, gint count, gboo if (r == -1) { /* We cannot write message to file, so we need to detect error and make decision */ r = rspamd_snprintf (errmsg, sizeof (errmsg), "direct_write_log_line: cannot write log line: %s", strerror (errno)); - if (errno == EBADF || errno == EIO || errno == EINTR) { + if (errno == EIO || errno == EINTR) { /* Descriptor is somehow invalid, try to restart */ reopen_log (rspamd_log); if (write (rspamd_log->fd, errmsg, r) != -1) { @@ -130,8 +130,8 @@ direct_write_log_line (rspamd_logger_t *rspamd_log, void *data, gint count, gboo rspamd_log->throttling = TRUE; rspamd_log->throttling_time = time (NULL); } - else if (errno == EPIPE) { - /* We write to some pipe and it disappears, disable logging */ + else if (errno == EPIPE || errno == EBADF) { + /* We write to some pipe and it disappears, disable logging or we has opened bad file descriptor */ rspamd_log->enabled = FALSE; } } @@ -143,17 +143,16 @@ direct_write_log_line (rspamd_logger_t *rspamd_log, void *data, gint count, gboo /* Logging utility functions */ gint -open_log (rspamd_logger_t *rspamd_log) +open_log_priv (rspamd_logger_t *rspamd_log, uid_t uid, gid_t gid) { - - rspamd_log->enabled = TRUE; - switch (rspamd_log->cfg->log_type) { case RSPAMD_LOG_CONSOLE: /* Do nothing with console */ + rspamd_log->enabled = TRUE; return 0; case RSPAMD_LOG_SYSLOG: openlog ("rspamd", LOG_NDELAY | LOG_PID, rspamd_log->cfg->log_facility); + rspamd_log->enabled = TRUE; return 0; case RSPAMD_LOG_FILE: rspamd_log->fd = open (rspamd_log->cfg->log_file, O_CREAT | O_WRONLY | O_APPEND, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); @@ -161,13 +160,18 @@ open_log (rspamd_logger_t *rspamd_log) fprintf (stderr, "open_log: cannot open desired log file: %s, %s", rspamd_log->cfg->log_file, strerror (errno)); return -1; } + if (fchown (rspamd_log->fd, uid, gid) == -1) { + fprintf (stderr, "open_log: cannot chown desired log file: %s, %s", rspamd_log->cfg->log_file, strerror (errno)); + return -1; + } + rspamd_log->enabled = TRUE; return 0; } return -1; } void -close_log (rspamd_logger_t *rspamd_log) +close_log_priv (rspamd_logger_t *rspamd_log, uid_t uid, gid_t gid) { gchar tmpbuf[256]; flush_log_buf (rspamd_log); @@ -207,6 +211,43 @@ close_log (rspamd_logger_t *rspamd_log) rspamd_log->enabled = FALSE; } +gint +reopen_log_priv (rspamd_logger_t *rspamd_log, uid_t uid, gid_t gid) +{ + close_log_priv (rspamd_log, uid, gid); + if (open_log_priv (rspamd_log, uid, gid) == 0) { + msg_info ("log file reopened"); + return 0; + } + + return -1; +} + +/** + * Open log file or initialize other structures + */ +gint +open_log (rspamd_logger_t *logger) +{ + return open_log_priv (logger, -1, -1); +} +/** + * Close log file or destroy other structures + */ +void +close_log (rspamd_logger_t *logger) +{ + close_log_priv (logger, -1, -1); +} +/** + * Close and open log again + */ +gint +reopen_log (rspamd_logger_t *logger) +{ + return reopen_log_priv (logger, -1, -1); +} + /* * Setup logger */ @@ -295,18 +336,6 @@ rspamd_set_logger (enum rspamd_log_type type, enum process_type ptype, struct rs } } -gint -reopen_log (rspamd_logger_t *rspamd_log) -{ - close_log (rspamd_log); - if (open_log (rspamd_log) == 0) { - msg_info ("log file reopened"); - return 0; - } - - return -1; -} - /** * Used after fork() for updating structure params */ diff --git a/src/logger.h b/src/logger.h index f44dc56d9..e25d6bfff 100644 --- a/src/logger.h +++ b/src/logger.h @@ -28,6 +28,20 @@ void close_log (rspamd_logger_t *logger); * Close and open log again */ gint reopen_log (rspamd_logger_t *logger); + +/** + * Open log file or initialize other structures for privileged processes + */ +gint open_log_priv (rspamd_logger_t *logger, uid_t uid, gid_t gid); +/** + * Close log file or destroy other structures for privileged processes + */ +void close_log_priv (rspamd_logger_t *logger, uid_t uid, gid_t gid); +/** + * Close and open log again for privileged processes + */ +gint reopen_log_priv (rspamd_logger_t *logger, uid_t uid, gid_t gid); + /** * Set log pid */ diff --git a/src/main.c b/src/main.c index f91bf9b34..03d3839cd 100644 --- a/src/main.c +++ b/src/main.c @@ -191,35 +191,59 @@ read_cmd_line (gint argc, gchar **argv, struct config_file *cfg) cfg->pid_file = rspamd_pidfile; } +/* Detect privilleged mode */ static void -drop_priv (struct config_file *cfg) +detect_priv (struct rspamd_main *rspamd) { struct passwd *pwd; struct group *grp; + uid_t euid; - if (geteuid () == 0 && cfg->rspamd_user) { - pwd = getpwnam (cfg->rspamd_user); + euid = geteuid (); + + if (euid == 0) { + if (!rspamd->cfg->rspamd_user) { + msg_err ("cannot run rspamd workers as root user, please add -u and -g options to select a proper unprivilleged user"); + exit (EXIT_FAILURE); + } + + rspamd->is_privilleged = TRUE; + pwd = getpwnam (rspamd->cfg->rspamd_user); if (pwd == NULL) { msg_err ("user specified does not exists (%s), aborting", strerror (errno)); exit (-errno); } - if (cfg->rspamd_group) { - grp = getgrnam (cfg->rspamd_group); + if (rspamd->cfg->rspamd_group) { + grp = getgrnam (rspamd->cfg->rspamd_group); if (grp == NULL) { msg_err ("group specified does not exists (%s), aborting", strerror (errno)); exit (-errno); } - if (setgid (grp->gr_gid) == -1) { - msg_err ("cannot setgid to %d (%s), aborting", (gint)grp->gr_gid, strerror (errno)); - exit (-errno); - } - if (initgroups (cfg->rspamd_user, grp->gr_gid) == -1) { - msg_err ("initgroups failed (%s), aborting", strerror (errno)); - exit (-errno); - } + rspamd->workers_gid = grp->gr_gid; + } + rspamd->workers_uid = pwd->pw_uid; + } + else { + rspamd->is_privilleged = FALSE; + rspamd->workers_uid = -1; + rspamd->workers_gid = -1; + } +} + +static void +drop_priv (struct rspamd_main *rspamd) +{ + if (rspamd->is_privilleged) { + if (setgid (rspamd->workers_gid) == -1) { + msg_err ("cannot setgid to %d (%s), aborting", (gint)rspamd->workers_gid, strerror (errno)); + exit (-errno); + } + if (initgroups (rspamd->cfg->rspamd_user, rspamd->workers_gid) == -1) { + msg_err ("initgroups failed (%s), aborting", strerror (errno)); + exit (-errno); } - if (setuid (pwd->pw_uid) == -1) { - msg_err ("cannot setuid to %d (%s), aborting", (gint)pwd->pw_uid, strerror (errno)); + if (setuid (rspamd->workers_uid) == -1) { + msg_err ("cannot setuid to %d (%s), aborting", (gint)rspamd->workers_uid, strerror (errno)); exit (-errno); } } @@ -229,7 +253,7 @@ static void config_logger (struct rspamd_main *rspamd, gboolean is_fatal) { rspamd_set_logger (rspamd->cfg->log_type, TYPE_MAIN, rspamd); - if (open_log (rspamd->logger) == -1) { + if (open_log_priv (rspamd->logger, rspamd->workers_uid, rspamd->workers_gid) == -1) { if (is_fatal) { fprintf (stderr, "Fatal error, cannot open logfile, exiting\n"); exit (EXIT_FAILURE); @@ -346,7 +370,7 @@ fork_worker (struct rspamd_main *rspamd, struct worker_conf *cf) /* Update pid for logging */ update_log_pid (cf->type, rspamd->logger); /* Drop privilleges */ - drop_priv (rspamd->cfg); + drop_priv (rspamd); /* Set limits */ set_worker_limits (cf); switch (cf->type) { @@ -887,6 +911,7 @@ main (gint argc, gchar **argv, gchar **env) (void)open_log (rspamd_main->logger); g_log_set_default_handler (rspamd_glib_log_function, rspamd_main->logger); + detect_priv (rspamd_main); init_lua (rspamd_main->cfg); /* Init counters */ @@ -1082,7 +1107,7 @@ main (gint argc, gchar **argv, gchar **env) } if (do_restart) { do_restart = 0; - reopen_log (rspamd_main->logger); + reopen_log_priv (rspamd_main->logger, rspamd_main->workers_uid, rspamd_main->workers_gid); msg_info ("rspamd " RVERSION " is restarting"); g_hash_table_foreach (rspamd_main->workers, kill_old_workers, NULL); remove_all_maps (); @@ -1091,7 +1116,7 @@ main (gint argc, gchar **argv, gchar **env) } if (do_reopen_log) { do_reopen_log = 0; - reopen_log (rspamd_main->logger); + reopen_log_priv (rspamd_main->logger, rspamd_main->workers_uid, rspamd_main->workers_gid); g_hash_table_foreach (rspamd_main->workers, reopen_log_handler, NULL); } if (got_alarm) { diff --git a/src/main.h b/src/main.h index c111752da..7ff76afb3 100644 --- a/src/main.h +++ b/src/main.h @@ -97,6 +97,9 @@ struct rspamd_main { statfile_pool_t *statfile_pool; /**< shared statfiles pool */ GHashTable *workers; /**< workers pool indexed by pid */ rspamd_logger_t *logger; + uid_t workers_uid; /**< worker's uid running to */ + gid_t workers_gid; /**< worker's gid running to */ + gboolean is_privilleged; /**< true if run in privilleged mode */ }; struct counter_data { -- 2.39.5