#include <getopt.h>
+#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+
#include "shared/log.h"
+#include "shared/util.h"
#include "crash-manager.h"
+#define USER_NAME "crash_worker"
+
static void print_help(const char *name)
{
printf("Syntax: %s [OPTIONS]\n"
#undef GET_NUMBER
}
+static bool set_caps(const cap_flag_t flag)
+{
+ bool res = false;
+ cap_t caps;
+ cap_value_t cap_list[5] = {
+ CAP_DAC_READ_SEARCH,
+ CAP_DAC_OVERRIDE,
+ CAP_KILL,
+ CAP_SYS_PTRACE,
+ CAP_SYSLOG
+ };
+
+ caps = cap_get_proc();
+ if (caps == NULL) {
+ _E("cap_get_proc() error: %m");
+ goto exit;
+ }
+
+ if (cap_set_flag(caps, flag, ARRAY_SIZE(cap_list), cap_list, CAP_SET) == -1) {
+ _E("cap_set_flag() error: %m");
+ goto exit;
+ }
+
+ if (cap_set_proc(caps) == -1) {
+ _E("cap_set_proc() error: %m");
+ goto exit;
+ }
+
+ res = true;
+exit:
+ if (caps != NULL && cap_free(caps) == -1) {
+ _E("cap_free() error: %m");
+ res = false;
+ }
+ return res;
+}
+
+static bool drop_privileges(const char *user_name)
+{
+ struct passwd *user_info = getpwnam(user_name);
+ if (!user_info) {
+ _E("getpwnam() error: %m");
+ return false;
+ }
+
+ if (!set_caps(CAP_PERMITTED))
+ return false;
+
+ /*
+ * setuid() clears capabilities, so we need to set PR_SET_KEEPCAPS and
+ * restore them after that
+ */
+ if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) {
+ _E("prctl(PR_SET_KEEPCAPS) error: %m");
+ return false;
+ }
+
+ if (setuid(user_info->pw_uid) == -1) {
+ _E("setuid() error: %m\n");
+ return false;
+ }
+
+ if (!set_caps(CAP_EFFECTIVE))
+ return false;
+
+ if (!set_caps(CAP_INHERITABLE))
+ return false;
+
+ return true;
+}
int main(int argc, char *argv[])
{
+ int res;
+
+ if (!drop_privileges(USER_NAME)) {
+ res = EXIT_FAILURE;
+ goto exit;
+ }
+
struct crash_info cinfo;
/*
if (!parse_args(&cinfo, argc, argv))
return EXIT_FAILURE;
- int res = crash_manager_direct(&cinfo) ? EXIT_SUCCESS : EXIT_FAILURE;
+ res = crash_manager_direct(&cinfo) ? EXIT_SUCCESS : EXIT_FAILURE;
crash_manager_free(&cinfo);
+exit:
_I("Exiting with exit code %d", res);
return res;
}