@@ -1547,4 +1547,247 @@ TEST_F(enclave, remove_added_page_no_eaccept)
15471547 EXPECT_EQ (remove_ioc .count , 0 );
15481548}
15491549
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+
15501793TEST_HARNESS_MAIN
0 commit comments