1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
/*
** $Id: utils.c 2698 2008-08-27 14:03:38Z andre.dig $
** watchcatd - Watchcat Daemon
** See copyright notice in distro's COPYRIGHT file
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <unistd.h>
#include <sched.h>
#include <syslog.h>
#include <errno.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include "utils.h"
extern char **environ;
/* You don't have to call _myassert directly, use the myassert macro.
* The return mean nothing, it only prevents warnings.
* The library client musts define mysyslog and mysyslog can't call myassert
* or myassert_sys!
*/
int _myassert(char *exp, char *filename, int line, const char *func)
{
mysyslog(LOG_ALERT, "FATAL ERROR, source_filename=`%s', "
"line=%i, function=%s assertion=`%s'", filename, line, func, exp);
exit(1);
return 0;
}
/* You don't have to call _myassert_sys directly, use the myassert_sys macro.
* The return mean nothing, it only prevents warnings.
* The library client musts define mysyslog and mysyslog can't call myassert
* or myassert_sys!
*/
int _myassert_sys(char *exp, char *filename, int line, const char *func)
{
int e = errno;
mysyslog(LOG_ALERT, "FATAL ERROR, source_filename=`%s', "
"line=%i, function=%s assertion=`%s' errno=%i, strerror=`%s'",
filename, line, func, exp, e, strerror(e));
exit(e);
return 0;
}
int is_fd_open(int fd)
{
struct stat dummy;
return fstat(fd, &dummy) == 0;
}
struct env_list {
char *name;
char *val;
};
void restrict_env(void)
{
int i;
char *envp;
char *allowed_env[] = { "TZ" };
#define NALLOWED (sizeof(allowed_env)/sizeof(char *))
struct env_list newenv[NALLOWED];
for (i = 0; i < NALLOWED; i++) {
envp = getenv(allowed_env[i]);
newenv[i].name = (envp ? strdup(allowed_env[i]) : NULL);
newenv[i].val = (envp ? strdup(envp) : NULL);
}
environ = NULL;
for (i = 0; i < NALLOWED; i++)
if (newenv[i].name != NULL)
setenv(newenv[i].name, newenv[i].val, 1);
setenv("PATH", "/bin/:/usr/bin/", 1);
free(envp);
envp = NULL;
}
/* These are all protections inherited across a fork and shared in watchcat's
* process group.
* The protect_process_group function must be called when watchcatd master
* is starting.
*/
void protect_process_group(int nodaemon, int priority)
{
struct sched_param sp;
signal(SIGPIPE, SIG_IGN);
sp.sched_priority = priority;
myassert_sys(sched_setscheduler(0, SCHED_RR, &sp) == 0);
restrict_env();
if (nodaemon) {
myassert_sys(chdir("/") == 0);
myassert_sys(setpgid(0, 0) == 0);
return;
}
myassert_sys(daemon(0, 0) == 0);
}
void drop_privileges(char *user)
{
struct passwd *pw;
myassert_sys(pw = getpwnam(user));
/* Chroot */
myassert_sys(chroot(pw->pw_dir) == 0);
myassert_sys(chdir("/") == 0);
/* Drop privileges */
myassert_sys(initgroups(user, pw->pw_gid) == 0);
myassert_sys(setgid(pw->pw_gid) == 0);
myassert_sys(setuid(pw->pw_uid) == 0);
myassert(seteuid(0) == -1 && setegid(0) == -1);
}
/* These are all protections doesn't inherited across a fork.
* The protect_daemon function must be called when daemon is starting.
*/
void protect_daemon(int realtime)
{
if (realtime)
myassert_sys(mlockall(MCL_CURRENT | MCL_FUTURE) == 0);
}
|