@@ -378,7 +378,127 @@ TEST_F(enclave, unclobbered_vdso_oversubscribed)
378378 EXPECT_EQ (get_op .value , MAGIC );
379379 EXPECT_EEXIT (& self -> run );
380380 EXPECT_EQ (self -> run .user_data , 0 );
381+ }
382+
383+ TEST_F_TIMEOUT (enclave , unclobbered_vdso_oversubscribed_remove , 900 )
384+ {
385+ struct sgx_enclave_remove_pages remove_ioc ;
386+ struct sgx_enclave_modify_types modt_ioc ;
387+ struct encl_op_get_from_buf get_op ;
388+ struct encl_op_eaccept eaccept_op ;
389+ struct encl_op_put_to_buf put_op ;
390+ struct encl_segment * heap ;
391+ unsigned long total_mem ;
392+ int ret , errno_save ;
393+ unsigned long addr ;
394+ unsigned long i ;
395+
396+ /*
397+ * Create enclave with additional heap that is as big as all
398+ * available physical SGX memory.
399+ */
400+ total_mem = get_total_epc_mem ();
401+ ASSERT_NE (total_mem , 0 );
402+ TH_LOG ("Creating an enclave with %lu bytes heap may take a while ..." ,
403+ total_mem );
404+ ASSERT_TRUE (setup_test_encl (total_mem , & self -> encl , _metadata ));
405+
406+ /*
407+ * Hardware (SGX2) and kernel support is needed for this test. Start
408+ * with check that test has a chance of succeeding.
409+ */
410+ memset (& modt_ioc , 0 , sizeof (modt_ioc ));
411+ ret = ioctl (self -> encl .fd , SGX_IOC_ENCLAVE_MODIFY_TYPES , & modt_ioc );
412+
413+ if (ret == -1 ) {
414+ if (errno == ENOTTY )
415+ SKIP (return ,
416+ "Kernel does not support SGX_IOC_ENCLAVE_MODIFY_TYPES ioctl()" );
417+ else if (errno == ENODEV )
418+ SKIP (return , "System does not support SGX2" );
419+ }
420+
421+ /*
422+ * Invalid parameters were provided during sanity check,
423+ * expect command to fail.
424+ */
425+ EXPECT_EQ (ret , -1 );
426+
427+ /* SGX2 is supported by kernel and hardware, test can proceed. */
428+ memset (& self -> run , 0 , sizeof (self -> run ));
429+ self -> run .tcs = self -> encl .encl_base ;
430+
431+ heap = & self -> encl .segment_tbl [self -> encl .nr_segments - 1 ];
432+
433+ put_op .header .type = ENCL_OP_PUT_TO_BUFFER ;
434+ put_op .value = MAGIC ;
435+
436+ EXPECT_EQ (ENCL_CALL (& put_op , & self -> run , false), 0 );
437+
438+ EXPECT_EEXIT (& self -> run );
439+ EXPECT_EQ (self -> run .user_data , 0 );
440+
441+ get_op .header .type = ENCL_OP_GET_FROM_BUFFER ;
442+ get_op .value = 0 ;
443+
444+ EXPECT_EQ (ENCL_CALL (& get_op , & self -> run , false), 0 );
445+
446+ EXPECT_EQ (get_op .value , MAGIC );
447+ EXPECT_EEXIT (& self -> run );
448+ EXPECT_EQ (self -> run .user_data , 0 );
381449
450+ /* Trim entire heap. */
451+ memset (& modt_ioc , 0 , sizeof (modt_ioc ));
452+
453+ modt_ioc .offset = heap -> offset ;
454+ modt_ioc .length = heap -> size ;
455+ modt_ioc .page_type = SGX_PAGE_TYPE_TRIM ;
456+
457+ TH_LOG ("Changing type of %zd bytes to trimmed may take a while ..." ,
458+ heap -> size );
459+ ret = ioctl (self -> encl .fd , SGX_IOC_ENCLAVE_MODIFY_TYPES , & modt_ioc );
460+ errno_save = ret == -1 ? errno : 0 ;
461+
462+ EXPECT_EQ (ret , 0 );
463+ EXPECT_EQ (errno_save , 0 );
464+ EXPECT_EQ (modt_ioc .result , 0 );
465+ EXPECT_EQ (modt_ioc .count , heap -> size );
466+
467+ /* EACCEPT all removed pages. */
468+ addr = self -> encl .encl_base + heap -> offset ;
469+
470+ eaccept_op .flags = SGX_SECINFO_TRIM | SGX_SECINFO_MODIFIED ;
471+ eaccept_op .header .type = ENCL_OP_EACCEPT ;
472+
473+ TH_LOG ("Entering enclave to run EACCEPT for each page of %zd bytes may take a while ..." ,
474+ heap -> size );
475+ for (i = 0 ; i < heap -> size ; i += 4096 ) {
476+ eaccept_op .epc_addr = addr + i ;
477+ eaccept_op .ret = 0 ;
478+
479+ EXPECT_EQ (ENCL_CALL (& eaccept_op , & self -> run , true), 0 );
480+
481+ EXPECT_EQ (self -> run .exception_vector , 0 );
482+ EXPECT_EQ (self -> run .exception_error_code , 0 );
483+ EXPECT_EQ (self -> run .exception_addr , 0 );
484+ ASSERT_EQ (eaccept_op .ret , 0 );
485+ ASSERT_EQ (self -> run .function , EEXIT );
486+ }
487+
488+ /* Complete page removal. */
489+ memset (& remove_ioc , 0 , sizeof (remove_ioc ));
490+
491+ remove_ioc .offset = heap -> offset ;
492+ remove_ioc .length = heap -> size ;
493+
494+ TH_LOG ("Removing %zd bytes from enclave may take a while ..." ,
495+ heap -> size );
496+ ret = ioctl (self -> encl .fd , SGX_IOC_ENCLAVE_REMOVE_PAGES , & remove_ioc );
497+ errno_save = ret == -1 ? errno : 0 ;
498+
499+ EXPECT_EQ (ret , 0 );
500+ EXPECT_EQ (errno_save , 0 );
501+ EXPECT_EQ (remove_ioc .count , heap -> size );
382502}
383503
384504TEST_F (enclave , clobbered_vdso )
0 commit comments