chiark / gitweb /
journald: properly decode audit's proctitle= field
[elogind.git] / src / journal / journald-audit.c
index 787ec34bb830af9836263863c3c98a1a0a2cb61b..d88d67c5bd9af25a14a31818f6bc7fd754e279b9 100644 (file)
@@ -67,7 +67,7 @@ static int map_simple_field(const char *field, const char **p, struct iovec **io
         return 1;
 }
 
-static int map_string_field(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) {
+static int map_string_field_internal(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov, bool filter_printable) {
         _cleanup_free_ char *c = NULL;
         const char *s, *e;
         size_t l;
@@ -108,6 +108,7 @@ static int map_string_field(const char *field, const char **p, struct iovec **io
                 memcpy(c, field, l);
                 for (e = *p; *e != ' ' && *e != 0; e += 2) {
                         int a, b;
+                        uint8_t x;
 
                         a = unhexchar(e[0]);
                         if (a < 0)
@@ -117,10 +118,15 @@ static int map_string_field(const char *field, const char **p, struct iovec **io
                         if (b < 0)
                                 return 0;
 
+                        x = ((uint8_t) a << 4 | (uint8_t) b);
+
+                        if (filter_printable && x < (uint8_t) ' ')
+                                x = (uint8_t) ' ';
+
                         if (!GREEDY_REALLOC(c, allocated, l+2))
                                 return -ENOMEM;
 
-                        c[l++] = (char) ((uint8_t) a << 4 | (uint8_t) b);
+                        c[l++] = (char) x;
                 }
 
                 c[l] = 0;
@@ -140,6 +146,14 @@ static int map_string_field(const char *field, const char **p, struct iovec **io
         return 1;
 }
 
+static int map_string_field(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) {
+        return map_string_field_internal(field, p, iov, n_iov_allocated, n_iov, false);
+}
+
+static int map_string_field_printable(const char *field, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) {
+        return map_string_field_internal(field, p, iov, n_iov_allocated, n_iov, true);
+}
+
 static int map_generic_field(const char *prefix, const char **p, struct iovec **iov, size_t *n_iov_allocated, unsigned *n_iov) {
         const char *e, *f;
         char *c, *t;
@@ -204,7 +218,7 @@ static const MapField map_fields_kernel[] = {
         { "subj=",      "_SELINUX_CONTEXT=",       map_simple_field },
         { "comm=",      "_COMM=",                  map_string_field },
         { "exe=",       "_EXE=",                   map_string_field },
-        { "proctitle=", "_CMDLINE=",               map_string_field },
+        { "proctitle=", "_CMDLINE=",               map_string_field_printable },
 
         /* Some fields don't map to native well-known fields. However,
          * we know that they are string fields, hence let's undo
@@ -438,6 +452,51 @@ void server_process_audit_message(
         process_audit_string(s, nl->nlmsg_type, NLMSG_DATA(nl), nl->nlmsg_len - ALIGN(sizeof(struct nlmsghdr)), tv);
 }
 
+static int enable_audit(int fd, bool b) {
+        struct {
+                union {
+                        struct nlmsghdr header;
+                        uint8_t header_space[NLMSG_HDRLEN];
+                };
+                struct audit_status body;
+        } _packed_ request = {
+                .header.nlmsg_len = NLMSG_LENGTH(sizeof(struct audit_status)),
+                .header.nlmsg_type = AUDIT_SET,
+                .header.nlmsg_flags = NLM_F_REQUEST,
+                .header.nlmsg_seq = 1,
+                .header.nlmsg_pid = 0,
+                .body.mask = AUDIT_STATUS_ENABLED,
+                .body.enabled = b,
+        };
+        union sockaddr_union sa = {
+                .nl.nl_family = AF_NETLINK,
+                .nl.nl_pid = 0,
+        };
+        struct iovec iovec = {
+                .iov_base = &request,
+                .iov_len = NLMSG_LENGTH(sizeof(struct audit_status)),
+        };
+        struct msghdr mh = {
+                .msg_iov = &iovec,
+                .msg_iovlen = 1,
+                .msg_name = &sa.sa,
+                .msg_namelen = sizeof(sa.nl),
+        };
+
+        ssize_t n;
+
+        n = sendmsg(fd, &mh, MSG_NOSIGNAL);
+        if (n < 0)
+                return -errno;
+        if (n != NLMSG_LENGTH(sizeof(struct audit_status)))
+                return -EIO;
+
+        /* We don't wait for the result here, we can't do anything
+         * about it anyway */
+
+        return 0;
+}
+
 int server_open_audit(Server *s) {
         static const int one = 1;
         int r;
@@ -479,5 +538,10 @@ int server_open_audit(Server *s) {
                 return r;
         }
 
+        /* We are listening now, try to enable audit */
+        r = enable_audit(s->audit_fd, true);
+        if (r < 0)
+                log_warning("Failed to issue audit enable call: %s", strerror(-r));
+
         return 0;
 }