1#!/bin/sh 2# SPDX-License-Identifier: GPL-2.0-or-later 3# Copyright (c) 2009 IBM Corporation 4# Copyright (c) 2018-2019 Petr Vorel <pvorel@suse.cz> 5# Author: Mimi Zohar <zohar@linux.ibm.com> 6# 7# Verify that measurements are added to the measurement list based on policy. 8 9TST_NEEDS_CMDS="awk cut" 10TST_SETUP="setup" 11TST_CNT=3 12TST_NEEDS_DEVICE=1 13 14. ima_setup.sh 15 16setup() 17{ 18 check_ima_policy "tcb" 19 20 TEST_FILE="$PWD/test.txt" 21 POLICY="$IMA_DIR/policy" 22 [ -f "$POLICY" ] || tst_res TINFO "not using default policy" 23 DIGEST_INDEX= 24 25 local template="$(tail -1 $ASCII_MEASUREMENTS | cut -d' ' -f 3)" 26 local i 27 28 # parse digest index 29 # https://www.kernel.org/doc/html/latest/security/IMA-templates.html#use 30 case "$template" in 31 ima|ima-ng|ima-sig) DIGEST_INDEX=4 ;; 32 *) 33 # using ima_template_fmt kernel parameter 34 local IFS="|" 35 i=4 36 for word in $template; do 37 if [ "$word" = 'd' -o "$word" = 'd-ng' ]; then 38 DIGEST_INDEX=$i 39 break 40 fi 41 i=$((i+1)) 42 done 43 esac 44 45 [ -z "$DIGEST_INDEX" ] && tst_brk TCONF \ 46 "Cannot find digest index (template: '$template')" 47} 48 49# TODO: find support for rmd128 rmd256 rmd320 wp256 wp384 tgr128 tgr160 50compute_digest() 51{ 52 local algorithm="$1" 53 local file="$2" 54 local digest 55 56 digest="$(${algorithm}sum $file 2>/dev/null | cut -f1 -d ' ')" 57 if [ -n "$digest" ]; then 58 echo "$digest" 59 return 0 60 fi 61 62 digest="$(openssl $algorithm $file 2>/dev/null | cut -f2 -d ' ')" 63 if [ -n "$digest" ]; then 64 echo "$digest" 65 return 0 66 fi 67 68 # uncommon ciphers 69 local arg="$algorithm" 70 case "$algorithm" in 71 tgr192) arg="tiger" ;; 72 wp512) arg="whirlpool" ;; 73 esac 74 75 digest="$(rdigest --$arg $file 2>/dev/null | cut -f1 -d ' ')" 76 if [ -n "$digest" ]; then 77 echo "$digest" 78 return 0 79 fi 80 return 1 81} 82 83ima_check() 84{ 85 local delimiter=':' 86 local algorithm digest expected_digest line 87 88 # need to read file to get updated $ASCII_MEASUREMENTS 89 cat $TEST_FILE > /dev/null 90 91 line="$(grep $TEST_FILE $ASCII_MEASUREMENTS | tail -1)" 92 if [ -z "$line" ]; then 93 tst_res TFAIL "cannot find measurement record for '$TEST_FILE'" 94 return 95 fi 96 tst_res TINFO "measurement record: '$line'" 97 98 digest=$(echo "$line" | cut -d' ' -f $DIGEST_INDEX) 99 if [ -z "$digest" ]; then 100 tst_res TFAIL "cannot find digest (index: $DIGEST_INDEX)" 101 return 102 fi 103 104 if [ "${digest#*$delimiter}" != "$digest" ]; then 105 algorithm=$(echo "$digest" | cut -d $delimiter -f 1) 106 digest=$(echo "$digest" | cut -d $delimiter -f 2) 107 else 108 case "${#digest}" in 109 32) algorithm="md5" ;; 110 40) algorithm="sha1" ;; 111 *) 112 tst_res TFAIL "algorithm must be either md5 or sha1 (digest: '$digest')" 113 return ;; 114 esac 115 fi 116 if [ -z "$algorithm" ]; then 117 tst_res TFAIL "cannot find algorithm" 118 return 119 fi 120 if [ -z "$digest" ]; then 121 tst_res TFAIL "cannot find digest" 122 return 123 fi 124 125 tst_res TINFO "computing digest for $algorithm algorithm" 126 expected_digest="$(compute_digest $algorithm $TEST_FILE)" || \ 127 tst_brk TCONF "cannot compute digest for $algorithm algorithm" 128 129 if [ "$digest" = "$expected_digest" ]; then 130 tst_res TPASS "correct digest found" 131 else 132 tst_res TFAIL "digest not found" 133 fi 134} 135 136check_iversion_support() 137{ 138 local device mount fs 139 140 tst_kvcmp -ge "4.16" && return 0 141 142 device="$(df . | sed -e 1d | cut -f1 -d ' ')" 143 mount="$(grep $device /proc/mounts | head -1)" 144 fs="$(echo $mount | awk '{print $3'})" 145 146 case "$fs" in 147 ext[2-4]) 148 if ! echo "$mount" | grep -q -w "i_version"; then 149 tst_res TCONF "device '$device' is not mounted with iversion, please mount it with 'mount $device -o remount,iversion'" 150 return 1 151 fi 152 ;; 153 xfs) 154 if dmesg | grep -q "XFS.*Mounting V[1-4] Filesystem"; then 155 tst_res TCONF "XFS Filesystem >= V5 required for iversion support" 156 return 1 157 fi 158 ;; 159 '') 160 tst_res TWARN "could not find mount info for device '$device'" 161 ;; 162 esac 163 164 return 0 165} 166 167test1() 168{ 169 tst_res TINFO "verify adding record to the IMA measurement list" 170 ROD echo "$(date) this is a test file" \> $TEST_FILE 171 ima_check 172} 173 174test2() 175{ 176 177 tst_res TINFO "verify updating record in the IMA measurement list" 178 check_iversion_support || return 179 ROD echo "$(date) modified file" \> $TEST_FILE 180 ima_check 181} 182 183test3() 184{ 185 local user="nobody" 186 local dir="$PWD/user" 187 local file="$dir/test.txt" 188 189 # Default policy does not measure user files 190 tst_res TINFO "verify not measuring user files" 191 tst_check_cmds sudo 192 193 if ! id $user >/dev/null 2>/dev/null; then 194 tst_res TCONF "missing system user $user (wrong installation)" 195 return 196 fi 197 198 mkdir -m 0700 $dir 199 chown $user $dir 200 cd $dir 201 # need to read file to get updated $ASCII_MEASUREMENTS 202 sudo -n -u $user sh -c "echo $(date) user file > $file; cat $file > /dev/null" 203 cd .. 204 205 EXPECT_FAIL "grep $file $ASCII_MEASUREMENTS" 206} 207 208tst_run 209