|
|
|
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;
|