blob: a9df3d6bdd5a1a6e386f96d1383fddc8ff12b9be (
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
|
#!/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 --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 && { echo 'unexpected success'; exit 1; }
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 && { echo 'unexpected success'; exit 1; }
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 && { echo 'unexpected success'; exit 1; }
f /tmp/f/ro-fs/foo 0666 - - - -
EOF
test "$(stat -c %U:%G:%a /tmp/f/fifo)" = "root:root:644"
systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
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 && { echo 'unexpected success'; exit 1; }
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 && { echo 'unexpected success'; exit 1; }
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 && { echo 'unexpected success'; exit 1; }
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 && { echo 'unexpected success'; exit 1; }
F /tmp/F/ro-fs/foo 0644 - - - -
EOF
systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
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 && { echo 'unexpected success'; exit 1; }
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 && { echo 'unexpected success'; exit 1; }
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 && { echo 'unexpected success'; exit 1; }
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 --create - <<EOF
w /tmp/w/unexistent 0644 - - - new content
EOF
test ! -e /tmp/w/unexistent
### no argument given -> fails.
systemd-tmpfiles --create - <<EOF && { echo 'unexpected success'; exit 1; }
w /tmp/w/unexistent 0644 - - - -
EOF
### write into an empty file.
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 --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 --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 && { echo 'unexpected success'; exit 1; }
f /tmp/w/daemon/unsafe-symlink/exploit 0644 daemon daemon - -
EOF
test ! -e /tmp/w/daemon/unsafe-symlink/exploit
|