From: Lennart Poettering Date: Fri, 22 Mar 2013 16:44:15 +0000 (+0100) Subject: journalctl: give a nice hint about group membership based on ACLs of /var/log/journal X-Git-Tag: v199~84 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=4468addca6d01a0d2d154371dd72f54307a9c786 journalctl: give a nice hint about group membership based on ACLs of /var/log/journal If we notice that we unprivileged and not in any of the groups which have access to /var/log/journal, print a nice message about which groups do. This checks and prints all groups that are in the default ACL for /var/log/journal, which is not necessarily correct for all journal files, but pretty close. --- diff --git a/src/journal/journalctl.c b/src/journal/journalctl.c index ddadc2133..4c288f333 100644 --- a/src/journal/journalctl.c +++ b/src/journal/journalctl.c @@ -35,6 +35,10 @@ #include #include +#ifdef HAVE_ACL +#include +#endif + #include #include "log.h" @@ -881,13 +885,96 @@ static int verify(sd_journal *j) { static int access_check(void) { #ifdef HAVE_ACL + /* If /var/log/journal doesn't even exist, unprivileged users have no access at all */ if (access("/var/log/journal", F_OK) < 0 && geteuid() != 0 && in_group("systemd-journal") <= 0) { log_error("Unprivileged users can't see messages unless persistent log storage is enabled. Users in the group 'systemd-journal' can always see messages."); return -EACCES; } - if (!arg_quiet && geteuid() != 0 && in_group("systemd-journal") <= 0) - log_warning("Showing user generated messages only. Users in the group 'systemd-journal' can see all messages. Pass -q to turn this notice off."); + /* If /var/log/journal exists, try to pring a nice notice if the user lacks access to it */ + if (!arg_quiet && geteuid() != 0) { + _cleanup_strv_free_ char **g = NULL; + bool have_access; + acl_t acl; + int r; + + have_access = in_group("systemd-journal") > 0; + if (!have_access) { + + /* Let's enumerate all groups from the default + * ACL of the directory, which generally + * should allow access to most journal + * files too */ + + acl = acl_get_file("/var/log/journal/", ACL_TYPE_DEFAULT); + if (acl) { + acl_entry_t entry; + + r = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); + while (r > 0) { + acl_tag_t tag; + gid_t *gid; + char *name; + + r = acl_get_tag_type(entry, &tag); + if (r < 0) + break; + + if (tag != ACL_GROUP) + goto next; + + gid = acl_get_qualifier(entry); + if (!gid) + break; + + if (in_gid(*gid) > 0) { + have_access = true; + break; + } + + name = gid_to_name(*gid); + if (!name) { + acl_free(acl); + return log_oom(); + } + + r = strv_push(&g, name); + if (r < 0) { + free(name); + acl_free(acl); + return log_oom(); + } + + next: + r = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); + } + + acl_free(acl); + } + } + + if (!have_access) { + + if (strv_isempty(g)) + log_notice("Hint: You are currently not seeing messages from other users and the system. Users in the group 'systemd-journal' can see all messages. Pass -q to turn this notice off."); + else { + _cleanup_free_ char *s = NULL; + + r = strv_extend(&g, "systemd-journal"); + if (r < 0) + return log_oom(); + + strv_sort(g); + strv_uniq(g); + + s = strv_join(g, "', '"); + if (!s) + return log_oom(); + + log_notice("Hint: You are currently not seeing messages from other users and the system. Users in the groups '%s' can see all messages. Pass -q to turn this notice off.", s); + } + } + } #else if (geteuid() != 0 && in_group("systemd-journal") <= 0) { log_error("No access to messages. Only users in the group 'systemd-journal' can see messages."); diff --git a/src/shared/strv.c b/src/shared/strv.c index 7bcfabbf1..e57e0ee7b 100644 --- a/src/shared/strv.c +++ b/src/shared/strv.c @@ -387,32 +387,43 @@ fail: return NULL; } -int strv_extend(char ***l, const char *value) { +int strv_push(char ***l, char *value) { char **c; - char *v; unsigned n; if (!value) return 0; - v = strdup(value); - if (!v) - return -ENOMEM; - n = strv_length(*l); c = realloc(*l, sizeof(char*) * (n + 2)); - if (!c) { - free(v); + if (!c) return -ENOMEM; - } - c[n] = v; + c[n] = value; c[n+1] = NULL; *l = c; return 0; } +int strv_extend(char ***l, const char *value) { + char *v; + int r; + + if (!value) + return 0; + + v = strdup(value); + if (!v) + return -ENOMEM; + + r = strv_push(l, v); + if (r < 0) + free(v); + + return r; +} + char **strv_uniq(char **l) { char **i; diff --git a/src/shared/strv.h b/src/shared/strv.h index 49058f8df..910d15337 100644 --- a/src/shared/strv.h +++ b/src/shared/strv.h @@ -41,6 +41,7 @@ char **strv_merge(char **a, char **b); char **strv_merge_concat(char **a, char **b, const char *suffix); char **strv_append(char **l, const char *s); int strv_extend(char ***l, const char *value); +int strv_push(char ***l, char *value); char **strv_remove(char **l, const char *s); char **strv_remove_prefix(char **l, const char *s); diff --git a/src/shared/util.c b/src/shared/util.c index 872f6f737..020b75d0f 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -4190,6 +4190,23 @@ char* uid_to_name(uid_t uid) { return r; } +char* gid_to_name(gid_t gid) { + struct group *p; + char *r; + + if (gid == 0) + return strdup("root"); + + p = getgrgid(gid); + if (p) + return strdup(p->gr_name); + + if (asprintf(&r, "%lu", (unsigned long) gid) < 0) + return NULL; + + return r; +} + int get_group_creds(const char **groupname, gid_t *gid) { struct group *g; gid_t id; @@ -4228,14 +4245,10 @@ int get_group_creds(const char **groupname, gid_t *gid) { return 0; } -int in_group(const char *name) { - gid_t gid, *gids; +int in_gid(gid_t gid) { + gid_t *gids; int ngroups_max, r, i; - r = get_group_creds(&name, &gid); - if (r < 0) - return r; - if (getgid() == gid) return 1; @@ -4258,6 +4271,17 @@ int in_group(const char *name) { return 0; } +int in_group(const char *name) { + int r; + gid_t gid; + + r = get_group_creds(&name, &gid); + if (r < 0) + return r; + + return in_gid(gid); +} + int glob_exists(const char *path) { glob_t g; int r, k; diff --git a/src/shared/util.h b/src/shared/util.h index f75c66bb8..7a3842100 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -429,9 +429,11 @@ int socket_from_display(const char *display, char **path); int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home, const char **shell); int get_group_creds(const char **groupname, gid_t *gid); +int in_gid(gid_t gid); int in_group(const char *name); char* uid_to_name(uid_t uid); +char* gid_to_name(gid_t gid); int glob_exists(const char *path);