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