summaryrefslogtreecommitdiffstats
path: root/test/units/testsuite-34.sh
blob: d15b675e2650cf366a0752ef1ac204d87b63bf85 (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
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -eux
set -o pipefail

systemd-analyze log-level debug

test_directory() {
    local directory="$1"
    local path="$2"

    # cleanup for previous invocation
    for i in xxx xxx2 yyy zzz x:yz x:yz2; do
        rm -rf "${path:?}/${i}" "${path:?}/private/${i}"
    done

    # Set everything up without DynamicUser=1

    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}"=zzz touch "${path}"/zzz/test
    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}"=zzz test -f "${path}"/zzz/test
    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}"=zzz -p TemporaryFileSystem="${path}" test -f "${path}"/zzz/test
    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}"=zzz:yyy test -f "${path}"/yyy/test
    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}=zzz:xxx zzz:xxx2" -p TemporaryFileSystem="${path}" bash -c "test -f ${path}/xxx/test && test -f ${path}/xxx2/test"
    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}"=zzz:xxx -p TemporaryFileSystem="${path}":ro test -f "${path}"/xxx/test
    (! systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}"=zzz test -f "${path}"/zzz/test-missing)

    test -d "${path}"/zzz
    test ! -L "${path}"/zzz
    test ! -e "${path}"/private/zzz

    test ! -e "${path}"/xxx
    test ! -e "${path}"/private/xxx
    test ! -e "${path}"/xxx2
    test ! -e "${path}"/private/xxx2
    test -L "${path}"/yyy
    test ! -e "${path}"/private/yyy

    test -f "${path}"/zzz/test
    test ! -e "${path}"/zzz/test-missing

    # Convert to DynamicUser=1

    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=1 -p "${directory}"=zzz test -f "${path}"/zzz/test
    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=1 -p "${directory}"=zzz -p TemporaryFileSystem="${path}" test -f "${path}"/zzz/test
    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=1 -p "${directory}"=zzz:yyy test -f "${path}"/yyy/test
    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=1 -p "${directory}=zzz:xxx zzz:xxx2" \
                -p TemporaryFileSystem="${path}" -p EnvironmentFile=-/usr/lib/systemd/systemd-asan-env bash -c "test -f ${path}/xxx/test && test -f ${path}/xxx2/test"
    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=1 -p "${directory}"=zzz:xxx -p TemporaryFileSystem="${path}":ro test -f "${path}"/xxx/test
    (! systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=1 -p "${directory}"=zzz test -f "${path}"/zzz/test-missing)

    test -L "${path}"/zzz
    test -d "${path}"/private/zzz

    test ! -e "${path}"/xxx
    test ! -e "${path}"/private/xxx
    test ! -e "${path}"/xxx2
    test ! -e "${path}"/private/xxx2
    test -L "${path}"/yyy # previous symlink is not removed
    test ! -e "${path}"/private/yyy

    test -f "${path}"/zzz/test
    test ! -e "${path}"/zzz/test-missing

    # Convert back

    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}"=zzz test -f "${path}"/zzz/test
    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}"=zzz -p TemporaryFileSystem="${path}" test -f "${path}"/zzz/test
    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}"=zzz:yyy test -f "${path}"/yyy/test
    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}"=zzz:xxx -p TemporaryFileSystem="${path}" test -f "${path}"/xxx/test
    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}=zzz:xxx zzz:xxx2" -p TemporaryFileSystem="${path}" bash -c "test -f ${path}/xxx/test && test -f ${path}/xxx2/test"
    systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}"=zzz:xxx -p TemporaryFileSystem="${path}":ro test -f "${path}"/xxx/test
    (! systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}"=zzz test -f "${path}"/zzz/test-missing)

    test -d "${path}"/zzz
    test ! -L "${path}"/zzz
    test ! -e "${path}"/private/zzz

    test ! -e "${path}"/xxx
    test ! -e "${path}"/private/xxx
    test ! -e "${path}"/xxx2
    test ! -e "${path}"/private/xxx2
    test -L "${path}"/yyy
    test ! -e "${path}"/private/yyy

    test -f "${path}"/zzz/test
    test ! -e "${path}"/zzz/test-missing

    # Exercise the unit parsing paths too
    cat >/run/systemd/system/testservice-34.service <<EOF
[Service]
Type=oneshot
TemporaryFileSystem=${path}
RuntimeDirectoryPreserve=yes
${directory}=zzz:x\:yz zzz:x\:yz2
ExecStart=test -f ${path}/x:yz2/test
ExecStart=test -f ${path}/x:yz/test
ExecStart=test -f ${path}/zzz/test
EOF
    systemctl daemon-reload
    systemctl start --wait testservice-34.service

    test -d "${path}"/zzz
    test ! -L "${path}"/zzz
    test ! -e "${path}"/private/zzz

    test ! -L "${path}"/x:yz
    test ! -L "${path}"/x:yz2
}

test_check_writable() {
    # cleanup for previous invocation
    for i in aaa quux waldo xxx; do
        rm -rf "/var/lib/$i" "/var/lib/private/$i"
    done

    cat >/run/systemd/system/testservice-34-check-writable.service <<\EOF
[Unit]
Description=Check writable directories when DynamicUser= with StateDirectory=

[Service]
# Relevant only for sanitizer runs
EnvironmentFile=-/usr/lib/systemd/systemd-asan-env

Type=oneshot
DynamicUser=yes
StateDirectory=waldo quux/pief aaa/bbb aaa aaa/ccc xxx/yyy:aaa/111 xxx:aaa/222 xxx/zzz:aaa/333

# Make sure that the state directories are really the only writable directory besides the obvious candidates
ExecStart=bash -c ' \
    set -eux; \
    set -o pipefail; \
    declare -a writable_dirs; \
    readarray -t writable_dirs < <(find / \( -path /var/tmp -o -path /tmp -o -path /proc -o -path /dev/mqueue -o -path /dev/shm -o \
                                              -path /sys/fs/bpf -o -path /dev/.lxc -o -path /sys/devices/system/cpu \) \
                                   -prune -o -type d -writable -print 2>/dev/null | sort -u); \
    [[ "$${#writable_dirs[@]}" == "8" ]]; \
    [[ "$${writable_dirs[0]}" == "/var/lib/private/aaa" ]]; \
    [[ "$${writable_dirs[1]}" == "/var/lib/private/aaa/bbb" ]]; \
    [[ "$${writable_dirs[2]}" == "/var/lib/private/aaa/ccc" ]]; \
    [[ "$${writable_dirs[3]}" == "/var/lib/private/quux/pief" ]]; \
    [[ "$${writable_dirs[4]}" == "/var/lib/private/waldo" ]]; \
    [[ "$${writable_dirs[5]}" == "/var/lib/private/xxx" ]]; \
    [[ "$${writable_dirs[6]}" == "/var/lib/private/xxx/yyy" ]]; \
    [[ "$${writable_dirs[7]}" == "/var/lib/private/xxx/zzz" ]]; \
'
EOF
    systemctl daemon-reload
    systemctl start testservice-34-check-writable.service
}

test_directory "StateDirectory" "/var/lib"
test_directory "RuntimeDirectory" "/run"
test_directory "CacheDirectory" "/var/cache"
test_directory "LogsDirectory" "/var/log"

test_check_writable

systemd-analyze log-level info

touch /testok