test_pal.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. #!/usr/bin/env python3
  2. import ast
  3. import collections
  4. import mmap
  5. import os
  6. import pathlib
  7. import random
  8. import shutil
  9. import string
  10. import subprocess
  11. import unittest
  12. from datetime import datetime, timedelta
  13. from regression import (
  14. HAS_SGX,
  15. RegressionTestCase,
  16. expectedFailureIf,
  17. )
  18. CPUINFO_FLAGS_WHITELIST = [
  19. 'fpu', 'vme', 'de', 'pse', 'tsc', 'msr', 'pae', 'mce', 'cx8', 'apic', 'sep',
  20. 'mtrr', 'pge', 'mca', 'cmov', 'pat', 'pse36', 'pn', 'clflush', 'dts',
  21. 'acpi', 'mmx', 'fxsr', 'sse', 'sse2', 'ss', 'ht', 'tm', 'ia64', 'pbe',
  22. ]
  23. class TC_00_Basic(RegressionTestCase):
  24. def test_000_atomic_math(self):
  25. stdout, stderr = self.run_binary(['AtomicMath'])
  26. self.assertIn('Subtract INT_MIN: Both values match 2147483648', stderr)
  27. self.assertIn('Subtract INT_MAX: Both values match -2147483647', stderr)
  28. self.assertIn('Subtract LLONG_MIN: Both values match -9223372036854775808', stderr)
  29. self.assertIn('Subtract LLONG_MAX: Both values match -9223372036854775807', stderr)
  30. def test_001_path_normalization(self):
  31. stdout, stderr = self.run_binary(['normalize_path'])
  32. self.assertIn("Success!\n", stderr)
  33. class TC_01_Bootstrap(RegressionTestCase):
  34. def test_100_basic_boostrapping(self):
  35. stdout, stderr = self.run_binary(['Bootstrap'])
  36. # Basic Bootstrapping
  37. self.assertIn('User Program Started', stderr)
  38. # Control Block: Executable Name
  39. self.assertIn('Loaded Executable: file:Bootstrap', stderr)
  40. # One Argument Given
  41. self.assertIn('# of Arguments: 1', stderr)
  42. self.assertIn('argv[0] = Bootstrap', stderr)
  43. # Control Block: Debug Stream (Inline)
  44. self.assertIn('Written to Debug Stream', stdout)
  45. # Control Block: Page Size
  46. self.assertIn('Page Size: {}'.format(mmap.PAGESIZE), stderr)
  47. # Control Block: Allocation Alignment
  48. self.assertIn('Allocation Alignment: {}'.format(mmap.ALLOCATIONGRANULARITY), stderr)
  49. # Control Block: Executable Range
  50. self.assertIn('Executable Range OK', stderr)
  51. def test_101_basic_boostrapping_five_arguments(self):
  52. stdout, stderr = self.run_binary(['Bootstrap', 'a', 'b', 'c', 'd'])
  53. # Five Arguments Given
  54. self.assertIn('# of Arguments: 5', stderr)
  55. self.assertIn('argv[1] = a', stderr)
  56. self.assertIn('argv[2] = b', stderr)
  57. self.assertIn('argv[3] = c', stderr)
  58. self.assertIn('argv[4] = d', stderr)
  59. def test_102_cpuinfo(self):
  60. with open('/proc/cpuinfo') as file:
  61. cpuinfo = file.read().strip().split('\n\n')[-1]
  62. cpuinfo = dict(map(str.strip, line.split(':'))
  63. for line in cpuinfo.split('\n'))
  64. if 'flags' in cpuinfo:
  65. cpuinfo['flags'] = ' '.join(flag for flag in cpuinfo['flags']
  66. if flag in CPUINFO_FLAGS_WHITELIST)
  67. stdout, stderr = self.run_binary(['Bootstrap'])
  68. self.assertIn('CPU num: {}'.format(int(cpuinfo['processor']) + 1),
  69. stderr)
  70. self.assertIn('CPU vendor: {[vendor_id]}'.format(cpuinfo), stderr)
  71. self.assertIn('CPU brand: {[model name]}'.format(cpuinfo), stderr)
  72. self.assertIn('CPU family: {[cpu family]}'.format(cpuinfo), stderr)
  73. self.assertIn('CPU model: {[model]}'.format(cpuinfo), stderr)
  74. self.assertIn('CPU stepping: {[stepping]}'.format(cpuinfo), stderr)
  75. self.assertIn('CPU flags: {[flags]}'.format(cpuinfo), stderr)
  76. def test_103_dotdot(self):
  77. stdout, stderr = self.run_binary(['..Bootstrap'])
  78. self.assertIn('User Program Started', stderr)
  79. def test_104_manifest_as_executable_name(self):
  80. manifest = self.get_manifest('Bootstrap2')
  81. stdout, stderr = self.run_binary([manifest])
  82. self.assertIn('User Program Started', stderr)
  83. self.assertIn('Loaded Manifest: file:' + manifest, stderr)
  84. def test_105_manifest_as_argument(self):
  85. manifest = self.get_manifest('Bootstrap4')
  86. stdout, stderr = self.run_binary([manifest])
  87. self.assertIn('Loaded Manifest: file:' + manifest, stderr)
  88. self.assertIn('Loaded Executable: file:Bootstrap', stderr)
  89. def test_106_manifest_with_shebang(self):
  90. manifest = self.get_manifest('Bootstrap4')
  91. stdout, stderr = self.run_binary(['./' + manifest])
  92. self.assertIn('Loaded Manifest: file:' + manifest, stderr)
  93. self.assertIn('Loaded Executable: file:Bootstrap', stderr)
  94. self.assertIn('argv[0] = Bootstrap', stderr)
  95. def test_110_preload_libraries(self):
  96. stdout, stderr = self.run_binary(['Bootstrap3'])
  97. self.assertIn('Binary 1 Preloaded', stderr)
  98. self.assertIn('Binary 2 Preloaded', stderr)
  99. self.assertIn('Preloaded Function 1 Called', stderr)
  100. self.assertIn('Preloaded Function 2 Called', stderr)
  101. def test_111_preload_libraries(self):
  102. # Bootstrap without Executable but Preload Libraries
  103. stdout, stderr = self.run_binary([self.get_manifest('Bootstrap5')])
  104. self.assertIn('Binary 1 Preloaded', stderr)
  105. self.assertIn('Binary 2 Preloaded', stderr)
  106. @unittest.skipUnless(HAS_SGX, 'this test requires SGX')
  107. def test_120_8gb_enclave(self):
  108. manifest = self.get_manifest('Bootstrap6')
  109. stdout, stderr = self.run_binary([manifest], timeout=360)
  110. self.assertIn('Loaded Manifest: file:' + manifest, stderr)
  111. self.assertIn('Executable Range OK', stderr)
  112. def test_130_large_number_of_items_in_manifest(self):
  113. stdout, stderr = self.run_binary([self.get_manifest('Bootstrap7')])
  114. self.assertIn('key1000=na', stderr)
  115. self.assertIn('key1=na', stderr)
  116. @unittest.skip('this is broken on non-SGX, see #860')
  117. def test_140_missing_executable_and_manifest(self):
  118. try:
  119. stdout, stderr = self.run_binary(['fakenews'])
  120. self.fail(
  121. 'expected non-zero returncode, stderr: {!r}'.format(stderr))
  122. except subprocess.CalledProcessError as e:
  123. self.assertIn('USAGE: ', e.stderr.decode())
  124. class TC_02_Symbols(RegressionTestCase):
  125. ALL_SYMBOLS = [
  126. 'DkVirtualMemoryAlloc',
  127. 'DkVirtualMemoryFree',
  128. 'DkVirtualMemoryProtect',
  129. 'DkProcessCreate',
  130. 'DkProcessExit',
  131. 'DkStreamOpen',
  132. 'DkStreamWaitForClient',
  133. 'DkStreamRead',
  134. 'DkStreamWrite',
  135. 'DkStreamDelete',
  136. 'DkStreamMap',
  137. 'DkStreamUnmap',
  138. 'DkStreamSetLength',
  139. 'DkStreamFlush',
  140. 'DkSendHandle',
  141. 'DkReceiveHandle',
  142. 'DkStreamAttributesQuery',
  143. 'DkStreamAttributesQueryByHandle',
  144. 'DkStreamAttributesSetByHandle',
  145. 'DkStreamGetName',
  146. 'DkStreamChangeName',
  147. 'DkThreadCreate',
  148. 'DkThreadDelayExecution',
  149. 'DkThreadYieldExecution',
  150. 'DkThreadExit',
  151. 'DkThreadResume',
  152. 'DkSetExceptionHandler',
  153. 'DkExceptionReturn',
  154. 'DkMutexCreate',
  155. 'DkMutexRelease',
  156. 'DkNotificationEventCreate',
  157. 'DkSynchronizationEventCreate',
  158. 'DkEventSet',
  159. 'DkEventClear',
  160. 'DkObjectsWaitAny',
  161. 'DkObjectClose',
  162. 'DkSystemTimeQuery',
  163. 'DkRandomBitsRead',
  164. 'DkInstructionCacheFlush',
  165. 'DkSegmentRegister',
  166. 'DkMemoryAvailableQuota',
  167. 'DkCreatePhysicalMemoryChannel',
  168. 'DkPhysicalMemoryCommit',
  169. 'DkPhysicalMemoryMap',
  170. ]
  171. def test_000_symbols(self):
  172. stdout, stderr = self.run_binary(['Symbols'])
  173. found_symbols = dict(line.split(' = ')
  174. for line in stderr.strip().split('\n') if line.startswith('Dk'))
  175. self.assertCountEqual(found_symbols, self.ALL_SYMBOLS)
  176. for k, v in found_symbols.items():
  177. v = ast.literal_eval(v)
  178. self.assertNotEqual(v, 0, 'symbol {} has value 0'.format(k))
  179. class TC_10_Exception(RegressionTestCase):
  180. def test_000_exception(self):
  181. stdout, stderr = self.run_binary(['Exception'])
  182. # Exception Handling (Div-by-Zero)
  183. self.assertIn('Arithmetic Exception Handler', stderr)
  184. # Exception Handling (Memory Fault)
  185. self.assertIn('Memory Fault Exception Handler', stderr)
  186. # Exception Handler Swap
  187. self.assertIn('Arithmetic Exception Handler 1', stderr)
  188. self.assertIn('Arithmetic Exception Handler 2', stderr)
  189. # Exception Handling (Set Context)
  190. self.assertIn('Arithmetic Exception Handler 1', stderr)
  191. # Exception Handling (Red zone)
  192. self.assertIn('Red zone test ok.', stderr)
  193. class TC_20_SingleProcess(RegressionTestCase):
  194. def test_000_exit_code(self):
  195. with self.expect_returncode(112):
  196. self.run_binary(['Exit'])
  197. def test_100_file(self):
  198. try:
  199. pathlib.Path('file_nonexist.tmp').unlink()
  200. except FileNotFoundError:
  201. pass
  202. pathlib.Path('file_delete.tmp').touch()
  203. with open('File', 'rb') as file:
  204. file_exist = file.read()
  205. stdout, stderr = self.run_binary(['File'])
  206. # Basic File Opening
  207. self.assertIn('File Open Test 1 OK', stderr)
  208. self.assertIn('File Open Test 2 OK', stderr)
  209. self.assertIn('File Open Test 3 OK', stderr)
  210. # Basic File Creation
  211. self.assertIn('File Creation Test 1 OK', stderr)
  212. self.assertIn('File Creation Test 2 OK', stderr)
  213. self.assertIn('File Creation Test 3 OK', stderr)
  214. # File Reading
  215. self.assertIn('Read Test 1 (0th - 40th): {}'.format(
  216. file_exist[0:40].hex()), stderr)
  217. self.assertIn('Read Test 2 (0th - 40th): {}'.format(
  218. file_exist[0:40].hex()), stderr)
  219. self.assertIn('Read Test 3 (200th - 240th): {}'.format(
  220. file_exist[200:240].hex()), stderr)
  221. # File Writing
  222. with open('file_nonexist.tmp', 'rb') as file:
  223. file_nonexist = file.read()
  224. self.assertEqual(file_exist[0:40], file_nonexist[200:240])
  225. self.assertEqual(file_exist[200:240], file_nonexist[0:40])
  226. # File Attribute Query
  227. self.assertIn('Query: type = ', stderr)
  228. self.assertIn(', size = {}'.format(len(file_exist)), stderr)
  229. # File Attribute Query by Handle
  230. self.assertIn('Query by Handle: type = ', stderr)
  231. self.assertIn(', size = {}'.format(len(file_exist)), stderr)
  232. # File Mapping
  233. self.assertIn(
  234. 'Map Test 1 (0th - 40th): {}'.format(file_exist[0:40].hex()),
  235. stderr)
  236. self.assertIn(
  237. 'Map Test 2 (200th - 240th): {}'.format(file_exist[200:240].hex()),
  238. stderr)
  239. self.assertIn(
  240. 'Map Test 3 (4096th - 4136th): {}'.format(file_exist[4096:4136].hex()),
  241. stderr)
  242. self.assertIn(
  243. 'Map Test 4 (4296th - 4336th): {}'.format(file_exist[4296:4336].hex()),
  244. stderr)
  245. # Set File Length
  246. self.assertEqual(
  247. pathlib.Path('file_nonexist.tmp').stat().st_size,
  248. mmap.ALLOCATIONGRANULARITY)
  249. # File Deletion
  250. self.assertFalse(pathlib.Path('file_delete.tmp').exists())
  251. @unittest.skipUnless(HAS_SGX, 'this test requires SGX')
  252. def test_101_nonexist_file(self):
  253. # Explicitly remove the file file_nonexist_disallowed.tmp before
  254. # running binary. Otherwise this test will fail if these tests are
  255. # run repeatedly.
  256. os.remove('file_nonexist_disallowed.tmp')
  257. stdout, stderr = self.run_binary(['File'])
  258. # Run file creation for non-existing file. This behavior is
  259. # disallowed unless sgx.allow_file_creation is explicitly set to 1.
  260. self.assertIn('File Creation Test 4 OK', stderr)
  261. def test_110_directory(self):
  262. for path in ['dir_exist.tmp', 'dir_nonexist.tmp', 'dir_delete.tmp']:
  263. try:
  264. shutil.rmtree(path)
  265. except FileNotFoundError:
  266. pass
  267. path = pathlib.Path('dir_exist.tmp')
  268. files = [path / ''.join(random.choice(string.ascii_letters)
  269. for j in range(8))
  270. for i in range(5)]
  271. path.mkdir()
  272. for p in files:
  273. p.touch()
  274. pathlib.Path('dir_delete.tmp').mkdir()
  275. stdout, stderr = self.run_binary(['Directory'])
  276. # Basic Directory Opening
  277. self.assertIn('Directory Open Test 1 OK', stderr)
  278. self.assertIn('Directory Open Test 2 OK', stderr)
  279. self.assertIn('Directory Open Test 3 OK', stderr)
  280. # Basic Directory Creation
  281. self.assertIn('Directory Creation Test 1 OK', stderr)
  282. self.assertIn('Directory Creation Test 2 OK', stderr)
  283. self.assertIn('Directory Creation Test 3 OK', stderr)
  284. # Directory Reading
  285. for p in files:
  286. self.assertIn('Read Directory: {}'.format(p.name), stderr)
  287. # Directory Attribute Query
  288. self.assertIn('Query: type = ', stderr)
  289. # Directory Attribute Query by Handle
  290. self.assertIn('Query by Handle: type = ', stderr)
  291. # Directory Deletion
  292. self.assertFalse(pathlib.Path('dir_delete.tmp').exists())
  293. def test_200_event(self):
  294. stdout, stderr = self.run_binary(['Event'])
  295. self.assertIn('Wait with too short timeout ok.', stderr)
  296. self.assertIn('Wait with long enough timeout ok.', stderr)
  297. def test_210_semaphore(self):
  298. stdout, stderr = self.run_binary(['Semaphore'])
  299. # Semaphore: Timeout on Locked Semaphores
  300. self.assertIn('Locked binary semaphore timed out (1000).', stderr)
  301. self.assertIn('Locked binary semaphore timed out (0).', stderr)
  302. # Semaphore: Acquire Unlocked Semaphores
  303. self.assertIn('Locked binary semaphore successfully (-1).', stderr)
  304. self.assertIn('Locked binary semaphore successfully (0).', stderr)
  305. def test_300_memory(self):
  306. stdout, stderr = self.run_binary(['Memory'])
  307. # Memory Allocation
  308. self.assertIn('Memory Allocation OK', stderr)
  309. # Memory Allocation with Address
  310. self.assertIn('Memory Allocation with Address OK', stderr)
  311. # Get Memory Total Quota
  312. self.assertIn('Total Memory:', stderr)
  313. for line in stderr.split('\n'):
  314. if line.startswith('Total Memory:'):
  315. self.assertNotEqual(line, 'Total Memory: 0')
  316. # Get Memory Available Quota
  317. self.assertIn('Get Memory Available Quota OK', stderr)
  318. @expectedFailureIf(HAS_SGX)
  319. def test_301_memory_nosgx(self):
  320. stdout, stderr = self.run_binary(['Memory'])
  321. # SGX1 does not support unmapping a page or changing its permission
  322. # after enclave init. Therefore the memory protection and deallocation
  323. # tests will fail. By utilizing SGX2 it's possibile to fix this.
  324. # Memory Protection
  325. self.assertIn('Memory Allocation Protection (RW) OK', stderr)
  326. self.assertIn('Memory Protection (R) OK', stderr)
  327. # Memory Deallocation
  328. self.assertIn('Memory Deallocation OK', stderr)
  329. def test_400_pipe(self):
  330. stdout, stderr = self.run_binary(['Pipe'])
  331. # Pipe Creation
  332. self.assertIn('Pipe Creation 1 OK', stderr)
  333. # Pipe Attributes
  334. self.assertIn('Pipe Attribute Query 1 on pipesrv returned OK', stderr)
  335. # Pipe Connection
  336. self.assertIn('Pipe Connection 1 OK', stderr)
  337. # Pipe Transmission
  338. self.assertIn('Pipe Write 1 OK', stderr)
  339. self.assertIn('Pipe Read 1: Hello World 1', stderr)
  340. self.assertIn('Pipe Write 2 OK', stderr)
  341. self.assertIn('Pipe Read 2: Hello World 2', stderr)
  342. def test_410_socket(self):
  343. stdout, stderr = self.run_binary(['Socket'])
  344. # TCP Socket Creation
  345. self.assertIn('TCP Creation 1 OK', stderr)
  346. # TCP Socket Connection
  347. self.assertIn('TCP Connection 1 OK', stderr)
  348. # TCP Socket Transmission
  349. self.assertIn('TCP Write 1 OK', stderr)
  350. self.assertIn('TCP Read 1: Hello World 1', stderr)
  351. self.assertIn('TCP Write 2 OK', stderr)
  352. self.assertIn('TCP Read 2: Hello World 2', stderr)
  353. # UDP Socket Creation
  354. self.assertIn('UDP Creation 1 OK', stderr)
  355. # UDP Socket Connection
  356. self.assertIn('UDP Connection 1 OK', stderr)
  357. # UDP Socket Transmission
  358. self.assertIn('UDP Write 1 OK', stderr)
  359. self.assertIn('UDP Read 1: Hello World 1', stderr)
  360. self.assertIn('UDP Write 2 OK', stderr)
  361. self.assertIn('UDP Read 2: Hello World 2', stderr)
  362. # Bound UDP Socket Transmission
  363. self.assertIn('UDP Write 3 OK', stderr)
  364. self.assertIn('UDP Read 3: Hello World 1', stderr)
  365. self.assertIn('UDP Write 4 OK', stderr)
  366. self.assertIn('UDP Read 4: Hello World 2', stderr)
  367. def test_500_thread(self):
  368. stdout, stderr = self.run_binary(['Thread'])
  369. # Thread Creation
  370. self.assertIn('Child Thread Created', stderr)
  371. self.assertIn('Run in Child Thread: Hello World', stderr)
  372. # Multiple Threads Run in Parallel
  373. self.assertIn('Threads Run in Parallel OK', stderr)
  374. # Set Thread Private Segment Register
  375. self.assertIn('Private Message (FS Segment) 1: Hello World 1', stderr)
  376. self.assertIn('Private Message (FS Segment) 2: Hello World 2', stderr)
  377. # Thread Exit
  378. self.assertIn('Child Thread Exited', stderr)
  379. def test_510_thread2(self):
  380. stdout, stderr = self.run_binary(['Thread2'])
  381. # Thread Cleanup: Exit by return.
  382. self.assertIn('Thread 2 ok.', stderr)
  383. # Thread Cleanup: Exit by DkThreadExit.
  384. self.assertIn('Thread 3 ok.', stderr)
  385. self.assertNotIn('Exiting thread 3 failed.', stderr)
  386. # Thread Cleanup: Can still start threads.
  387. self.assertIn('Thread 4 ok.', stderr)
  388. def test_900_misc(self):
  389. stdout, stderr = self.run_binary(['Misc'])
  390. # Query System Time
  391. self.assertIn('Query System Time OK', stderr)
  392. # Delay Execution for 10000 Microseconds
  393. self.assertIn('Delay Execution for 10000 Microseconds OK', stderr)
  394. # Delay Execution for 3 Seconds
  395. self.assertIn('Delay Execution for 3 Seconds OK', stderr)
  396. # Generate Random Bits
  397. self.assertIn('Generate Random Bits OK', stderr)
  398. def test_910_hex(self):
  399. stdout, stderr = self.run_binary(['Hex'])
  400. # Hex 2 String Helper Function
  401. self.assertIn('Hex test 1 is deadbeef', stderr)
  402. self.assertIn('Hex test 2 is cdcdcdcdcdcdcdcd', stderr)
  403. class TC_21_ProcessCreation(RegressionTestCase):
  404. def test_100_process(self):
  405. stdout, stderr = self.run_binary(['Process'], timeout=8)
  406. counter = collections.Counter(stderr.split('\n'))
  407. # Process Creation
  408. self.assertEqual(counter['Child Process Created'], 3)
  409. # Process Creation Arguments
  410. self.assertEqual(counter['argv[0] = Process'], 3)
  411. self.assertEqual(counter['argv[1] = Child'], 3)
  412. # Process Channel Transmission
  413. self.assertEqual(counter['Process Write 1 OK'], 3)
  414. self.assertEqual(counter['Process Read 1: Hello World 1'], 3)
  415. self.assertEqual(counter['Process Write 2 OK'], 3)
  416. self.assertEqual(counter['Process Read 2: Hello World 2'], 3)
  417. def test_110_process_broadcast(self):
  418. stdout, stderr = self.run_binary(['Process'], timeout=8)
  419. counter = collections.Counter(stderr.split('\n'))
  420. # Multi-Process Broadcast Channel Transmission
  421. if ('Warning: broadcast stream is not open. '
  422. 'Do you have a multicast route configured?') in stderr:
  423. self.skipTest('Could not open broadcast stream. '
  424. 'Do you have a multicast route configured?')
  425. self.assertEqual(counter['Broadcast Write OK'], 1)
  426. self.assertEqual(counter['Broadcast Read: Hello World 1'], 3)
  427. def test_200_process2(self):
  428. # Process Creation with a Different Binary
  429. stdout, stderr = self.run_binary(['Process2'])
  430. counter = collections.Counter(stderr.split('\n'))
  431. self.assertEqual(counter['User Program Started'], 1)
  432. def test_300_process3(self):
  433. # Process Creation without Executable
  434. stdout, stderr = self.run_binary(['Process3'])
  435. counter = collections.Counter(stderr.split('\n'))
  436. self.assertEqual(counter['Binary 1 Preloaded'], 2)
  437. self.assertEqual(counter['Binary 2 Preloaded'], 2)
  438. @unittest.skipIf(HAS_SGX, 'GIPC not supported on SGX')
  439. ## XXX Should really be running these tests as part of CI
  440. @unittest.skipUnless(pathlib.Path('/dev/gipc').exists(), 'GIPC not loaded')
  441. class TC_22_GIPC(RegressionTestCase):
  442. def test_000_gipc(self):
  443. with open('ipc_mapping.tmp', 'w') as file:
  444. file.write('Hello World')
  445. os.ftruncate(file.fileno(), mmap.PAGESIZE)
  446. stdout, stderr = self.run_binary(['Ipc'])
  447. counter = collections.Counter(stderr.split('\n'))
  448. # Create and Join Physical Memory Bulk Copy Store
  449. self.assertEqual(counter['Create Physical Memory Store OK'], 5)
  450. self.assertEqual(counter['Join Physical Memory Store OK'], 5)
  451. # Map and Commit Anonymous Physical Memory
  452. self.assertIn('[Test 1] Physical Memory Commit OK', stderr)
  453. self.assertIn('[Test 1] Physical Memory Map : Hello World', stderr)
  454. # Transfer Anonymous Physical Memory as Copy-on-Write
  455. self.assertIn('[Test 1] Sender After Commit: Hello World, Alice', stderr)
  456. self.assertIn('[Test 1] Sender Before Map : Alice, Hello World', stderr)
  457. self.assertIn('[Test 1] Receiver After Map : Hello World, Bob', stderr)
  458. self.assertIn('[Test 1] Sender After Map : Alice, Hello World', stderr)
  459. # Map and Commit Untouched Physical Memory
  460. self.assertIn('[Test 2] Physical Memory Commit OK', stderr)
  461. self.assertIn('[Test 2] Physical Memory Map : ', stderr)
  462. self.assertIn('[Test 2] Sender After Commit: Hello World, Alice', stderr)
  463. self.assertIn('[Test 2] Sender Before Map : Alice, Hello World', stderr)
  464. self.assertIn('[Test 2] Receiver After Map : Hello World, Bob', stderr)
  465. self.assertIn('[Test 2] Sender After Map : Alice, Hello World', stderr)
  466. # Map and Commit File-Backed Physical Memory
  467. self.assertIn('[Test 3] Physical Memory Commit OK', stderr)
  468. self.assertIn('[Test 3] Physical Memory Map : Hello World', stderr)
  469. self.assertIn('[Test 3] Sender After Commit: Hello World', stderr)
  470. self.assertIn('[Test 3] Receiver After Map : Hello World, Bob', stderr)
  471. self.assertIn('[Test 3] Sender After Map : Hello World', stderr)
  472. # Map and Commit File-Backed Physical Memory Beyond File Size
  473. self.assertIn('[Test 4] Physical Memory Commit OK', stderr)
  474. self.assertIn('[Test 4] Physical Memory Map : Memory Fault', stderr)
  475. # Map and Commit Huge Physical Memory
  476. self.assertIn('[Test 5] Physical Memory Commit OK', stderr)
  477. self.assertIn('[Test 5] Physical Memory Map : Hello World', stderr)
  478. class TC_23_SendHandle(RegressionTestCase):
  479. def test_000_send_handle(self):
  480. stdout, stderr = self.run_binary(['SendHandle'])
  481. counter = collections.Counter(stderr.split('\n'))
  482. # Send and Receive Handles across Processes
  483. self.assertEqual(counter['Send Handle OK'], 3)
  484. self.assertEqual(counter['Receive Handle OK'], 3)
  485. # Send Pipe Handle
  486. self.assertEqual(counter['Receive Pipe Handle: Hello World'], 1)
  487. # Send Socket Handle
  488. self.assertEqual(counter['Receive Socket Handle: Hello World'], 1)
  489. # Send File Handle
  490. self.assertEqual(counter['Receive File Handle: Hello World'], 1)
  491. @unittest.skipUnless(HAS_SGX, 'need SGX')
  492. class TC_40_AVXDisable(RegressionTestCase):
  493. @unittest.expectedFailure
  494. def test_000_avx_disable(self):
  495. # Disable AVX bit in XFRM
  496. stdout, stderr = self.run_binary(['AvxDisable'])
  497. self.assertIn('Illegal instruction executed in enclave', stderr)
  498. @unittest.skipUnless(HAS_SGX, 'need SGX')
  499. class TC_50_Attestation(RegressionTestCase):
  500. def test_000_remote_attestation(self):
  501. stdout, stderr = self.run_binary(["Attestation"])
  502. for line in stderr.split("\n"):
  503. # Check the attestation status
  504. if line.startswith("Attestation status:"):
  505. status = line[19:].strip()
  506. self.assertIn(status, ["OK", "GROUP_OUT_OF_DATE"])
  507. # Check the timestamp
  508. if line.startswith("Attestation timestamp:"):
  509. timestamp = datetime.strptime(line[22:].strip(), "%Y-%m-%dT%H:%M:%S.%f")
  510. # The timestamp may be in another time zone, but should be
  511. # within 24 hours of the current time.
  512. self.assertTrue(datetime.now() - timedelta(hours=24) <= timestamp and \
  513. datetime.now() + timedelta(hours=24) >= timestamp);