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