Whamcloud - gitweb
LU-8995 tests: set debug size correctly
[fs/lustre-release.git] / lustre / tests / sanity-selinux.sh
1 #!/bin/bash
2 #
3 # Run select tests by setting ONLY, or as arguments to the script.
4 # Skip specific tests by setting EXCEPT.
5 #
6 # e.g. ONLY="22 23" or ONLY="`seq 32 39`" or EXCEPT="31"
7 set -e
8
9 ONLY=${ONLY:-"$*"}
10 # bug number for skipped test:
11 ALWAYS_EXCEPT=${ALWAYS_EXCEPT:-"$SANITY_SELINUX_EXCEPT"}
12 # UPDATE THE COMMENT ABOVE WITH BUG NUMBERS WHEN CHANGING ALWAYS_EXCEPT!
13
14 SRCDIR=$(dirname $0)
15 SAVE_PWD=$PWD
16
17 LUSTRE=${LUSTRE:-$(dirname $0)/..}
18 . $LUSTRE/tests/test-framework.sh
19 init_test_env $@
20 . ${CONFIG:=$LUSTRE/tests/cfg/$NAME.sh}
21 init_logging
22
23 require_dsh_mds || exit 0
24
25 [ "$SLOW" = "no" ] && EXCEPT_SLOW="xxx"
26
27 # $RUNAS_ID may get set incorrectly somewhere else
28 [ $UID -eq 0 -a $RUNAS_ID -eq 0 ] &&
29         error "RUNAS_ID set to 0, but UID is also 0!"
30
31 #
32 # global variables of this  sanity
33 #
34
35 check_selinux() {
36         echo -n "Checking SELinux environment... "
37         local selinux_status=$(getenforce)
38         if [ "$selinux_status" != "Enforcing" ]; then
39             skip "SELinux is currently in $selinux_status mode," \
40                  "but it must be enforced to run sanity-selinux" && exit 0
41         fi
42         local selinux_policy=$(sestatus |
43                 awk -F':' '$1 == "Loaded policy name" {print $2}' | xargs)
44         if [ -z "$selinux_policy" ]; then
45             selinux_policy=$(sestatus |
46                 awk -F':' '$1 == "Policy from config file" {print $2}' | xargs)
47         fi
48         [ "$selinux_policy" == "targeted" ] ||
49                 error "Accepting only targeted policy"
50         echo "$selinux_status, $selinux_policy"
51 }
52
53 check_selinux
54
55 # we want double mount
56 MOUNT_2=${MOUNT_2:-"yes"}
57 check_and_setup_lustre
58
59 rm -rf $DIR/[df][0-9]*
60
61 check_runas_id $RUNAS_ID $RUNAS_ID $RUNAS
62
63 build_test_filter
64
65 umask 077
66
67 check_selinux_xattr() {
68         local mds=$1
69         local mds_path=$2
70         local mds_dev=$(facet_device $mds)
71         local mntpt="/tmp/mdt_"
72         local opts
73
74         do_facet $mds mkdir -p $mntpt  || error "mkdir $mntpt failed"
75         mount_fstype $mds $mntpt  || error "mount $mds failed"
76
77         local xattrval=$(do_facet $mds getfattr -n security.selinux \
78                                 ${mntpt}/ROOT/$mds_path |
79                          awk -F"=" '$1=="security.selinux" {print $2}')
80
81         unmount_fstype $mds $mntpt || error "umount $mds failed"
82         do_facet $mds rmdir $mntpt || error "rmdir $mntpt failed"
83
84         echo $xattrval
85 }
86
87
88 test_1() {
89         local devname=$(mdsdevname 1)
90         local filename=${DIR}/${tdir}/df1
91         local mds_path=${filename#$MOUNT}
92
93         mds_path=${mds_path#/}
94
95         $LFS setdirstripe -i0 -c1 ${DIR}/$tdir || error "create dir $tdir failed"
96         touch $filename || error "cannot touch $filename"
97
98         local xattrval=$(check_selinux_xattr "mds1" $mds_path)
99
100         [ -n "$xattrval" -a "$xattrval" != '""' ] ||
101                 error "security.selinux xattr is not set"
102 }
103 run_test 1 "create file and check security.selinux xattr is set on MDT"
104
105 test_2a() {
106         local devname=$(mdsdevname 1)
107         local dirname=${DIR}/${tdir}/dir2a
108         local mds_path=${dirname#$MOUNT}
109
110         mds_path=${mds_path#/}
111
112         $LFS setdirstripe -i0 -c1 ${DIR}/$tdir || error "create dir failed"
113         mkdir $dirname || error "cannot mkdir $dirname"
114
115         local xattrval=$(check_selinux_xattr "mds1" $mds_path)
116
117         [ -n "$xattrval" -a "$xattrval" != '""' ] ||
118                 error "security.selinux xattr is not set"
119 }
120 run_test 2a "create dir (mkdir) and check security.selinux xattr is set on MDT"
121
122 test_2b() {
123         local devname=$(mdsdevname 1)
124         local dirname1=${DIR}/$tdir/dir2b1
125         local dirname2=${DIR}/$tdir/dir2b2
126         local mds_path=${dirname1#$MOUNT}
127
128         mds_path=${mds_path#/}
129
130         $LFS setdirstripe -i0 -c1 ${DIR}/$tdir || error "create dir failed"
131         $LFS mkdir -c0 $dirname1 || error "cannot 'lfs mkdir' $dirname1"
132
133         local xattrval=$(check_selinux_xattr "mds1" $mds_path)
134
135         mds_path=${dirname2#$MOUNT}
136         mds_path=${mds_path#/}
137
138         [ -n "$xattrval" -a "$xattrval" != '""' ] ||
139                 error "security.selinux xattr is not set"
140
141         $LFS setdirstripe -i0 $dirname2 ||
142             error "cannot 'lfs setdirstripe' $dirname2"
143
144         xattrval=$(check_selinux_xattr "mds1" $mds_path)
145
146         [ -n "$xattrval" -a "$xattrval" != '""' ] ||
147                 error "security.selinux xattr is not set"
148 }
149 run_test 2b "create dir with lfs and check security.selinux xattr is set on MDT"
150
151 test_3() {
152         local filename=$DIR/df3
153
154         # get current mapping of runasid, and save it
155         local uname=$(getent passwd $RUNAS_ID | cut -d: -f1)
156         local sename=$(semanage login -l |
157                        awk -v uname=$uname '$1==uname {print $2}')
158         local serange=$(semanage login -l |
159                         awk -v uname=$uname '$1==uname {print $3}')
160
161         # change mapping of runasid to unconfined_u
162         semanage login -a -s unconfined_u $uname ||
163                 error "unable to map $uname to unconfined_u"
164
165         # "access" Lustre
166         echo "${uname} mapped as unconfined_u: touch $filename"
167         $PDSH ${uname}@localhost "touch $filename" ||
168                 error "can't touch $filename"
169         echo "${uname} mapped as unconfined_u: rm -f $filename"
170         $PDSH ${uname}@localhost "rm -f $filename" ||
171                 error "can't remove $filename"
172
173         # restore original mapping of runasid
174         if [ -n "$sename" ]; then
175                 if [ -n "$serange" ]; then
176                         semanage login -a -s $sename -r $serange $uname ||
177                                 error "unable to restore mapping for $uname"
178                 else
179                         semanage login -a -s $sename $uname ||
180                                 error "unable to restore mapping for $uname"
181                 fi
182         else
183                 semanage login -d $uname
184         fi
185
186         return 0
187 }
188 run_test 3 "access with unconfined user"
189
190 test_4() {
191         local filename=$DIR/df4
192
193         # get current mapping of runasid, and save it
194         local uname=$(getent passwd $RUNAS_ID | cut -d: -f1)
195         local sename=$(semanage login -l |
196                               awk -v uname=$uname '$1==uname {print $2}')
197         local serange=$(semanage login -l |
198                          awk -v uname=$uname '$1==uname {print $3}')
199
200         # change mapping of runasid to guest_u
201         semanage login -a -s guest_u $uname ||
202                 error "unable to map $uname to guest_u"
203
204         # "access" Lustre
205         echo "${uname} mapped as guest_u: touch $filename"
206         $PDSH ${uname}@localhost "touch $filename" &&
207                 error "touch $filename should have failed"
208
209         # change mapping of runasid to user_u
210         semanage login -a -s user_u $uname ||
211                 error "unable to map $uname to user_u"
212
213         # "access" Lustre
214         echo "${uname} mapped as user_u: touch $filename"
215         $PDSH ${uname}@localhost "touch $filename" ||
216                 error "can't touch $filename"
217         echo "${uname} mapped as user_u: rm -f $filename"
218         $PDSH ${uname}@localhost "rm -f $filename" ||
219                 error "can't remove $filename"
220
221         # restore original mapping of runasid
222         if [ -n "$sename" ]; then
223                 if [ -n "$serange" ]; then
224                         semanage login -a -s $sename -r $serange $uname ||
225                                 error "unable to restore mapping for $uname"
226                 else
227                         semanage login -a -s $sename $uname ||
228                                 error "unable to restore mapping for $uname"
229                 fi
230         else
231                 semanage login -d $uname
232         fi
233
234         return 0
235 }
236 run_test 4 "access with specific SELinux user"
237
238 test_5() {
239         local filename=$DIR/df5
240         local newsecctx="nfs_t"
241
242         # create file
243         touch $filename || error "cannot touch $filename"
244
245         # change sec context
246         chcon -t $newsecctx $filename
247         ls -lZ $filename
248
249         # purge client's cache
250         sync ; echo 3 > /proc/sys/vm/drop_caches
251
252         # get sec context
253         ls -lZ $filename
254         local secctxseen=$(ls -lZ $filename | awk '{print $4}' | cut -d: -f3)
255
256         [ "$newsecctx" == "$secctxseen" ] ||
257                 error "sec context seen from 1st mount point is not correct"
258
259         return 0
260 }
261 run_test 5 "security context retrieval from MDT xattr"
262
263 test_10() {
264         local filename1=$DIR/df10
265         local filename2=$DIR2/df10
266         local newsecctx="nfs_t"
267
268         # create file from 1st mount point
269         touch $filename1 || error "cannot touch $filename1"
270         ls -lZ $filename1
271
272         # change sec context from 2nd mount point
273         chcon -t $newsecctx $filename2
274         ls -lZ $filename2
275
276         # get sec context from 1st mount point
277         ls -lZ $filename1
278         local secctxseen=$(ls -lZ $filename1 | awk '{print $4}' | cut -d: -f3)
279
280         [ "$newsecctx" == "$secctxseen" ] ||
281                 error "sec context seen from 1st mount point is not correct"
282
283         return 0
284 }
285 run_test 10 "[consistency] concurrent security context change"
286
287 test_20a() {
288         local uname=$(getent passwd $RUNAS_ID | cut -d: -f1)
289         local filename1=$DIR/df20a
290         local filename2=$DIR2/df20a
291         local req_delay=20
292
293         # sleep some time in ll_create_nd()
294         #define OBD_FAIL_LLITE_CREATE_FILE_PAUSE   0x1409
295         do_facet client "$LCTL set_param fail_val=$req_delay fail_loc=0x1409"
296
297         # create file on first mount point
298         $PDSH ${uname}@localhost "touch $filename1" &
299         local touchpid=$!
300         sleep 5
301
302         if [[ -z "$(ps h -o comm -p $touchpid)" ]]; then
303                 error "touch failed to sleep, pid=$touchpid"
304         fi
305
306         # get sec info on second mount point
307         if [ -e "$filename2" ]; then
308                 secinfo2=$(ls -lZ $filename2 | awk '{print $4}')
309         fi
310
311         # get sec info on first mount point
312         wait $touchpid
313         secinfo1=$(ls -lZ $filename1 | awk '{print $4}')
314
315         # compare sec contexts
316         [ -z "$secinfo2" -o "$secinfo1" == "$secinfo2" ] ||
317                 error "sec context seen from 2nd mount point is not correct"
318
319         return 0
320 }
321 run_test 20a "[atomicity] concurrent access from another client (file)"
322
323 test_20b() {
324         local uname=$(getent passwd $RUNAS_ID | cut -d: -f1)
325         local dirname1=$DIR/dd20b
326         local dirname2=$DIR2/dd20b
327         local req_delay=20
328
329         # sleep some time in ll_create_nd()
330         #define OBD_FAIL_LLITE_NEWNODE_PAUSE     0x140a
331         do_facet client "$LCTL set_param fail_val=$req_delay fail_loc=0x140a"
332
333         # create file on first mount point
334         $PDSH ${uname}@localhost "mkdir $dirname1" &
335         local mkdirpid=$!
336         sleep 5
337
338         if [[ -z "$(ps h -o comm -p $mkdirpid)" ]]; then
339                 error "mkdir failed to sleep, pid=$mkdirpid"
340         fi
341
342         # get sec info on second mount point
343         if [ -e "$dirname2" ]; then
344                 secinfo2=$(ls -ldZ $dirname2 | awk '{print $4}')
345         else
346                 secinfo2=""
347         fi
348
349         # get sec info on first mount point
350         wait $mkdirpid
351         secinfo1=$(ls -ldZ $dirname1 | awk '{print $4}')
352
353         # compare sec contexts
354         [ -z "$secinfo2" -o "$secinfo1" == "$secinfo2" ] ||
355                 error "sec context seen from 2nd mount point is not correct"
356
357         return 0
358 }
359 run_test 20b "[atomicity] concurrent access from another client (dir)"
360
361 test_20c() {
362         local dirname1=$DIR/dd20c
363         local dirname2=$DIR2/dd20c
364         local req_delay=20
365
366         # sleep some time in ll_create_nd()
367         #define OBD_FAIL_LLITE_SETDIRSTRIPE_PAUSE     0x140b
368         do_facet client "$LCTL set_param fail_val=$req_delay fail_loc=0x140b"
369
370         # create file on first mount point
371         lfs mkdir -c0 $dirname1 &
372         local mkdirpid=$!
373         sleep 5
374
375         if [[ -z "$(ps h -o comm -p $mkdirpid)" ]]; then
376                 error "lfs mkdir failed to sleep, pid=$mkdirpid"
377         fi
378
379         # get sec info on second mount point
380         if [ -e "$dirname2" ]; then
381                 secinfo2=$(ls -ldZ $dirname2 | awk '{print $4}')
382         else
383                 secinfo2=""
384         fi
385
386         # get sec info on first mount point
387         wait $mkdirpid
388         secinfo1=$(ls -ldZ $dirname1 | awk '{print $4}')
389
390         # compare sec contexts
391         [ -z "$secinfo2" -o "$secinfo1" == "$secinfo2" ] ||
392                 error "sec context seen from 2nd mount point is not correct"
393
394         return 0
395 }
396 run_test 20c "[atomicity] concurrent access from another client (dir via lfs)"
397
398
399 complete $SECONDS
400 check_and_cleanup_lustre
401 exit_status
402