923a60
From fd09d69b1bca2b4b602f4ee98d4749a39af04bb4 Mon Sep 17 00:00:00 2001
923a60
From: Lennart Poettering <lennart@poettering.net>
923a60
Date: Fri, 10 Apr 2015 16:22:22 +0200
923a60
Subject: [PATCH] tmpfiles: enforce ordering when executing lines
923a60
923a60
Always create files first, and then adjust their ACLs, xattrs, file
923a60
attributes, never the opposite. Previously the order was not
923a60
deterministic, thus possibly first adjusting ACLs/xattrs/file
923a60
attributes before actually creating the items.
923a60
923a60
Cherry-picked from: 17493fa5d17cadce3b773692d3eeab137de7d323
923a60
Resolves: #1365870
923a60
---
923a60
 src/tmpfiles/tmpfiles.c | 39 +++++++++++++++++++++++++++++++++++----
923a60
 1 file changed, 35 insertions(+), 4 deletions(-)
923a60
923a60
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
923a60
index 64c733aaa0..bda89df5be 100644
923a60
--- a/src/tmpfiles/tmpfiles.c
923a60
+++ b/src/tmpfiles/tmpfiles.c
923a60
@@ -78,18 +78,18 @@ typedef enum ItemType {
923a60
         COPY_FILES = 'C',
923a60
 
923a60
         /* These ones take globs */
923a60
+        WRITE_FILE = 'w',
923a60
         SET_XATTR = 't',
923a60
         RECURSIVE_SET_XATTR = 'T',
923a60
         SET_ACL = 'a',
923a60
         RECURSIVE_SET_ACL = 'A',
923a60
-        WRITE_FILE = 'w',
923a60
         IGNORE_PATH = 'x',
923a60
         IGNORE_DIRECTORY_PATH = 'X',
923a60
         REMOVE_PATH = 'r',
923a60
         RECURSIVE_REMOVE_PATH = 'R',
923a60
-        ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
923a60
         RELABEL_PATH = 'z',
923a60
         RECURSIVE_RELABEL_PATH = 'Z',
923a60
+        ADJUST_MODE = 'm', /* legacy, 'z' is identical to this */
923a60
 } ItemType;
923a60
 
923a60
 typedef struct Item {
923a60
@@ -1480,6 +1480,31 @@ static void item_array_free(ItemArray *a) {
923a60
         free(a);
923a60
 }
923a60
 
923a60
+static int item_compare(const void *a, const void *b) {
923a60
+        const Item *x = a, *y = b;
923a60
+
923a60
+        /* Make sure that the ownership taking item is put first, so
923a60
+         * that we first create the node, and then can adjust it */
923a60
+
923a60
+        if (takes_ownership(x->type) && !takes_ownership(y->type))
923a60
+                return -1;
923a60
+        if (!takes_ownership(x->type) && takes_ownership(y->type))
923a60
+                return 1;
923a60
+
923a60
+        return (int) x->type - (int) y->type;
923a60
+}
923a60
+
923a60
+static void item_array_sort(ItemArray *a) {
923a60
+
923a60
+        /* Sort an item array, to enforce stable ordering in which we
923a60
+         * apply things. */
923a60
+
923a60
+        if (a->count <= 1)
923a60
+                return;
923a60
+
923a60
+        qsort(a->items, a->count, sizeof(Item), item_compare);
923a60
+}
923a60
+
923a60
 static bool item_compatible(Item *a, Item *b) {
923a60
         assert(a);
923a60
         assert(b);
923a60
@@ -1806,6 +1831,8 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
923a60
                 return log_oom();
923a60
 
923a60
         memcpy(existing->items + existing->count++, &i, sizeof(i));
923a60
+        item_array_sort(existing);
923a60
+
923a60
         zero(i);
923a60
         return 0;
923a60
 }
923a60
@@ -2045,13 +2072,17 @@ int main(int argc, char *argv[]) {
923a60
                 }
923a60
         }
923a60
 
923a60
-        HASHMAP_FOREACH(a, globs, iterator) {
923a60
+        /* The non-globbing ones usually create things, hence we apply
923a60
+         * them first */
923a60
+        HASHMAP_FOREACH(a, items, iterator) {
923a60
                 k = process_item_array(a);
923a60
                 if (k < 0 && r == 0)
923a60
                         r = k;
923a60
         }
923a60
 
923a60
-        HASHMAP_FOREACH(a, items, iterator) {
923a60
+        /* The globbing ones usually alter things, hence we apply them
923a60
+         * second. */
923a60
+        HASHMAP_FOREACH(a, globs, iterator) {
923a60
                 k = process_item_array(a);
923a60
                 if (k < 0 && r == 0)
923a60
                         r = k;