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) {
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;
}
}
/* 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);
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);
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
*/
}
}
-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
*/
* 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
*/
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);
}
}
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);
/* 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) {
(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 */
}
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 ();
}
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) {
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 {