dd65c9
From d23386f61d810dab77e9d9d9130adbd826ea823f Mon Sep 17 00:00:00 2001
dd65c9
From: Michal Sekletar <msekleta@redhat.com>
dd65c9
Date: Thu, 7 Sep 2017 15:49:08 +0200
dd65c9
Subject: [PATCH] tmpfiles: substitute % specifiers in arguments for writing
dd65c9
 files and xattrs
dd65c9
dd65c9
(cherry-picked from commit bd550f78eb261c757cbff85acdb55563c56521f2)
dd65c9
dd65c9
Related: #1299714
dd65c9
---
dd65c9
 src/tmpfiles/tmpfiles.c | 79 ++++++++++++++++++++++++++-----------------------
dd65c9
 1 file changed, 42 insertions(+), 37 deletions(-)
dd65c9
dd65c9
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
dd65c9
index 70e0cc2fa..ddb274fce 100644
dd65c9
--- a/src/tmpfiles/tmpfiles.c
dd65c9
+++ b/src/tmpfiles/tmpfiles.c
dd65c9
@@ -151,6 +151,14 @@ static const char conf_file_dirs[] = CONF_DIRS_NULSTR("tmpfiles");
dd65c9
 static Hashmap *items = NULL, *globs = NULL;
dd65c9
 static Set *unix_sockets = NULL;
dd65c9
 
dd65c9
+static const Specifier specifier_table[] = {
dd65c9
+        { 'm', specifier_machine_id, NULL },
dd65c9
+        { 'b', specifier_boot_id, NULL },
dd65c9
+        { 'H', specifier_host_name, NULL },
dd65c9
+        { 'v', specifier_kernel_release, NULL },
dd65c9
+        {}
dd65c9
+};
dd65c9
+
dd65c9
 static bool needs_glob(ItemType t) {
dd65c9
         return IN_SET(t,
dd65c9
                       WRITE_FILE,
dd65c9
@@ -657,8 +665,7 @@ static int path_set_perms(Item *i, const char *path) {
dd65c9
         return label_fix(path, false, false);
dd65c9
 }
dd65c9
 
dd65c9
-static int get_xattrs_from_arg(Item *i) {
dd65c9
-        char *xattr;
dd65c9
+static int parse_xattrs_from_arg(Item *i) {
dd65c9
         const char *p;
dd65c9
         int r;
dd65c9
 
dd65c9
@@ -667,35 +674,37 @@ static int get_xattrs_from_arg(Item *i) {
dd65c9
 
dd65c9
         p = i->argument;
dd65c9
 
dd65c9
-        while ((r = unquote_first_word(&p, &xattr, false)) > 0) {
dd65c9
-                _cleanup_free_ char *tmp = NULL, *name = NULL,
dd65c9
-                        *value = NULL, *value2 = NULL, *_xattr = xattr;
dd65c9
+        for (;;) {
dd65c9
+                _cleanup_free_ char *name = NULL, *value = NULL, *xattr = NULL, *xattr_replaced = NULL;
dd65c9
+
dd65c9
+                r = unquote_first_word(&p, &xattr, false);
dd65c9
+                if (r < 0)
dd65c9
+                        log_warning_errno(r, "Failed to parse extended attribute '%s', ignoring: %m", p);
dd65c9
+                if (r <= 0)
dd65c9
+                        break;
dd65c9
+
dd65c9
+                r = specifier_printf(xattr, specifier_table, NULL, &xattr_replaced);
dd65c9
+                if (r < 0)
dd65c9
+                        return log_error_errno(r, "Failed to replace specifiers in extended attribute '%s': %m", xattr);
dd65c9
 
dd65c9
-                r = split_pair(xattr, "=", &name, &value);
dd65c9
+                r = split_pair(xattr_replaced, "=", &name, &value);
dd65c9
                 if (r < 0) {
dd65c9
                         log_warning("Illegal xattr found: \"%s\" - ignoring.", xattr);
dd65c9
                         continue;
dd65c9
                 }
dd65c9
 
dd65c9
-                if (strempty(name) || strempty(value)) {
dd65c9
-                        log_warning("Malformed xattr found: \"%s\" - ignoring.", xattr);
dd65c9
+                if (isempty(name) || isempty(value)) {
dd65c9
+                        log_warning("Malformed extended attribute found, ignoring: %s", xattr);
dd65c9
                         continue;
dd65c9
                 }
dd65c9
 
dd65c9
-                tmp = unquote(value, "\"");
dd65c9
-                if (!tmp)
dd65c9
-                        return log_oom();
dd65c9
-
dd65c9
-                value2 = cunescape(tmp);
dd65c9
-                if (!value2)
dd65c9
+                if (strv_push_pair(&i->xattrs, name, value) < 0)
dd65c9
                         return log_oom();
dd65c9
 
dd65c9
-                if (strv_push_pair(&i->xattrs, name, value2) < 0)
dd65c9
-                        return log_oom();
dd65c9
-                name = value2 = NULL;
dd65c9
+                name = value = NULL;
dd65c9
         }
dd65c9
 
dd65c9
-        return r;
dd65c9
+        return 0;
dd65c9
 }
dd65c9
 
dd65c9
 static int path_set_xattrs(Item *i, const char *path) {
dd65c9
@@ -708,17 +717,16 @@ static int path_set_xattrs(Item *i, const char *path) {
dd65c9
                 int n;
dd65c9
 
dd65c9
                 n = strlen(*value);
dd65c9
-                log_debug("\"%s\": setting xattr \"%s=%s\"", path, *name, *value);
dd65c9
+                log_debug("Setting extended attribute '%s=%s' on %s.", *name, *value, path);
dd65c9
                 if (lsetxattr(path, *name, *value, n, 0) < 0) {
dd65c9
-                        log_error("Setting extended attribute %s=%s on %s failed: %m",
dd65c9
-                                  *name, *value, path);
dd65c9
+                        log_error("Setting extended attribute %s=%s on %s failed: %m", *name, *value, path);
dd65c9
                         return -errno;
dd65c9
                 }
dd65c9
         }
dd65c9
         return 0;
dd65c9
 }
dd65c9
 
dd65c9
-static int get_acls_from_arg(Item *item) {
dd65c9
+static int parse_acls_from_arg(Item *item) {
dd65c9
 #ifdef HAVE_ACL
dd65c9
         int r;
dd65c9
 
dd65c9
@@ -726,6 +734,7 @@ static int get_acls_from_arg(Item *item) {
dd65c9
 
dd65c9
         /* If force (= modify) is set, we will not modify the acl
dd65c9
          * afterwards, so the mask can be added now if necessary. */
dd65c9
+
dd65c9
         r = parse_acl(item->argument, &item->acl_access, &item->acl_default, !item->force);
dd65c9
         if (r < 0)
dd65c9
                 log_warning_errno(r, "Failed to parse ACL \"%s\": %m. Ignoring",
dd65c9
@@ -839,7 +848,7 @@ static int path_set_acls(Item *item, const char *path) {
dd65c9
          FS_TOPDIR_FL       |                   \
dd65c9
          FS_NOCOW_FL)
dd65c9
 
dd65c9
-static int get_attribute_from_arg(Item *item) {
dd65c9
+static int parse_attribute_from_arg(Item *item) {
dd65c9
 
dd65c9
         static const struct {
dd65c9
                 char character;
dd65c9
@@ -993,7 +1002,7 @@ static int write_one_file(Item *i, const char *path) {
dd65c9
         }
dd65c9
 
dd65c9
         if (i->argument) {
dd65c9
-                _cleanup_free_ char *unescaped;
dd65c9
+                _cleanup_free_ char *unescaped = NULL, *replaced = NULL;
dd65c9
 
dd65c9
                 log_debug("%s to \"%s\".",
dd65c9
                           i->type == CREATE_FILE ? "Appending" : "Writing", path);
dd65c9
@@ -1002,7 +1011,11 @@ static int write_one_file(Item *i, const char *path) {
dd65c9
                 if (!unescaped)
dd65c9
                         return log_oom();
dd65c9
 
dd65c9
-                r = loop_write(fd, unescaped, strlen(unescaped), false);
dd65c9
+                r = specifier_printf(unescaped, specifier_table, NULL, &replaced);
dd65c9
+                if (r < 0)
dd65c9
+                        return log_error_errno(r, "Failed to replace specifiers in parameter to write '%s': %m", unescaped);
dd65c9
+
dd65c9
+                r = loop_write(fd, replaced, strlen(replaced), false);
dd65c9
                 if (r < 0)
dd65c9
                         return log_error_errno(r, "Failed to write file \"%s\": %m", path);
dd65c9
         } else
dd65c9
@@ -1712,14 +1725,6 @@ static bool should_include_path(const char *path) {
dd65c9
 
dd65c9
 static int parse_line(const char *fname, unsigned line, const char *buffer) {
dd65c9
 
dd65c9
-        static const Specifier specifier_table[] = {
dd65c9
-                { 'm', specifier_machine_id, NULL },
dd65c9
-                { 'b', specifier_boot_id, NULL },
dd65c9
-                { 'H', specifier_host_name, NULL },
dd65c9
-                { 'v', specifier_kernel_release, NULL },
dd65c9
-                {}
dd65c9
-        };
dd65c9
-
dd65c9
         _cleanup_free_ char *action = NULL, *mode = NULL, *user = NULL, *group = NULL, *age = NULL, *path = NULL;
dd65c9
         _cleanup_(item_free_contents) Item i = {};
dd65c9
         ItemArray *existing;
dd65c9
@@ -1801,7 +1806,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
dd65c9
         case RELABEL_PATH:
dd65c9
         case RECURSIVE_RELABEL_PATH:
dd65c9
                 if (i.argument)
dd65c9
-                        log_warning("[%s:%u] %c lines don't take argument field, ignoring.", fname, line, i.type);
dd65c9
+                        log_warning("[%s:%u] %c lines don't take argument fields, ignoring.", fname, line, i.type);
dd65c9
 
dd65c9
                 break;
dd65c9
 
dd65c9
@@ -1861,7 +1866,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
dd65c9
                         log_error("[%s:%u] Set extended attribute requires argument.", fname, line);
dd65c9
                         return -EBADMSG;
dd65c9
                 }
dd65c9
-                r = get_xattrs_from_arg(&i);
dd65c9
+                r = parse_xattrs_from_arg(&i);
dd65c9
                 if (r < 0)
dd65c9
                         return r;
dd65c9
                 break;
dd65c9
@@ -1872,7 +1877,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
dd65c9
                         log_error("[%s:%u] Set ACLs requires argument.", fname, line);
dd65c9
                         return -EBADMSG;
dd65c9
                 }
dd65c9
-                r = get_acls_from_arg(&i);
dd65c9
+                r = parse_acls_from_arg(&i);
dd65c9
                 if (r < 0)
dd65c9
                         return r;
dd65c9
                 break;
dd65c9
@@ -1883,7 +1888,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
dd65c9
                         log_error("[%s:%u] Set file attribute requires argument.", fname, line);
dd65c9
                         return -EBADMSG;
dd65c9
                 }
dd65c9
-                r = get_attribute_from_arg(&i);
dd65c9
+                r = parse_attribute_from_arg(&i);
dd65c9
                 if (r < 0)
dd65c9
                         return r;
dd65c9
                 break;