diff options
| -rw-r--r-- | lib/oeqa/runtime/cases/smack.py | 103 |
1 files changed, 15 insertions, 88 deletions
diff --git a/lib/oeqa/runtime/cases/smack.py b/lib/oeqa/runtime/cases/smack.py index b8255c7..6b87574 100644 --- a/lib/oeqa/runtime/cases/smack.py +++ b/lib/oeqa/runtime/cases/smack.py | |||
| @@ -15,17 +15,16 @@ class SmackBasicTest(OERuntimeTestCase): | |||
| 15 | 15 | ||
| 16 | @classmethod | 16 | @classmethod |
| 17 | def setUpClass(cls): | 17 | def setUpClass(cls): |
| 18 | cls.smack_path = "" | ||
| 19 | cls.current_label = "" | 18 | cls.current_label = "" |
| 20 | cls.uid = 1000 | 19 | cls.uid = 1000 |
| 20 | status, output = cls.tc.target.run("grep smack /proc/mounts | awk '{print $2}'") | ||
| 21 | cls.smack_path = output | ||
| 21 | 22 | ||
| 22 | @skipIfNotFeature('smack', | 23 | @skipIfNotFeature('smack', |
| 23 | 'Test requires smack to be in DISTRO_FEATURES') | 24 | 'Test requires smack to be in DISTRO_FEATURES') |
| 24 | @OEHasPackage(['smack-test']) | 25 | @OEHasPackage(['smack-test']) |
| 25 | @OETestDepends(['ssh.SSHTest.test_ssh']) | 26 | @OETestDepends(['ssh.SSHTest.test_ssh']) |
| 26 | def test_smack_basic(self): | 27 | def test_smack_basic(self): |
| 27 | status, output = self.target.run("grep smack /proc/mounts | awk '{print $2}'") | ||
| 28 | self.smack_path = output | ||
| 29 | status,output = self.target.run("cat /proc/self/attr/current") | 28 | status,output = self.target.run("cat /proc/self/attr/current") |
| 30 | self.current_label = output.strip() | 29 | self.current_label = output.strip() |
| 31 | 30 | ||
| @@ -41,11 +40,11 @@ class SmackBasicTest(OERuntimeTestCase): | |||
| 41 | "Status and output: %d %s" %(status, output)) | 40 | "Status and output: %d %s" %(status, output)) |
| 42 | status, output = self.target.run("chsmack %s" %filename) | 41 | status, output = self.target.run("chsmack %s" %filename) |
| 43 | self.target.run("rm %s" %filename) | 42 | self.target.run("rm %s" %filename) |
| 44 | m = re.search('(?<=access=")\S+(?=")', output) | 43 | m = re.search('(access=")\S+(?=")', output) |
| 45 | if m is None: | 44 | if m is None: |
| 46 | self.fail("Did not find access attribute") | 45 | self.fail("Did not find access attribute") |
| 47 | else: | 46 | else: |
| 48 | label_retrieved = m .group(0) | 47 | label_retrieved = re.split("access=\"", output)[1][:-1] |
| 49 | self.assertEqual( | 48 | self.assertEqual( |
| 50 | LABEL, label_retrieved, | 49 | LABEL, label_retrieved, |
| 51 | "label not set correctly. expected and gotten: " | 50 | "label not set correctly. expected and gotten: " |
| @@ -64,11 +63,11 @@ class SmackBasicTest(OERuntimeTestCase): | |||
| 64 | "Status and output: %d %s" %(status, output)) | 63 | "Status and output: %d %s" %(status, output)) |
| 65 | status, output = self.target.run("chsmack %s" %filename) | 64 | status, output = self.target.run("chsmack %s" %filename) |
| 66 | self.target.run("rm %s" %filename) | 65 | self.target.run("rm %s" %filename) |
| 67 | m= re.search('(?<=execute=")\S+(?=")', output) | 66 | m= re.search('(execute=")\S+(?=")', output) |
| 68 | if m is None: | 67 | if m is None: |
| 69 | self.fail("Did not find execute attribute") | 68 | self.fail("Did not find execute attribute") |
| 70 | else: | 69 | else: |
| 71 | label_retrieved = m.group(0) | 70 | label_retrieved = re.split("execute=\"", output)[1][:-1] |
| 72 | self.assertEqual( | 71 | self.assertEqual( |
| 73 | LABEL, label_retrieved, | 72 | LABEL, label_retrieved, |
| 74 | "label not set correctly. expected and gotten: " + | 73 | "label not set correctly. expected and gotten: " + |
| @@ -87,11 +86,11 @@ class SmackBasicTest(OERuntimeTestCase): | |||
| 87 | "Status and output: %d %s" %(status, output)) | 86 | "Status and output: %d %s" %(status, output)) |
| 88 | status, output = self.target.run("chsmack %s" %filename) | 87 | status, output = self.target.run("chsmack %s" %filename) |
| 89 | self.target.run("rm %s" %filename) | 88 | self.target.run("rm %s" %filename) |
| 90 | m = re.search('(?<=mmap=")\S+(?=")', output) | 89 | m = re.search('(mmap=")\S+(?=")', output) |
| 91 | if m is None: | 90 | if m is None: |
| 92 | self.fail("Did not find mmap attribute") | 91 | self.fail("Did not find mmap attribute") |
| 93 | else: | 92 | else: |
| 94 | label_retrieved = m.group(0) | 93 | label_retrieved = re.split("mmap=\"", output)[1][:-1] |
| 95 | self.assertEqual( | 94 | self.assertEqual( |
| 96 | LABEL, label_retrieved, | 95 | LABEL, label_retrieved, |
| 97 | "label not set correctly. expected and gotten: " + | 96 | "label not set correctly. expected and gotten: " + |
| @@ -109,11 +108,11 @@ class SmackBasicTest(OERuntimeTestCase): | |||
| 109 | "Status and output: %d %s" %(status, output)) | 108 | "Status and output: %d %s" %(status, output)) |
| 110 | status, output = self.target.run("chsmack %s" %directory) | 109 | status, output = self.target.run("chsmack %s" %directory) |
| 111 | self.target.run("rmdir %s" %directory) | 110 | self.target.run("rmdir %s" %directory) |
| 112 | m = re.search('(?<=transmute=")\S+(?=")', output) | 111 | m = re.search('(transmute=")\S+(?=")', output) |
| 113 | if m is None: | 112 | if m is None: |
| 114 | self.fail("Did not find transmute attribute") | 113 | self.fail("Did not find transmute attribute") |
| 115 | else: | 114 | else: |
| 116 | label_retrieved = m.group(0) | 115 | label_retrieved = re.split("transmute=\"", output)[1][:-1] |
| 117 | self.assertEqual( | 116 | self.assertEqual( |
| 118 | "TRUE", label_retrieved, | 117 | "TRUE", label_retrieved, |
| 119 | "label not set correctly. expected and gotten: " + | 118 | "label not set correctly. expected and gotten: " + |
| @@ -127,10 +126,10 @@ class SmackBasicTest(OERuntimeTestCase): | |||
| 127 | ''' | 126 | ''' |
| 128 | 127 | ||
| 129 | labelf = "/proc/self/attr/current" | 128 | labelf = "/proc/self/attr/current" |
| 130 | command = "/bin/sh -c 'echo PRIVILEGED >%s; cat %s'" %(labelf, labelf) | 129 | command = "/bin/sh -c 'echo PRIVILEGED >%s'; cat %s" %(labelf, labelf) |
| 131 | 130 | ||
| 132 | status, output = self.target.run( | 131 | status, output = self.target.run( |
| 133 | "notroot.py 0 %s %s" %(self.current_label, command)) | 132 | "/usr/sbin/notroot.py 0 %s %s" %(self.current_label, command)) |
| 134 | 133 | ||
| 135 | self.assertIn("PRIVILEGED", output, | 134 | self.assertIn("PRIVILEGED", output, |
| 136 | "Privilege process did not change label.Output: %s" %output) | 135 | "Privilege process did not change label.Output: %s" %output) |
| @@ -142,7 +141,7 @@ class SmackBasicTest(OERuntimeTestCase): | |||
| 142 | 141 | ||
| 143 | command = "/bin/sh -c 'echo %s >/proc/self/attr/current'" %LABEL | 142 | command = "/bin/sh -c 'echo %s >/proc/self/attr/current'" %LABEL |
| 144 | status, output = self.target.run( | 143 | status, output = self.target.run( |
| 145 | "notroot.py %d %s %s" | 144 | "/usr/sbin/notroot.py %d %s %s" |
| 146 | %(self.uid, self.current_label, command) + | 145 | %(self.uid, self.current_label, command) + |
| 147 | " 2>&1 | grep 'Operation not permitted'" ) | 146 | " 2>&1 | grep 'Operation not permitted'" ) |
| 148 | 147 | ||
| @@ -160,9 +159,9 @@ class SmackBasicTest(OERuntimeTestCase): | |||
| 160 | filename = "/tmp/test_unprivileged_change_file_label" | 159 | filename = "/tmp/test_unprivileged_change_file_label" |
| 161 | 160 | ||
| 162 | self.target.run("touch %s" % filename) | 161 | self.target.run("touch %s" % filename) |
| 163 | self.target.run("notroot.py %d %s" %(self.uid, self.current_label)) | 162 | self.target.run("/usr/sbin/notroot.py %d %s" %(self.uid, self.current_label)) |
| 164 | status, output = self.target.run( | 163 | status, output = self.target.run( |
| 165 | "notroot.py " + | 164 | "/usr/sbin/notroot.py " + |
| 166 | "%d unprivileged %s -a %s %s 2>&1 " %(self.uid, chsmack, LABEL, filename) + | 165 | "%d unprivileged %s -a %s %s 2>&1 " %(self.uid, chsmack, LABEL, filename) + |
| 167 | "| grep 'Operation not permitted'" ) | 166 | "| grep 'Operation not permitted'" ) |
| 168 | 167 | ||
| @@ -347,78 +346,6 @@ class SmackBasicTest(OERuntimeTestCase): | |||
| 347 | 346 | ||
| 348 | 347 | ||
| 349 | @OETestDepends(['smack.SmackBasicTest.test_smack_basic']) | 348 | @OETestDepends(['smack.SmackBasicTest.test_smack_basic']) |
| 350 | def test_smack_mmap_enforced(self): | ||
| 351 | '''Test if smack mmap access is enforced''' | ||
| 352 | raise unittest.SkipTest("Depends on mmap_test, which was removed from the layer while investigating its license.") | ||
| 353 | |||
| 354 | # 12345678901234567890123456789012345678901234567890123456 | ||
| 355 | delr1="mmap_label mmap_test_label1 -----" | ||
| 356 | delr2="mmap_label mmap_test_label2 -----" | ||
| 357 | delr3="mmap_file_label mmap_test_label1 -----" | ||
| 358 | delr4="mmap_file_label mmap_test_label2 -----" | ||
| 359 | |||
| 360 | RuleA="mmap_label mmap_test_label1 rw---" | ||
| 361 | RuleB="mmap_label mmap_test_label2 r--at" | ||
| 362 | RuleC="mmap_file_label mmap_test_label1 rw---" | ||
| 363 | RuleD="mmap_file_label mmap_test_label2 rwxat" | ||
| 364 | |||
| 365 | mmap_label="mmap_label" | ||
| 366 | file_label="mmap_file_label" | ||
| 367 | test_file = "/usr/sbin/smack_test_mmap" | ||
| 368 | mmap_exe = "/tmp/mmap_test" | ||
| 369 | status, echo = self.target.run("which echo") | ||
| 370 | status, output = self.target.run( | ||
| 371 | "notroot.py %d %s %s 'test' > %s" \ | ||
| 372 | %(self.uid, self.current_label, echo, test_file)) | ||
| 373 | status, output = self.target.run("ls %s" %test_file) | ||
| 374 | self.assertEqual(status, 0, "Could not create mmap test file") | ||
| 375 | self.target.run("chsmack -m %s %s" %(file_label, test_file)) | ||
| 376 | self.target.run("chsmack -e %s %s" %(mmap_label, mmap_exe)) | ||
| 377 | |||
| 378 | # test with no rules with mmap label or exec label as subject | ||
| 379 | # access should be granted | ||
| 380 | self.target.run('echo -n "%s" > %s/load' %(delr1, self.smack_path)) | ||
| 381 | self.target.run('echo -n "%s" > %s/load' %(delr2, self.smack_path)) | ||
| 382 | self.target.run('echo -n "%s" > %s/load' %(delr3, self.smack_path)) | ||
| 383 | self.target.run('echo -n "%s" > %s/load' %(delr4, self.smack_path)) | ||
| 384 | status, output = self.target.run("%s %s 0 2" % (mmap_exe, test_file)) | ||
| 385 | self.assertEqual( | ||
| 386 | status, 0, | ||
| 387 | "Should have mmap access without rules. Output: %s" %output) | ||
| 388 | |||
| 389 | # add rules that do not match access required | ||
| 390 | self.target.run('echo -n "%s" > %s/load' %(RuleA, self.smack_path)) | ||
| 391 | self.target.run('echo -n "%s" > %s/load' %(RuleB, self.smack_path)) | ||
| 392 | status, output = self.target.run("%s %s 0 2" % (mmap_exe, test_file)) | ||
| 393 | self.assertNotEqual( | ||
| 394 | status, 0, | ||
| 395 | "Should not have mmap access with unmatching rules. " + | ||
| 396 | "Output: %s" %output) | ||
| 397 | self.assertIn( | ||
| 398 | "Permission denied", output, | ||
| 399 | "Mmap access should be denied with unmatching rules") | ||
| 400 | |||
| 401 | # add rule to match only partially (one way) | ||
| 402 | self.target.run('echo -n "%s" > %s/load' %(RuleC, self.smack_path)) | ||
| 403 | status, output = self.target.run("%s %s 0 2" %(mmap_exe, test_file)) | ||
| 404 | self.assertNotEqual( | ||
| 405 | status, 0, | ||
| 406 | "Should not have mmap access with partial matching rules. " + | ||
| 407 | "Output: %s" %output) | ||
| 408 | self.assertIn( | ||
| 409 | "Permission denied", output, | ||
| 410 | "Mmap access should be denied with partial matching rules") | ||
| 411 | |||
| 412 | # add rule to match fully | ||
| 413 | self.target.run('echo -n "%s" > %s/load' %(RuleD, self.smack_path)) | ||
| 414 | status, output = self.target.run("%s %s 0 2" %(mmap_exe, test_file)) | ||
| 415 | self.assertEqual( | ||
| 416 | status, 0, | ||
| 417 | "Should have mmap access with full matching rules." + | ||
| 418 | "Output: %s" %output) | ||
| 419 | |||
| 420 | |||
| 421 | @OETestDepends(['smack.SmackBasicTest.test_smack_basic']) | ||
| 422 | def test_smack_transmute_dir(self): | 349 | def test_smack_transmute_dir(self): |
| 423 | '''Test if smack transmute attribute works | 350 | '''Test if smack transmute attribute works |
| 424 | 351 | ||
