Blame SOURCES/0377-journalctl-rework-code-that-checks-whether-we-have-a.patch

17b0f1
From e9bef2f8146ccf152459248775eec8e8ce123865 Mon Sep 17 00:00:00 2001
17b0f1
From: Lennart Poettering <lennart@poettering.net>
17b0f1
Date: Wed, 22 Apr 2015 22:54:23 +0200
17b0f1
Subject: [PATCH] journalctl: rework code that checks whether we have access to
17b0f1
 /var/log/journal
17b0f1
17b0f1
- fix some memory leaks on error conditions
17b0f1
17b0f1
- handle all error cases properly, and log about failures
17b0f1
17b0f1
- move HAVE_ACL and no-HAVE_ACL code closer to each other
17b0f1
17b0f1
Cherry-picked from: e346512c684e9efae84c6442f7e6a5781564ecde
17b0f1
Related: #1318994
17b0f1
---
17b0f1
 src/journal/journalctl.c | 120 ++++++++++++++++++++-------------------
17b0f1
 src/shared/acl-util.c    | 102 ++++++++++++++++++---------------
17b0f1
 src/shared/acl-util.h    |   2 +-
17b0f1
 3 files changed, 119 insertions(+), 105 deletions(-)
17b0f1
17b0f1
diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c
17b0f1
index 6ba8847798..f60e6415f8 100644
17b0f1
--- a/src/journal/journalctl.c
17b0f1
+++ b/src/journal/journalctl.c
17b0f1
@@ -1680,61 +1680,76 @@ static int verify(sd_journal *j) {
17b0f1
         return r;
17b0f1
 }
17b0f1
 
17b0f1
-#ifdef HAVE_ACL
17b0f1
 static int access_check_var_log_journal(sd_journal *j) {
17b0f1
+#ifdef HAVE_ACL
17b0f1
         _cleanup_strv_free_ char **g = NULL;
17b0f1
-        bool have_access;
17b0f1
+        const char* dir;
17b0f1
+#endif
17b0f1
         int r;
17b0f1
 
17b0f1
         assert(j);
17b0f1
 
17b0f1
-        have_access = in_group("systemd-journal") > 0;
17b0f1
+        if (arg_quiet)
17b0f1
+                return 0;
17b0f1
 
17b0f1
-        if (!have_access) {
17b0f1
-                const char* dir;
17b0f1
+        /* If we are root, we should have access, don't warn. */
17b0f1
+        if (getuid() == 0)
17b0f1
+                return 0;
17b0f1
 
17b0f1
-                if (access("/run/log/journal", F_OK) >= 0)
17b0f1
-                        dir = "/run/log/journal";
17b0f1
-                else
17b0f1
-                        dir = "/var/log/journal";
17b0f1
+        /* If we are in the 'systemd-journal' group, we should have
17b0f1
+         * access too. */
17b0f1
+        r = in_group("systemd-journal");
17b0f1
+        if (r < 0)
17b0f1
+                return log_error_errno(r, "Failed to check if we are in the 'systemd-journal' group: %m");
17b0f1
+        if (r > 0)
17b0f1
+                return 0;
17b0f1
 
17b0f1
-                /* Let's enumerate all groups from the default ACL of
17b0f1
-                 * the directory, which generally should allow access
17b0f1
-                 * to most journal files too */
17b0f1
-                r = search_acl_groups(&g, dir, &have_access);
17b0f1
-                if (r < 0)
17b0f1
-                        return r;
17b0f1
-        }
17b0f1
+#ifdef HAVE_ACL
17b0f1
+        if (laccess("/run/log/journal", F_OK) >= 0)
17b0f1
+                dir = "/run/log/journal";
17b0f1
+        else
17b0f1
+                dir = "/var/log/journal";
17b0f1
 
17b0f1
-        if (!have_access) {
17b0f1
+        /* If we are in any of the groups listed in the journal ACLs,
17b0f1
+         * then all is good, too. Let's enumerate all groups from the
17b0f1
+         * default ACL of the directory, which generally should allow
17b0f1
+         * access to most journal files too. */
17b0f1
+        r = acl_search_groups(dir, &g);
17b0f1
+        if (r < 0)
17b0f1
+                return log_error_errno(r, "Failed to search journal ACL: %m");
17b0f1
+        if (r > 0)
17b0f1
+                return 0;
17b0f1
 
17b0f1
-                if (strv_isempty(g))
17b0f1
-                        log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
17b0f1
-                                   "      Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
17b0f1
-                                   "      turn off this notice.");
17b0f1
-                else {
17b0f1
-                        _cleanup_free_ char *s = NULL;
17b0f1
+        /* Print a pretty list, if there were ACLs set. */
17b0f1
+        if (!strv_isempty(g)) {
17b0f1
+                _cleanup_free_ char *s = NULL;
17b0f1
 
17b0f1
-                        r = strv_extend(&g, "systemd-journal");
17b0f1
-                        if (r < 0)
17b0f1
-                                return log_oom();
17b0f1
+                /* Thre are groups in the ACL, let's list them */
17b0f1
+                r = strv_extend(&g, "systemd-journal");
17b0f1
+                if (r < 0)
17b0f1
+                        return log_oom();
17b0f1
 
17b0f1
-                        strv_sort(g);
17b0f1
-                        strv_uniq(g);
17b0f1
+                strv_sort(g);
17b0f1
+                strv_uniq(g);
17b0f1
 
17b0f1
-                        s = strv_join(g, "', '");
17b0f1
-                        if (!s)
17b0f1
-                                return log_oom();
17b0f1
+                s = strv_join(g, "', '");
17b0f1
+                if (!s)
17b0f1
+                        return log_oom();
17b0f1
 
17b0f1
-                        log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
17b0f1
-                                   "      Users in groups '%s' can see all messages.\n"
17b0f1
-                                   "      Pass -q to turn off this notice.", s);
17b0f1
-                }
17b0f1
+                log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
17b0f1
+                           "      Users in groups '%s' can see all messages.\n"
17b0f1
+                           "      Pass -q to turn off this notice.", s);
17b0f1
+                return 1;
17b0f1
         }
17b0f1
+#endif
17b0f1
 
17b0f1
-        return 0;
17b0f1
+        /* If no ACLs were found, print a short version of the message. */
17b0f1
+        log_notice("Hint: You are currently not seeing messages from other users and the system.\n"
17b0f1
+                   "      Users in the 'systemd-journal' group can see all messages. Pass -q to\n"
17b0f1
+                   "      turn off this notice.");
17b0f1
+
17b0f1
+        return 1;
17b0f1
 }
17b0f1
-#endif
17b0f1
 
17b0f1
 static int access_check(sd_journal *j) {
17b0f1
         Iterator it;
17b0f1
@@ -1746,30 +1761,15 @@ static int access_check(sd_journal *j) {
17b0f1
         if (set_isempty(j->errors)) {
17b0f1
                 if (ordered_hashmap_isempty(j->files))
17b0f1
                         log_notice("No journal files were found.");
17b0f1
+
17b0f1
                 return 0;
17b0f1
         }
17b0f1
 
17b0f1
         if (set_contains(j->errors, INT_TO_PTR(-EACCES))) {
17b0f1
-#ifdef HAVE_ACL
17b0f1
-                /* If /run/log/journal or /var/log/journal exist, try
17b0f1
-                   to pring a nice notice if the user lacks access to it. */
17b0f1
-                if (!arg_quiet && geteuid() != 0) {
17b0f1
-                        r = access_check_var_log_journal(j);
17b0f1
-                        if (r < 0)
17b0f1
-                                return r;
17b0f1
-                }
17b0f1
-#else
17b0f1
-                if (geteuid() != 0 && in_group("systemd-journal") <= 0) {
17b0f1
-                        log_error("Unprivileged users cannot access messages. Users in the 'systemd-journal' group\n"
17b0f1
-                                  "group may access messages.");
17b0f1
-                        return -EACCES;
17b0f1
-                }
17b0f1
-#endif
17b0f1
+                (void) access_check_var_log_journal(j);
17b0f1
 
17b0f1
-                if (ordered_hashmap_isempty(j->files)) {
17b0f1
-                        log_error("No journal files were opened due to insufficient permissions.");
17b0f1
-                        r = -EACCES;
17b0f1
-                }
17b0f1
+                if (ordered_hashmap_isempty(j->files))
17b0f1
+                        r = log_error_errno(EACCES, "No journal files were opened due to insufficient permissions.");
17b0f1
         }
17b0f1
 
17b0f1
         SET_FOREACH(code, j->errors, it) {
17b0f1
@@ -1778,8 +1778,12 @@ static int access_check(sd_journal *j) {
17b0f1
                 err = -PTR_TO_INT(code);
17b0f1
                 assert(err > 0);
17b0f1
 
17b0f1
-                if (err != EACCES)
17b0f1
-                        log_warning_errno(err, "Error was encountered while opening journal files: %m");
17b0f1
+                if (err == EACCES)
17b0f1
+                        continue;
17b0f1
+
17b0f1
+                log_warning_errno(err, "Error was encountered while opening journal files: %m");
17b0f1
+                if (r == 0)
17b0f1
+                        r = -err;
17b0f1
         }
17b0f1
 
17b0f1
         return r;
17b0f1
diff --git a/src/shared/acl-util.c b/src/shared/acl-util.c
17b0f1
index e67e9acb6a..d18a02f503 100644
17b0f1
--- a/src/shared/acl-util.c
17b0f1
+++ b/src/shared/acl-util.c
17b0f1
@@ -82,17 +82,18 @@ int calc_acl_mask_if_needed(acl_t *acl_p) {
17b0f1
 
17b0f1
                 if (tag == ACL_MASK)
17b0f1
                         return 0;
17b0f1
-                if (IN_SET(tag, ACL_USER, ACL_GROUP))
17b0f1
-                        goto calc;
17b0f1
+
17b0f1
+                if (IN_SET(tag, ACL_USER, ACL_GROUP)) {
17b0f1
+                        if (acl_calc_mask(acl_p) < 0)
17b0f1
+                                return -errno;
17b0f1
+
17b0f1
+                        return 1;
17b0f1
+                }
17b0f1
         }
17b0f1
         if (r < 0)
17b0f1
                 return -errno;
17b0f1
-        return 0;
17b0f1
 
17b0f1
-calc:
17b0f1
-        if (acl_calc_mask(acl_p) < 0)
17b0f1
-                return -errno;
17b0f1
-        return 1;
17b0f1
+        return 0;
17b0f1
 }
17b0f1
 
17b0f1
 int add_base_acls_if_needed(acl_t *acl_p, const char *path) {
17b0f1
@@ -159,59 +160,68 @@ int add_base_acls_if_needed(acl_t *acl_p, const char *path) {
17b0f1
         return 0;
17b0f1
 }
17b0f1
 
17b0f1
-int search_acl_groups(char*** dst, const char* path, bool* belong) {
17b0f1
-        acl_t acl;
17b0f1
+int acl_search_groups(const char *path, char ***ret_groups) {
17b0f1
+        _cleanup_strv_free_ char **g = NULL;
17b0f1
+        _cleanup_(acl_free) acl_t acl = NULL;
17b0f1
+        bool ret = false;
17b0f1
+        acl_entry_t entry;
17b0f1
+        int r;
17b0f1
 
17b0f1
         assert(path);
17b0f1
-        assert(belong);
17b0f1
 
17b0f1
         acl = acl_get_file(path, ACL_TYPE_DEFAULT);
17b0f1
-        if (acl) {
17b0f1
-                acl_entry_t entry;
17b0f1
-                int r;
17b0f1
-
17b0f1
-                r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
17b0f1
-                while (r > 0) {
17b0f1
-                        acl_tag_t tag;
17b0f1
-                        gid_t *gid;
17b0f1
-                        char *name;
17b0f1
+        if (!acl)
17b0f1
+                return -errno;
17b0f1
 
17b0f1
-                        r = acl_get_tag_type(entry, &tag;;
17b0f1
-                        if (r < 0)
17b0f1
-                                break;
17b0f1
+        r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
17b0f1
+        for (;;) {
17b0f1
+                _cleanup_(acl_free_gid_tpp) gid_t *gid = NULL;
17b0f1
+                acl_tag_t tag;
17b0f1
+
17b0f1
+                if (r < 0)
17b0f1
+                        return -errno;
17b0f1
+                if (r == 0)
17b0f1
+                        break;
17b0f1
+
17b0f1
+                if (acl_get_tag_type(entry, &tag) < 0)
17b0f1
+                        return -errno;
17b0f1
 
17b0f1
-                        if (tag != ACL_GROUP)
17b0f1
-                                goto next;
17b0f1
+                if (tag != ACL_GROUP)
17b0f1
+                        goto next;
17b0f1
 
17b0f1
-                        gid = acl_get_qualifier(entry);
17b0f1
-                        if (!gid)
17b0f1
-                                break;
17b0f1
+                gid = acl_get_qualifier(entry);
17b0f1
+                if (!gid)
17b0f1
+                        return -errno;
17b0f1
+
17b0f1
+                if (in_gid(*gid) > 0) {
17b0f1
+                        if (!ret_groups)
17b0f1
+                                return true;
17b0f1
 
17b0f1
-                        if (in_gid(*gid) > 0) {
17b0f1
-                                *belong = true;
17b0f1
-                                break;
17b0f1
-                        }
17b0f1
+                        ret = true;
17b0f1
+                }
17b0f1
+
17b0f1
+                if (ret_groups) {
17b0f1
+                        char *name;
17b0f1
 
17b0f1
                         name = gid_to_name(*gid);
17b0f1
-                        if (!name) {
17b0f1
-                                acl_free(acl);
17b0f1
-                                return log_oom();
17b0f1
-                        }
17b0f1
-
17b0f1
-                        r = strv_consume(dst, name);
17b0f1
-                        if (r < 0) {
17b0f1
-                                acl_free(acl);
17b0f1
-                                return log_oom();
17b0f1
-                        }
17b0f1
-
17b0f1
-                next:
17b0f1
-                        r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
17b0f1
+                        if (!name)
17b0f1
+                                return -ENOMEM;
17b0f1
+
17b0f1
+                        r = strv_consume(&g, name);
17b0f1
+                        if (r < 0)
17b0f1
+                                return r;
17b0f1
                 }
17b0f1
 
17b0f1
-                acl_free(acl);
17b0f1
+        next:
17b0f1
+                r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
17b0f1
         }
17b0f1
 
17b0f1
-        return 0;
17b0f1
+        if (ret_groups) {
17b0f1
+                *ret_groups = g;
17b0f1
+                g = NULL;
17b0f1
+        }
17b0f1
+
17b0f1
+        return ret;
17b0f1
 }
17b0f1
 
17b0f1
 int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask) {
17b0f1
diff --git a/src/shared/acl-util.h b/src/shared/acl-util.h
17b0f1
index fdb90063fa..c8bcc266d0 100644
17b0f1
--- a/src/shared/acl-util.h
17b0f1
+++ b/src/shared/acl-util.h
17b0f1
@@ -32,7 +32,7 @@
17b0f1
 int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry);
17b0f1
 int calc_acl_mask_if_needed(acl_t *acl_p);
17b0f1
 int add_base_acls_if_needed(acl_t *acl_p, const char *path);
17b0f1
-int search_acl_groups(char*** dst, const char* path, bool* belong);
17b0f1
+int acl_search_groups(const char* path, char ***ret_groups);
17b0f1
 int parse_acl(char *text, acl_t *acl_access, acl_t *acl_default, bool want_mask);
17b0f1
 int acls_for_file(const char *path, acl_type_t type, acl_t new, acl_t *acl);
17b0f1