mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-18 06:03:42 +03:00
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.
This commit is contained in:
parent
8e70580bb0
commit
4468addca6
@ -35,6 +35,10 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/fs.h>
|
||||
|
||||
#ifdef HAVE_ACL
|
||||
#include <sys/acl.h>
|
||||
#endif
|
||||
|
||||
#include <systemd/sd-journal.h>
|
||||
|
||||
#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.");
|
||||
|
@ -387,11 +387,29 @@ 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;
|
||||
|
||||
n = strv_length(*l);
|
||||
c = realloc(*l, sizeof(char*) * (n + 2));
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
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;
|
||||
|
||||
@ -399,18 +417,11 @@ int strv_extend(char ***l, const char *value) {
|
||||
if (!v)
|
||||
return -ENOMEM;
|
||||
|
||||
n = strv_length(*l);
|
||||
c = realloc(*l, sizeof(char*) * (n + 2));
|
||||
if (!c) {
|
||||
r = strv_push(l, v);
|
||||
if (r < 0)
|
||||
free(v);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
c[n] = v;
|
||||
c[n+1] = NULL;
|
||||
|
||||
*l = c;
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
char **strv_uniq(char **l) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user