doczkal / rpms / abrt

Forked from rpms/abrt 4 years ago
Clone

Blame SOURCES/0182-lib-add-convenient-wrappers-for-ensuring-writable-di.patch

a60cd7
From 40826f4ed0b325961d23f1e5dda45215bdb120c0 Mon Sep 17 00:00:00 2001
a60cd7
From: Jakub Filak <jfilak@redhat.com>
a60cd7
Date: Wed, 30 Sep 2015 14:13:35 +0200
a60cd7
Subject: [PATCH] lib: add convenient wrappers for ensuring writable dir
a60cd7
a60cd7
Replace lchown with fchown and chmod with fchmod.
a60cd7
a60cd7
Related to CVE-2015-5287
a60cd7
Related: #1262252
a60cd7
a60cd7
Signed-off-by: Jakub Filak <jfilak@redhat.com>
a60cd7
---
a60cd7
 src/daemon/abrtd.c    | 19 -------------------
a60cd7
 src/include/libabrt.h |  6 ++++++
a60cd7
 src/lib/hooklib.c     | 46 ++++++++++++++++++++++++++++++++++++++++++++++
a60cd7
 3 files changed, 52 insertions(+), 19 deletions(-)
a60cd7
a60cd7
diff --git a/src/daemon/abrtd.c b/src/daemon/abrtd.c
a60cd7
index b8426dd..b1252d2 100644
a60cd7
--- a/src/daemon/abrtd.c
a60cd7
+++ b/src/daemon/abrtd.c
a60cd7
@@ -158,25 +158,6 @@ static gboolean handle_signal_cb(GIOChannel *gio, GIOCondition condition, gpoint
a60cd7
     return TRUE; /* "please don't remove this event" */
a60cd7
 }
a60cd7
 
a60cd7
-static void ensure_writable_dir(const char *dir, mode_t mode, const char *user)
a60cd7
-{
a60cd7
-    struct stat sb;
a60cd7
-
a60cd7
-    if (mkdir(dir, mode) != 0 && errno != EEXIST)
a60cd7
-        perror_msg_and_die("Can't create '%s'", dir);
a60cd7
-    if (stat(dir, &sb) != 0 || !S_ISDIR(sb.st_mode))
a60cd7
-        error_msg_and_die("'%s' is not a directory", dir);
a60cd7
-
a60cd7
-    struct passwd *pw = getpwnam(user);
a60cd7
-    if (!pw)
a60cd7
-        perror_msg_and_die("Can't find user '%s'", user);
a60cd7
-
a60cd7
-    if ((sb.st_uid != pw->pw_uid || sb.st_gid != pw->pw_gid) && lchown(dir, pw->pw_uid, pw->pw_gid) != 0)
a60cd7
-        perror_msg_and_die("Can't set owner %u:%u on '%s'", (unsigned int)pw->pw_uid, (unsigned int)pw->pw_gid, dir);
a60cd7
-    if ((sb.st_mode & 07777) != mode && chmod(dir, mode) != 0)
a60cd7
-        perror_msg_and_die("Can't set mode %o on '%s'", mode, dir);
a60cd7
-}
a60cd7
-
a60cd7
 static void sanitize_dump_dir_rights(void)
a60cd7
 {
a60cd7
     /* We can't allow everyone to create dumps: otherwise users can flood
a60cd7
diff --git a/src/include/libabrt.h b/src/include/libabrt.h
a60cd7
index 21ce440..2510a77 100644
a60cd7
--- a/src/include/libabrt.h
a60cd7
+++ b/src/include/libabrt.h
a60cd7
@@ -42,6 +42,12 @@ int low_free_space(unsigned setting_MaxCrashReportsSize, const char *dump_locati
a60cd7
 
a60cd7
 #define trim_problem_dirs abrt_trim_problem_dirs
a60cd7
 void trim_problem_dirs(const char *dirname, double cap_size, const char *exclude_path);
a60cd7
+#define ensure_writable_dir_id abrt_ensure_writable_dir_uid_git
a60cd7
+void ensure_writable_dir_uid_gid(const char *dir, mode_t mode, uid_t uid, gid_t gid);
a60cd7
+#define ensure_writable_dir abrt_ensure_writable_dir
a60cd7
+void ensure_writable_dir(const char *dir, mode_t mode, const char *user);
a60cd7
+#define ensure_writable_dir_group abrt_ensure_writable_dir_group
a60cd7
+void ensure_writable_dir_group(const char *dir, mode_t mode, const char *user, const char *group);
a60cd7
 #define run_unstrip_n abrt_run_unstrip_n
a60cd7
 char *run_unstrip_n(const char *dump_dir_name, unsigned timeout_sec);
a60cd7
 #define get_backtrace abrt_get_backtrace
a60cd7
diff --git a/src/lib/hooklib.c b/src/lib/hooklib.c
a60cd7
index 8e93663..160a011 100644
a60cd7
--- a/src/lib/hooklib.c
a60cd7
+++ b/src/lib/hooklib.c
a60cd7
@@ -428,6 +428,52 @@ char* problem_data_save(problem_data_t *pd)
a60cd7
     return problem_id;
a60cd7
 }
a60cd7
 
a60cd7
+void ensure_writable_dir_uid_gid(const char *dir, mode_t mode, uid_t uid, gid_t gid)
a60cd7
+{
a60cd7
+    struct stat sb;
a60cd7
+    int dir_fd;
a60cd7
+
a60cd7
+    if (mkdir(dir, mode) != 0 && errno != EEXIST)
a60cd7
+        perror_msg_and_die("Can't create '%s'", dir);
a60cd7
+
a60cd7
+    dir_fd = open(dir, O_DIRECTORY | O_NOFOLLOW);
a60cd7
+    if (dir_fd < 0)
a60cd7
+        perror_msg_and_die("Can't open directory '%s'", dir);
a60cd7
+
a60cd7
+    if (fstat(dir_fd, &sb) != 0)
a60cd7
+        perror_msg_and_die("Can't stat directory '%s'", dir);
a60cd7
+
a60cd7
+    if ((sb.st_uid != uid || sb.st_gid != gid) && fchown(dir_fd, uid, gid) != 0)
a60cd7
+        perror_msg_and_die("Can't set owner %u:%u on '%s'", (unsigned int)uid, (unsigned int)gid, dir);
a60cd7
+
a60cd7
+    if ((sb.st_mode & 07777) != mode && fchmod(dir_fd, mode) != 0)
a60cd7
+        perror_msg_and_die("Can't set mode %o on '%s'", mode, dir);
a60cd7
+
a60cd7
+    close(dir_fd);
a60cd7
+}
a60cd7
+
a60cd7
+void ensure_writable_dir(const char *dir, mode_t mode, const char *user)
a60cd7
+{
a60cd7
+    struct passwd *pw = getpwnam(user);
a60cd7
+    if (!pw)
a60cd7
+        perror_msg_and_die("Can't find user '%s'", user);
a60cd7
+
a60cd7
+    ensure_writable_dir_uid_gid(dir, mode, pw->pw_uid, pw->pw_gid);
a60cd7
+}
a60cd7
+
a60cd7
+void ensure_writable_dir_group(const char *dir, mode_t mode, const char *user, const char *group)
a60cd7
+{
a60cd7
+    struct passwd *pw = getpwnam(user);
a60cd7
+    if (!pw)
a60cd7
+        perror_msg_and_die("Can't find user '%s'", user);
a60cd7
+
a60cd7
+    struct group *gr = getgrnam(group);
a60cd7
+    if (!gr)
a60cd7
+        perror_msg_and_die("Can't find group '%s'", group);
a60cd7
+
a60cd7
+    ensure_writable_dir_uid_gid(dir, mode, pw->pw_uid, gr->gr_gid);
a60cd7
+}
a60cd7
+
a60cd7
 bool dir_is_in_dump_location(const char *dir_name)
a60cd7
 {
a60cd7
     unsigned len = strlen(g_settings_dump_location);
a60cd7
-- 
a60cd7
1.8.3.1
a60cd7