@@ -1547,4 +1547,247 @@ TEST_F(enclave, remove_added_page_no_eaccept)
1547
1547
EXPECT_EQ (remove_ioc .count , 0 );
1548
1548
}
1549
1549
1550
+ /*
1551
+ * Request enclave page removal but instead of correctly following with
1552
+ * EACCEPT a read attempt to page is made from within the enclave.
1553
+ */
1554
+ TEST_F (enclave , remove_added_page_invalid_access )
1555
+ {
1556
+ struct encl_op_get_from_addr get_addr_op ;
1557
+ struct encl_op_put_to_addr put_addr_op ;
1558
+ struct sgx_enclave_modify_types ioc ;
1559
+ unsigned long data_start ;
1560
+ int ret , errno_save ;
1561
+
1562
+ ASSERT_TRUE (setup_test_encl (ENCL_HEAP_SIZE_DEFAULT , & self -> encl , _metadata ));
1563
+
1564
+ memset (& self -> run , 0 , sizeof (self -> run ));
1565
+ self -> run .tcs = self -> encl .encl_base ;
1566
+
1567
+ /*
1568
+ * Hardware (SGX2) and kernel support is needed for this test. Start
1569
+ * with check that test has a chance of succeeding.
1570
+ */
1571
+ memset (& ioc , 0 , sizeof (ioc ));
1572
+ ret = ioctl (self -> encl .fd , SGX_IOC_ENCLAVE_MODIFY_TYPES , & ioc );
1573
+
1574
+ if (ret == -1 ) {
1575
+ if (errno == ENOTTY )
1576
+ SKIP (return ,
1577
+ "Kernel does not support SGX_IOC_ENCLAVE_MODIFY_TYPES ioctl()" );
1578
+ else if (errno == ENODEV )
1579
+ SKIP (return , "System does not support SGX2" );
1580
+ }
1581
+
1582
+ /*
1583
+ * Invalid parameters were provided during sanity check,
1584
+ * expect command to fail.
1585
+ */
1586
+ EXPECT_EQ (ret , -1 );
1587
+
1588
+ /*
1589
+ * Page that will be removed is the second data page in the .data
1590
+ * segment. This forms part of the local encl_buffer within the
1591
+ * enclave.
1592
+ */
1593
+ data_start = self -> encl .encl_base +
1594
+ encl_get_data_offset (& self -> encl ) + PAGE_SIZE ;
1595
+
1596
+ /*
1597
+ * Sanity check that page at @data_start is writable before
1598
+ * removing it.
1599
+ *
1600
+ * Start by writing MAGIC to test page.
1601
+ */
1602
+ put_addr_op .value = MAGIC ;
1603
+ put_addr_op .addr = data_start ;
1604
+ put_addr_op .header .type = ENCL_OP_PUT_TO_ADDRESS ;
1605
+
1606
+ EXPECT_EQ (ENCL_CALL (& put_addr_op , & self -> run , true), 0 );
1607
+
1608
+ EXPECT_EEXIT (& self -> run );
1609
+ EXPECT_EQ (self -> run .exception_vector , 0 );
1610
+ EXPECT_EQ (self -> run .exception_error_code , 0 );
1611
+ EXPECT_EQ (self -> run .exception_addr , 0 );
1612
+
1613
+ /*
1614
+ * Read memory that was just written to, confirming that data
1615
+ * previously written (MAGIC) is present.
1616
+ */
1617
+ get_addr_op .value = 0 ;
1618
+ get_addr_op .addr = data_start ;
1619
+ get_addr_op .header .type = ENCL_OP_GET_FROM_ADDRESS ;
1620
+
1621
+ EXPECT_EQ (ENCL_CALL (& get_addr_op , & self -> run , true), 0 );
1622
+
1623
+ EXPECT_EQ (get_addr_op .value , MAGIC );
1624
+ EXPECT_EEXIT (& self -> run );
1625
+ EXPECT_EQ (self -> run .exception_vector , 0 );
1626
+ EXPECT_EQ (self -> run .exception_error_code , 0 );
1627
+ EXPECT_EQ (self -> run .exception_addr , 0 );
1628
+
1629
+ /* Start page removal by requesting change of page type to PT_TRIM. */
1630
+ memset (& ioc , 0 , sizeof (ioc ));
1631
+
1632
+ ioc .offset = encl_get_data_offset (& self -> encl ) + PAGE_SIZE ;
1633
+ ioc .length = PAGE_SIZE ;
1634
+ ioc .page_type = SGX_PAGE_TYPE_TRIM ;
1635
+
1636
+ ret = ioctl (self -> encl .fd , SGX_IOC_ENCLAVE_MODIFY_TYPES , & ioc );
1637
+ errno_save = ret == -1 ? errno : 0 ;
1638
+
1639
+ EXPECT_EQ (ret , 0 );
1640
+ EXPECT_EQ (errno_save , 0 );
1641
+ EXPECT_EQ (ioc .result , 0 );
1642
+ EXPECT_EQ (ioc .count , 4096 );
1643
+
1644
+ /*
1645
+ * Read from page that was just removed.
1646
+ */
1647
+ get_addr_op .value = 0 ;
1648
+
1649
+ EXPECT_EQ (ENCL_CALL (& get_addr_op , & self -> run , true), 0 );
1650
+
1651
+ /*
1652
+ * From kernel perspective the page is present but according to SGX the
1653
+ * page should not be accessible so a #PF with SGX bit set is
1654
+ * expected.
1655
+ */
1656
+
1657
+ EXPECT_EQ (self -> run .function , ERESUME );
1658
+ EXPECT_EQ (self -> run .exception_vector , 14 );
1659
+ EXPECT_EQ (self -> run .exception_error_code , 0x8005 );
1660
+ EXPECT_EQ (self -> run .exception_addr , data_start );
1661
+ }
1662
+
1663
+ /*
1664
+ * Request enclave page removal and correctly follow with
1665
+ * EACCEPT but do not follow with removal ioctl() but instead a read attempt
1666
+ * to removed page is made from within the enclave.
1667
+ */
1668
+ TEST_F (enclave , remove_added_page_invalid_access_after_eaccept )
1669
+ {
1670
+ struct encl_op_get_from_addr get_addr_op ;
1671
+ struct encl_op_put_to_addr put_addr_op ;
1672
+ struct sgx_enclave_modify_types ioc ;
1673
+ struct encl_op_eaccept eaccept_op ;
1674
+ unsigned long data_start ;
1675
+ int ret , errno_save ;
1676
+
1677
+ ASSERT_TRUE (setup_test_encl (ENCL_HEAP_SIZE_DEFAULT , & self -> encl , _metadata ));
1678
+
1679
+ memset (& self -> run , 0 , sizeof (self -> run ));
1680
+ self -> run .tcs = self -> encl .encl_base ;
1681
+
1682
+ /*
1683
+ * Hardware (SGX2) and kernel support is needed for this test. Start
1684
+ * with check that test has a chance of succeeding.
1685
+ */
1686
+ memset (& ioc , 0 , sizeof (ioc ));
1687
+ ret = ioctl (self -> encl .fd , SGX_IOC_ENCLAVE_MODIFY_TYPES , & ioc );
1688
+
1689
+ if (ret == -1 ) {
1690
+ if (errno == ENOTTY )
1691
+ SKIP (return ,
1692
+ "Kernel does not support SGX_IOC_ENCLAVE_MODIFY_TYPES ioctl()" );
1693
+ else if (errno == ENODEV )
1694
+ SKIP (return , "System does not support SGX2" );
1695
+ }
1696
+
1697
+ /*
1698
+ * Invalid parameters were provided during sanity check,
1699
+ * expect command to fail.
1700
+ */
1701
+ EXPECT_EQ (ret , -1 );
1702
+
1703
+ /*
1704
+ * Page that will be removed is the second data page in the .data
1705
+ * segment. This forms part of the local encl_buffer within the
1706
+ * enclave.
1707
+ */
1708
+ data_start = self -> encl .encl_base +
1709
+ encl_get_data_offset (& self -> encl ) + PAGE_SIZE ;
1710
+
1711
+ /*
1712
+ * Sanity check that page at @data_start is writable before
1713
+ * removing it.
1714
+ *
1715
+ * Start by writing MAGIC to test page.
1716
+ */
1717
+ put_addr_op .value = MAGIC ;
1718
+ put_addr_op .addr = data_start ;
1719
+ put_addr_op .header .type = ENCL_OP_PUT_TO_ADDRESS ;
1720
+
1721
+ EXPECT_EQ (ENCL_CALL (& put_addr_op , & self -> run , true), 0 );
1722
+
1723
+ EXPECT_EEXIT (& self -> run );
1724
+ EXPECT_EQ (self -> run .exception_vector , 0 );
1725
+ EXPECT_EQ (self -> run .exception_error_code , 0 );
1726
+ EXPECT_EQ (self -> run .exception_addr , 0 );
1727
+
1728
+ /*
1729
+ * Read memory that was just written to, confirming that data
1730
+ * previously written (MAGIC) is present.
1731
+ */
1732
+ get_addr_op .value = 0 ;
1733
+ get_addr_op .addr = data_start ;
1734
+ get_addr_op .header .type = ENCL_OP_GET_FROM_ADDRESS ;
1735
+
1736
+ EXPECT_EQ (ENCL_CALL (& get_addr_op , & self -> run , true), 0 );
1737
+
1738
+ EXPECT_EQ (get_addr_op .value , MAGIC );
1739
+ EXPECT_EEXIT (& self -> run );
1740
+ EXPECT_EQ (self -> run .exception_vector , 0 );
1741
+ EXPECT_EQ (self -> run .exception_error_code , 0 );
1742
+ EXPECT_EQ (self -> run .exception_addr , 0 );
1743
+
1744
+ /* Start page removal by requesting change of page type to PT_TRIM. */
1745
+ memset (& ioc , 0 , sizeof (ioc ));
1746
+
1747
+ ioc .offset = encl_get_data_offset (& self -> encl ) + PAGE_SIZE ;
1748
+ ioc .length = PAGE_SIZE ;
1749
+ ioc .page_type = SGX_PAGE_TYPE_TRIM ;
1750
+
1751
+ ret = ioctl (self -> encl .fd , SGX_IOC_ENCLAVE_MODIFY_TYPES , & ioc );
1752
+ errno_save = ret == -1 ? errno : 0 ;
1753
+
1754
+ EXPECT_EQ (ret , 0 );
1755
+ EXPECT_EQ (errno_save , 0 );
1756
+ EXPECT_EQ (ioc .result , 0 );
1757
+ EXPECT_EQ (ioc .count , 4096 );
1758
+
1759
+ eaccept_op .epc_addr = (unsigned long )data_start ;
1760
+ eaccept_op .ret = 0 ;
1761
+ eaccept_op .flags = SGX_SECINFO_TRIM | SGX_SECINFO_MODIFIED ;
1762
+ eaccept_op .header .type = ENCL_OP_EACCEPT ;
1763
+
1764
+ EXPECT_EQ (ENCL_CALL (& eaccept_op , & self -> run , true), 0 );
1765
+
1766
+ EXPECT_EEXIT (& self -> run );
1767
+ EXPECT_EQ (self -> run .exception_vector , 0 );
1768
+ EXPECT_EQ (self -> run .exception_error_code , 0 );
1769
+ EXPECT_EQ (self -> run .exception_addr , 0 );
1770
+ EXPECT_EQ (eaccept_op .ret , 0 );
1771
+
1772
+ /* Skip ioctl() to remove page. */
1773
+
1774
+ /*
1775
+ * Read from page that was just removed.
1776
+ */
1777
+ get_addr_op .value = 0 ;
1778
+
1779
+ EXPECT_EQ (ENCL_CALL (& get_addr_op , & self -> run , true), 0 );
1780
+
1781
+ /*
1782
+ * From kernel perspective the page is present but according to SGX the
1783
+ * page should not be accessible so a #PF with SGX bit set is
1784
+ * expected.
1785
+ */
1786
+
1787
+ EXPECT_EQ (self -> run .function , ERESUME );
1788
+ EXPECT_EQ (self -> run .exception_vector , 14 );
1789
+ EXPECT_EQ (self -> run .exception_error_code , 0x8005 );
1790
+ EXPECT_EQ (self -> run .exception_addr , data_start );
1791
+ }
1792
+
1550
1793
TEST_HARNESS_MAIN
0 commit comments