4
4
*
5
5
* Copyright © 2017-2020 Mickaël Salaün <[email protected] >
6
6
* Copyright © 2020 ANSSI
7
- * Copyright © 2020-2021 Microsoft Corporation
7
+ * Copyright © 2020-2022 Microsoft Corporation
8
8
*/
9
9
10
10
#define _GNU_SOURCE
@@ -371,6 +371,13 @@ TEST_F_FORK(layout1, inval)
371
371
ASSERT_EQ (EINVAL , errno );
372
372
path_beneath .allowed_access &= ~LANDLOCK_ACCESS_FS_EXECUTE ;
373
373
374
+ /* Tests with denied-by-default access right. */
375
+ path_beneath .allowed_access |= LANDLOCK_ACCESS_FS_REFER ;
376
+ ASSERT_EQ (-1 , landlock_add_rule (ruleset_fd , LANDLOCK_RULE_PATH_BENEATH ,
377
+ & path_beneath , 0 ));
378
+ ASSERT_EQ (EINVAL , errno );
379
+ path_beneath .allowed_access &= ~LANDLOCK_ACCESS_FS_REFER ;
380
+
374
381
/* Test with unknown (64-bits) value. */
375
382
path_beneath .allowed_access |= (1ULL << 60 );
376
383
ASSERT_EQ (-1 , landlock_add_rule (ruleset_fd , LANDLOCK_RULE_PATH_BENEATH ,
@@ -1826,6 +1833,20 @@ TEST_F_FORK(layout1, link)
1826
1833
ASSERT_EQ (0 , link (file1_s1d3 , file2_s1d3 ));
1827
1834
}
1828
1835
1836
+ static int test_rename (const char * const oldpath , const char * const newpath )
1837
+ {
1838
+ if (rename (oldpath , newpath ))
1839
+ return errno ;
1840
+ return 0 ;
1841
+ }
1842
+
1843
+ static int test_exchange (const char * const oldpath , const char * const newpath )
1844
+ {
1845
+ if (renameat2 (AT_FDCWD , oldpath , AT_FDCWD , newpath , RENAME_EXCHANGE ))
1846
+ return errno ;
1847
+ return 0 ;
1848
+ }
1849
+
1829
1850
TEST_F_FORK (layout1 , rename_file )
1830
1851
{
1831
1852
const struct rule rules [] = {
@@ -1867,10 +1888,10 @@ TEST_F_FORK(layout1, rename_file)
1867
1888
* to a different directory (which allows file removal).
1868
1889
*/
1869
1890
ASSERT_EQ (-1 , rename (file1_s2d1 , file1_s1d3 ));
1870
- ASSERT_EQ (EXDEV , errno );
1891
+ ASSERT_EQ (EACCES , errno );
1871
1892
ASSERT_EQ (-1 , renameat2 (AT_FDCWD , file1_s2d1 , AT_FDCWD , file1_s1d3 ,
1872
1893
RENAME_EXCHANGE ));
1873
- ASSERT_EQ (EXDEV , errno );
1894
+ ASSERT_EQ (EACCES , errno );
1874
1895
ASSERT_EQ (-1 , renameat2 (AT_FDCWD , dir_s2d2 , AT_FDCWD , file1_s1d3 ,
1875
1896
RENAME_EXCHANGE ));
1876
1897
ASSERT_EQ (EXDEV , errno );
@@ -1894,7 +1915,7 @@ TEST_F_FORK(layout1, rename_file)
1894
1915
ASSERT_EQ (EXDEV , errno );
1895
1916
ASSERT_EQ (0 , unlink (file1_s1d3 ));
1896
1917
ASSERT_EQ (-1 , rename (file1_s2d1 , file1_s1d3 ));
1897
- ASSERT_EQ (EXDEV , errno );
1918
+ ASSERT_EQ (EACCES , errno );
1898
1919
1899
1920
/* Exchanges and renames files with same parent. */
1900
1921
ASSERT_EQ (0 , renameat2 (AT_FDCWD , file2_s2d3 , AT_FDCWD , file1_s2d3 ,
@@ -2014,6 +2035,115 @@ TEST_F_FORK(layout1, reparent_refer)
2014
2035
ASSERT_EQ (0 , rename (dir_s1d3 , dir_s2d3 ));
2015
2036
}
2016
2037
2038
+ /* Checks renames beneath dir_s1d1. */
2039
+ static void refer_denied_by_default (struct __test_metadata * const _metadata ,
2040
+ const struct rule layer1 [],
2041
+ const int layer1_err ,
2042
+ const struct rule layer2 [])
2043
+ {
2044
+ int ruleset_fd ;
2045
+
2046
+ ASSERT_EQ (0 , unlink (file1_s1d2 ));
2047
+
2048
+ ruleset_fd = create_ruleset (_metadata , layer1 [0 ].access , layer1 );
2049
+ ASSERT_LE (0 , ruleset_fd );
2050
+ enforce_ruleset (_metadata , ruleset_fd );
2051
+ ASSERT_EQ (0 , close (ruleset_fd ));
2052
+
2053
+ /*
2054
+ * If the first layer handles LANDLOCK_ACCESS_FS_REFER (according to
2055
+ * layer1_err), then it allows some different-parent renames and links.
2056
+ */
2057
+ ASSERT_EQ (layer1_err , test_rename (file1_s1d1 , file1_s1d2 ));
2058
+ if (layer1_err == 0 )
2059
+ ASSERT_EQ (layer1_err , test_rename (file1_s1d2 , file1_s1d1 ));
2060
+ ASSERT_EQ (layer1_err , test_exchange (file2_s1d1 , file2_s1d2 ));
2061
+ ASSERT_EQ (layer1_err , test_exchange (file2_s1d2 , file2_s1d1 ));
2062
+
2063
+ ruleset_fd = create_ruleset (_metadata , layer2 [0 ].access , layer2 );
2064
+ ASSERT_LE (0 , ruleset_fd );
2065
+ enforce_ruleset (_metadata , ruleset_fd );
2066
+ ASSERT_EQ (0 , close (ruleset_fd ));
2067
+
2068
+ /*
2069
+ * Now, either the first or the second layer does not handle
2070
+ * LANDLOCK_ACCESS_FS_REFER, which means that any different-parent
2071
+ * renames and links are denied, thus making the layer handling
2072
+ * LANDLOCK_ACCESS_FS_REFER null and void.
2073
+ */
2074
+ ASSERT_EQ (EXDEV , test_rename (file1_s1d1 , file1_s1d2 ));
2075
+ ASSERT_EQ (EXDEV , test_exchange (file2_s1d1 , file2_s1d2 ));
2076
+ ASSERT_EQ (EXDEV , test_exchange (file2_s1d2 , file2_s1d1 ));
2077
+ }
2078
+
2079
+ const struct rule layer_dir_s1d1_refer [] = {
2080
+ {
2081
+ .path = dir_s1d1 ,
2082
+ .access = LANDLOCK_ACCESS_FS_REFER ,
2083
+ },
2084
+ {},
2085
+ };
2086
+
2087
+ const struct rule layer_dir_s1d1_execute [] = {
2088
+ {
2089
+ /* Matches a parent directory. */
2090
+ .path = dir_s1d1 ,
2091
+ .access = LANDLOCK_ACCESS_FS_EXECUTE ,
2092
+ },
2093
+ {},
2094
+ };
2095
+
2096
+ const struct rule layer_dir_s2d1_execute [] = {
2097
+ {
2098
+ /* Does not match a parent directory. */
2099
+ .path = dir_s2d1 ,
2100
+ .access = LANDLOCK_ACCESS_FS_EXECUTE ,
2101
+ },
2102
+ {},
2103
+ };
2104
+
2105
+ /*
2106
+ * Tests precedence over renames: denied by default for different parent
2107
+ * directories, *with* a rule matching a parent directory, but not directly
2108
+ * denying access (with MAKE_REG nor REMOVE).
2109
+ */
2110
+ TEST_F_FORK (layout1 , refer_denied_by_default1 )
2111
+ {
2112
+ refer_denied_by_default (_metadata , layer_dir_s1d1_refer , 0 ,
2113
+ layer_dir_s1d1_execute );
2114
+ }
2115
+
2116
+ /*
2117
+ * Same test but this time turning around the ABI version order: the first
2118
+ * layer does not handle LANDLOCK_ACCESS_FS_REFER.
2119
+ */
2120
+ TEST_F_FORK (layout1 , refer_denied_by_default2 )
2121
+ {
2122
+ refer_denied_by_default (_metadata , layer_dir_s1d1_execute , EXDEV ,
2123
+ layer_dir_s1d1_refer );
2124
+ }
2125
+
2126
+ /*
2127
+ * Tests precedence over renames: denied by default for different parent
2128
+ * directories, *without* a rule matching a parent directory, but not directly
2129
+ * denying access (with MAKE_REG nor REMOVE).
2130
+ */
2131
+ TEST_F_FORK (layout1 , refer_denied_by_default3 )
2132
+ {
2133
+ refer_denied_by_default (_metadata , layer_dir_s1d1_refer , 0 ,
2134
+ layer_dir_s2d1_execute );
2135
+ }
2136
+
2137
+ /*
2138
+ * Same test but this time turning around the ABI version order: the first
2139
+ * layer does not handle LANDLOCK_ACCESS_FS_REFER.
2140
+ */
2141
+ TEST_F_FORK (layout1 , refer_denied_by_default4 )
2142
+ {
2143
+ refer_denied_by_default (_metadata , layer_dir_s2d1_execute , EXDEV ,
2144
+ layer_dir_s1d1_refer );
2145
+ }
2146
+
2017
2147
TEST_F_FORK (layout1 , reparent_link )
2018
2148
{
2019
2149
const struct rule layer1 [] = {
@@ -2336,11 +2466,12 @@ TEST_F_FORK(layout1, reparent_exdev_layers_rename1)
2336
2466
ASSERT_EQ (EXDEV , errno );
2337
2467
2338
2468
/*
2339
- * However, moving the file2_s1d3 file below dir_s2d3 is allowed
2340
- * because it cannot inherit MAKE_REG nor MAKE_DIR rights (which are
2341
- * dedicated to directories) .
2469
+ * Moving the file2_s1d3 file below dir_s2d3 is denied because the
2470
+ * second layer does not handle REFER, which is always denied by
2471
+ * default .
2342
2472
*/
2343
- ASSERT_EQ (0 , rename (file2_s1d3 , file1_s2d3 ));
2473
+ ASSERT_EQ (-1 , rename (file2_s1d3 , file1_s2d3 ));
2474
+ ASSERT_EQ (EXDEV , errno );
2344
2475
}
2345
2476
2346
2477
TEST_F_FORK (layout1 , reparent_exdev_layers_rename2 )
@@ -2373,8 +2504,12 @@ TEST_F_FORK(layout1, reparent_exdev_layers_rename2)
2373
2504
ASSERT_EQ (EACCES , errno );
2374
2505
ASSERT_EQ (-1 , rename (file1_s1d1 , file1_s2d3 ));
2375
2506
ASSERT_EQ (EXDEV , errno );
2376
- /* Modify layout! */
2377
- ASSERT_EQ (0 , rename (file2_s1d2 , file1_s2d3 ));
2507
+ /*
2508
+ * Modifying the layout is now denied because the second layer does not
2509
+ * handle REFER, which is always denied by default.
2510
+ */
2511
+ ASSERT_EQ (-1 , rename (file2_s1d2 , file1_s2d3 ));
2512
+ ASSERT_EQ (EXDEV , errno );
2378
2513
2379
2514
/* Without REFER source, EACCES wins over EXDEV. */
2380
2515
ASSERT_EQ (-1 , rename (dir_s1d1 , file1_s2d2 ));
0 commit comments