summaryrefslogtreecommitdiffstats
path: root/test/units/TEST-22-TMPFILES.03.sh
blob: d1584987551bd6fe2bbec9e12687bdd13f299aa2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#!/bin/bash
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# Basic tests for types creating/writing files
set -eux
set -o pipefail

rm -fr /tmp/{f,F,w}
mkdir  /tmp/{f,F,w}
touch /tmp/file-owned-by-root

#
# 'f'
#
systemd-tmpfiles --dry-run --create - <<EOF
f     /tmp/f/1    0644 - - - -
f     /tmp/f/2    0644 - - - This string should be written
EOF

test ! -e /tmp/f/1
test ! -e /tmp/f/2

systemd-tmpfiles --create - <<EOF
f     /tmp/f/1    0644 - - - -
f     /tmp/f/2    0644 - - - This string should be written
EOF

### '1' should exist and be empty
test -f /tmp/f/1; test ! -s /tmp/f/1
test "$(stat -c %U:%G:%a /tmp/f/1)" = "root:root:644"

test "$(stat -c %U:%G:%a /tmp/f/2)" = "root:root:644"
test "$(< /tmp/f/2)" = "This string should be written"

### The perms are supposed to be updated even if the file already exists.
systemd-tmpfiles --create - <<EOF
f     /tmp/f/1    0666 daemon daemon - This string should not be written
EOF

# file should be empty
test ! -s /tmp/f/1
test "$(stat -c %U:%G:%a /tmp/f/1)" = "daemon:daemon:666"

### But we shouldn't try to set perms on an existing file which is not a
### regular one.
mkfifo /tmp/f/fifo
chmod 644 /tmp/f/fifo

(! systemd-tmpfiles --create -) <<EOF
f     /tmp/f/fifo    0666 daemon daemon - This string should not be written
EOF

test -p /tmp/f/fifo
test "$(stat -c %U:%G:%a /tmp/f/fifo)" = "root:root:644"

### 'f' should not follow symlinks.
ln -s missing /tmp/f/dangling
ln -s /tmp/file-owned-by-root /tmp/f/symlink

(! systemd-tmpfiles --create -) <<EOF
f     /tmp/f/dangling    0644 daemon daemon - -
f     /tmp/f/symlink     0644 daemon daemon - -
EOF
test ! -e /tmp/f/missing
test "$(stat -c %U:%G:%a /tmp/file-owned-by-root)" = "root:root:644"

### Handle read-only filesystem gracefully: we shouldn't fail if the target
### already exists and have the correct perms.
mkdir /tmp/f/rw-fs
mkdir /tmp/f/ro-fs

touch /tmp/f/rw-fs/foo
chmod 644 /tmp/f/rw-fs/foo

mount -o bind,ro /tmp/f/rw-fs /tmp/f/ro-fs

systemd-tmpfiles --create - <<EOF
f     /tmp/f/ro-fs/foo    0644 - - - - This string should not be written
EOF
test -f /tmp/f/ro-fs/foo; test ! -s /tmp/f/ro-fs/foo

(! systemd-tmpfiles --create -) <<EOF
f     /tmp/f/ro-fs/foo    0666 - - - -
EOF
test "$(stat -c %U:%G:%a /tmp/f/fifo)" = "root:root:644"

(! systemd-tmpfiles --create -) <<EOF
f     /tmp/f/ro-fs/bar    0644 - - - -
EOF
test ! -e /tmp/f/ro-fs/bar

### 'f' shouldn't follow unsafe paths.
mkdir /tmp/f/daemon
ln -s /root /tmp/f/daemon/unsafe-symlink
chown -R --no-dereference daemon:daemon /tmp/f/daemon

(! systemd-tmpfiles --create -) <<EOF
f     /tmp/f/daemon/unsafe-symlink/exploit    0644 daemon daemon - -
EOF
test ! -e /tmp/f/daemon/unsafe-symlink/exploit

#
# 'F'
#
echo "This should be truncated" >/tmp/F/truncated
echo "This should be truncated" >/tmp/F/truncated-with-content

systemd-tmpfiles --create - <<EOF
F     /tmp/F/created                0644 - - - -
F     /tmp/F/created-with-content   0644 - - - new content
F     /tmp/F/truncated              0666 daemon daemon - -
F     /tmp/F/truncated-with-content 0666 daemon daemon - new content
EOF

test -f /tmp/F/created; test ! -s /tmp/F/created
test -f /tmp/F/created-with-content
test "$(< /tmp/F/created-with-content)" = "new content"
test -f /tmp/F/truncated; test ! -s /tmp/F/truncated
test "$(stat -c %U:%G:%a /tmp/F/truncated)" = "daemon:daemon:666"
test -s /tmp/F/truncated-with-content
test "$(stat -c %U:%G:%a /tmp/F/truncated-with-content)" = "daemon:daemon:666"

### We shouldn't try to truncate anything but regular files since the behavior is
### unspecified in the other cases.
mkfifo /tmp/F/fifo

(! systemd-tmpfiles --create -) <<EOF
F     /tmp/F/fifo                0644 - - - -
EOF

test -p /tmp/F/fifo

### 'F' should not follow symlinks.
ln -s missing /tmp/F/dangling
ln -s /tmp/file-owned-by-root /tmp/F/symlink

(! systemd-tmpfiles --create -) <<EOF
f     /tmp/F/dangling    0644 daemon daemon - -
f     /tmp/F/symlink     0644 daemon daemon - -
EOF
test ! -e /tmp/F/missing
test "$(stat -c %U:%G:%a /tmp/file-owned-by-root)" = "root:root:644"

### Handle read-only filesystem gracefully: we shouldn't fail if the target
### already exists and is empty.
mkdir /tmp/F/rw-fs
mkdir /tmp/F/ro-fs

touch /tmp/F/rw-fs/foo
chmod 644 /tmp/F/rw-fs/foo

mount -o bind,ro /tmp/F/rw-fs /tmp/F/ro-fs

systemd-tmpfiles --create - <<EOF
F     /tmp/F/ro-fs/foo    0644 - - - -
EOF
test -f /tmp/F/ro-fs/foo; test ! -s /tmp/F/ro-fs/foo

echo "truncating is not allowed anymore" >/tmp/F/rw-fs/foo
(! systemd-tmpfiles --create -) <<EOF
F     /tmp/F/ro-fs/foo    0644 - - - -
EOF

(! systemd-tmpfiles --create -) <<EOF
F     /tmp/F/ro-fs/foo    0644 - - - - This string should not be written
EOF
test -f /tmp/F/ro-fs/foo
grep -q 'truncating is not allowed' /tmp/F/ro-fs/foo

# Trying to change the perms should fail.
: >/tmp/F/rw-fs/foo
(! systemd-tmpfiles --create -) <<EOF
F     /tmp/F/ro-fs/foo    0666 - - - -
EOF
test "$(stat -c %U:%G:%a /tmp/F/ro-fs/foo)" = "root:root:644"

### Try to create a new file.
(! systemd-tmpfiles --create -) <<EOF
F     /tmp/F/ro-fs/bar    0644 - - - -
EOF
test ! -e /tmp/F/ro-fs/bar

### 'F' shouldn't follow unsafe paths.
mkdir /tmp/F/daemon
ln -s /root /tmp/F/daemon/unsafe-symlink
chown -R --no-dereference daemon:daemon /tmp/F/daemon

(! systemd-tmpfiles --create -) <<EOF
F     /tmp/F/daemon/unsafe-symlink/exploit    0644 daemon daemon - -
EOF
test ! -e /tmp/F/daemon/unsafe-symlink/exploit

#
# 'w'
#
touch /tmp/w/overwritten
touch /tmp/w/appended

### nop if the target does not exist.
systemd-tmpfiles --dry-run --create - <<EOF
w     /tmp/w/unexistent    0644 - - - new content
EOF
test ! -e /tmp/w/unexistent

systemd-tmpfiles --create - <<EOF
w     /tmp/w/unexistent    0644 - - - new content
EOF
test ! -e /tmp/w/unexistent

### no argument given -> fails.
(! systemd-tmpfiles --create -) <<EOF
w     /tmp/w/unexistent    0644 - - - -
EOF

### write into an empty file.
systemd-tmpfiles --dry-run --create - <<EOF
w     /tmp/w/overwritten    0644 - - - old content
EOF
test -f /tmp/w/overwritten
test -z "$(< /tmp/w/overwritten)"

systemd-tmpfiles --create - <<EOF
w     /tmp/w/overwritten    0644 - - - old content
EOF
test -f /tmp/w/overwritten
test "$(< /tmp/w/overwritten)" = "old content"

### old content is overwritten
systemd-tmpfiles --dry-run --create - <<EOF
w     /tmp/w/overwritten    0644 - - - new content
EOF
test -f /tmp/w/overwritten
test "$(< /tmp/w/overwritten)" = "old content"

systemd-tmpfiles --create - <<EOF
w     /tmp/w/overwritten    0644 - - - new content
EOF
test -f /tmp/w/overwritten
test "$(< /tmp/w/overwritten)" = "new content"

### append lines
systemd-tmpfiles --create - <<EOF
w+    /tmp/w/appended    0644 - - - 1
w+    /tmp/w/appended    0644 - - - 2\n
w+    /tmp/w/appended    0644 - - - 3
EOF
test -f /tmp/w/appended
test "$(< /tmp/w/appended)" = "$(echo -ne '12\n3')"

### writing into an 'exotic' file should be allowed.
systemd-tmpfiles --dry-run --create - <<EOF
w     /dev/null    - - - - new content
EOF

systemd-tmpfiles --create - <<EOF
w     /dev/null    - - - - new content
EOF

### 'w' follows symlinks
ln -s ./overwritten /tmp/w/symlink
systemd-tmpfiles --create - <<EOF
w     /tmp/w/symlink    - - - - $(readlink -e /tmp/w/symlink)
EOF
readlink -e /tmp/w/symlink
test "$(< /tmp/w/overwritten)" = "/tmp/w/overwritten"

### 'w' shouldn't follow unsafe paths.
mkdir /tmp/w/daemon
ln -s /root /tmp/w/daemon/unsafe-symlink
chown -R --no-dereference daemon:daemon /tmp/w/daemon

(! systemd-tmpfiles --create -) <<EOF
f     /tmp/w/daemon/unsafe-symlink/exploit    0644 daemon daemon - -
EOF
test ! -e /tmp/w/daemon/unsafe-symlink/exploit