blob: 6b361cabc5f1d7f54aff285fb3bfbee11eac12fc [file] [log] [blame]
Brad Bishop15ae2502019-06-18 21:44:24 -04001#!/usr/bin/env python
2#
3# Authors: Cristina Moraru <cristina.moraru@intel.com>
4# Alexandru Cornea <alexandru.cornea@intel.com>
5
6import string
7from time import sleep
8from oeqa.runtime.case import OERuntimeTestCase
9from oeqa.core.decorator.depends import OETestDepends
10from oeqa.runtime.decorator.package import OEHasPackage
11from oeqa.core.decorator.data import skipIfNotFeature
12from oeqa.core.decorator.data import skipIfDataVar, skipIfNotDataVar
13import bb
14blacklist = ["/usr/bin/uz", "/bin/su.shadow"]
15
16class IMACheck(OERuntimeTestCase):
17
18 @classmethod
19 def setUpClass(cls):
20 locations = ["/bin", "/usr/bin"]
21 cls.binaries = []
22 for l in locations:
23 status, output = cls.tc.target.run("find %s -type f" % l)
24 cls.binaries.extend(output.split("\n"))
25
26 cls.total = len(cls.binaries)
27
28
29 @OETestDepends(['ssh.SSHTest.test_ssh'])
30 def test_ima_enabled(self):
31 ''' Test if IMA policy is loaded before systemd starts'''
32
33 ima_search = "ima: "
34 systemd_search = "systemd .* running"
35 status, output = self.target.run("dmesg | grep -n '%s'" % ima_search)
36 self.assertEqual( status, 0, "Did not find '%s' in dmesg" % ima_search)
37
38
39 @skipIfNotFeature('systemd',
40 'Test requires systemd to be in DISTRO_FEATURES')
41 @skipIfNotDataVar('VIRTUAL-RUNTIME_init_manager', 'systemd',
42 'systemd is not the init manager for this image')
43 @OETestDepends(['ima.IMACheck.test_ima_enabled'])
44 def test_ima_before_systemd(self):
45 ''' Test if IMA policy is loaded before systemd starts'''
46 ima_search = "ima: "
47 systemd_search = "systemd .* running"
48 status, output = self.target.run("dmesg | grep -n '%s'" % ima_search)
49 self.assertEqual( status, 0, "Did not find '%s' in dmesg" % ima_search)
50 ima_id = int(output.split(":")[0])
51 status, output = self.target.run("dmesg | grep -n '%s'" % systemd_search)
52 self.assertEqual(status, 0, "Did not find '%s' in dmesg" % systemd_search)
53 init_id = int(output.split(":")[0])
54 if ima_id > init_id:
55 self.fail("IMA does not start before systemd")
56
57
58 @OETestDepends(['ima.IMACheck.test_ima_enabled'])
59 def test_ima_hash(self):
60 ''' Test if IMA stores correct file hash '''
Andrew Geisslerdc9d6142023-05-19 09:38:37 -050061 filename = "/etc/ld.so.cache"
Brad Bishop15ae2502019-06-18 21:44:24 -040062 ima_measure_file = "/sys/kernel/security/ima/ascii_runtime_measurements"
Brad Bishop15ae2502019-06-18 21:44:24 -040063
64 # wait for the IMA system to update the entry
Andrew Geisslerdc9d6142023-05-19 09:38:37 -050065 maximum_tries = 3
Brad Bishop15ae2502019-06-18 21:44:24 -040066 tries = 0
Andrew Geisslerdc9d6142023-05-19 09:38:37 -050067 status, output = self.target.run("sha256sum %s" %filename)
Brad Bishop15ae2502019-06-18 21:44:24 -040068 sleep(2)
69 current_hash = output.split()[0]
70 ima_hash = ""
71
72 while tries < maximum_tries:
Andrew Geisslerdc9d6142023-05-19 09:38:37 -050073 status, output = self.target.run("cat %s | grep -e '%s'" \
Brad Bishop15ae2502019-06-18 21:44:24 -040074 % (ima_measure_file, filename))
75 # get last entry, 4th field
76 if status == 0:
77 tokens = output.split("\n")[-1].split()[3]
78 ima_hash = tokens.split(":")[1]
79 if ima_hash == current_hash:
80 break
81
82 tries += 1
83 sleep(1)
84
85 # clean target
86 self.target.run("rm %s" % filename)
87 if ima_hash != current_hash:
88 self.fail("Hash stored by IMA does not match actual hash")
89
90
91 @OETestDepends(['ima.IMACheck.test_ima_enabled'])
92 def test_ima_signature(self):
93 ''' Test if IMA stores correct signature for system binaries'''
94 passed = 0
95 failed = 0
96 for b in self.binaries:
97 if b in blacklist:
98 continue
99 status, output = self.target.run("evmctl ima_verify %s" % b)
100 if status != 0:
101 failed += 1
102 else:
103 passed += 1
104
105 if failed == self.total:
106 self.fail("Signature verifications failed (%s)" % self.total)
107
108 #bb.warn("pass: %s, fail: %s, Total: %s" % (passed, failed, total))
109
110 @OETestDepends(['ima.IMACheck.test_ima_enabled'])
111 def test_ima_overwrite(self):
112 ''' Test if IMA prevents overwriting signed files '''
113 passed = 0
114 failed = 0
115 for b in self.binaries:
116 if b in blacklist:
117 continue
118 self.target.run("echo 'foo' >> %s" % b )
119 status, output = self.target.run("evmctl ima_verify %s" % b)
120
121 if status != 0:
122 failed += 1
123 else:
124 passed += 1
125
126 if failed == self.total:
127 self.fail("Overwritting verifications failed (%s)" % self.total)