107107 #endif
108108#endif
109109
110+ #ifndef __NR_open_tree_attr
111+ #if defined __alpha__
112+ #define __NR_open_tree_attr 577
113+ #elif defined _MIPS_SIM
114+ #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */
115+ #define __NR_open_tree_attr (467 + 4000)
116+ #endif
117+ #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */
118+ #define __NR_open_tree_attr (467 + 6000)
119+ #endif
120+ #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */
121+ #define __NR_open_tree_attr (467 + 5000)
122+ #endif
123+ #elif defined __ia64__
124+ #define __NR_open_tree_attr (467 + 1024)
125+ #else
126+ #define __NR_open_tree_attr 467
127+ #endif
128+ #endif
129+
110130#ifndef MOUNT_ATTR_IDMAP
111131#define MOUNT_ATTR_IDMAP 0x00100000
112132#endif
@@ -121,6 +141,12 @@ static inline int sys_mount_setattr(int dfd, const char *path, unsigned int flag
121141 return syscall (__NR_mount_setattr , dfd , path , flags , attr , size );
122142}
123143
144+ static inline int sys_open_tree_attr (int dfd , const char * path , unsigned int flags ,
145+ struct mount_attr * attr , size_t size )
146+ {
147+ return syscall (__NR_open_tree_attr , dfd , path , flags , attr , size );
148+ }
149+
124150static ssize_t write_nointr (int fd , const void * buf , size_t count )
125151{
126152 ssize_t ret ;
@@ -1222,6 +1248,12 @@ TEST_F(mount_setattr_idmapped, attached_mount_inside_current_mount_namespace)
12221248 attr .userns_fd = get_userns_fd (0 , 10000 , 10000 );
12231249 ASSERT_GE (attr .userns_fd , 0 );
12241250 ASSERT_NE (sys_mount_setattr (open_tree_fd , "" , AT_EMPTY_PATH , & attr , sizeof (attr )), 0 );
1251+ /*
1252+ * Make sure that open_tree_attr() without OPEN_TREE_CLONE is not a way
1253+ * to bypass this mount_setattr() restriction.
1254+ */
1255+ ASSERT_LT (sys_open_tree_attr (open_tree_fd , "" , AT_EMPTY_PATH , & attr , sizeof (attr )), 0 );
1256+
12251257 ASSERT_EQ (close (attr .userns_fd ), 0 );
12261258 ASSERT_EQ (close (open_tree_fd ), 0 );
12271259}
@@ -1255,6 +1287,12 @@ TEST_F(mount_setattr_idmapped, attached_mount_outside_current_mount_namespace)
12551287 ASSERT_GE (attr .userns_fd , 0 );
12561288 ASSERT_NE (sys_mount_setattr (open_tree_fd , "" , AT_EMPTY_PATH , & attr ,
12571289 sizeof (attr )), 0 );
1290+ /*
1291+ * Make sure that open_tree_attr() without OPEN_TREE_CLONE is not a way
1292+ * to bypass this mount_setattr() restriction.
1293+ */
1294+ ASSERT_LT (sys_open_tree_attr (open_tree_fd , "" , AT_EMPTY_PATH , & attr , sizeof (attr )), 0 );
1295+
12581296 ASSERT_EQ (close (attr .userns_fd ), 0 );
12591297 ASSERT_EQ (close (open_tree_fd ), 0 );
12601298}
@@ -1321,6 +1359,19 @@ TEST_F(mount_setattr_idmapped, detached_mount_outside_current_mount_namespace)
13211359 ASSERT_EQ (close (open_tree_fd ), 0 );
13221360}
13231361
1362+ static bool expected_uid_gid (int dfd , const char * path , int flags ,
1363+ uid_t expected_uid , gid_t expected_gid )
1364+ {
1365+ int ret ;
1366+ struct stat st ;
1367+
1368+ ret = fstatat (dfd , path , & st , flags );
1369+ if (ret < 0 )
1370+ return false;
1371+
1372+ return st .st_uid == expected_uid && st .st_gid == expected_gid ;
1373+ }
1374+
13241375/**
13251376 * Validate that currently changing the idmapping of an idmapped mount fails.
13261377 */
@@ -1331,6 +1382,8 @@ TEST_F(mount_setattr_idmapped, change_idmapping)
13311382 .attr_set = MOUNT_ATTR_IDMAP ,
13321383 };
13331384
1385+ ASSERT_TRUE (expected_uid_gid (- EBADF , "/mnt/D" , 0 , 0 , 0 ));
1386+
13341387 if (!mount_setattr_supported ())
13351388 SKIP (return , "mount_setattr syscall not supported" );
13361389
@@ -1348,27 +1401,25 @@ TEST_F(mount_setattr_idmapped, change_idmapping)
13481401 AT_EMPTY_PATH , & attr , sizeof (attr )), 0 );
13491402 ASSERT_EQ (close (attr .userns_fd ), 0 );
13501403
1404+ EXPECT_FALSE (expected_uid_gid (open_tree_fd , "." , 0 , 0 , 0 ));
1405+ EXPECT_TRUE (expected_uid_gid (open_tree_fd , "." , 0 , 10000 , 10000 ));
1406+
13511407 /* Change idmapping on a detached mount that is already idmapped. */
13521408 attr .userns_fd = get_userns_fd (0 , 20000 , 10000 );
13531409 ASSERT_GE (attr .userns_fd , 0 );
13541410 ASSERT_NE (sys_mount_setattr (open_tree_fd , "" , AT_EMPTY_PATH , & attr , sizeof (attr )), 0 );
1411+ /*
1412+ * Make sure that open_tree_attr() without OPEN_TREE_CLONE is not a way
1413+ * to bypass this mount_setattr() restriction.
1414+ */
1415+ EXPECT_LT (sys_open_tree_attr (open_tree_fd , "" , AT_EMPTY_PATH , & attr , sizeof (attr )), 0 );
1416+ EXPECT_FALSE (expected_uid_gid (open_tree_fd , "." , 0 , 20000 , 20000 ));
1417+ EXPECT_TRUE (expected_uid_gid (open_tree_fd , "." , 0 , 10000 , 10000 ));
1418+
13551419 ASSERT_EQ (close (attr .userns_fd ), 0 );
13561420 ASSERT_EQ (close (open_tree_fd ), 0 );
13571421}
13581422
1359- static bool expected_uid_gid (int dfd , const char * path , int flags ,
1360- uid_t expected_uid , gid_t expected_gid )
1361- {
1362- int ret ;
1363- struct stat st ;
1364-
1365- ret = fstatat (dfd , path , & st , flags );
1366- if (ret < 0 )
1367- return false;
1368-
1369- return st .st_uid == expected_uid && st .st_gid == expected_gid ;
1370- }
1371-
13721423TEST_F (mount_setattr_idmapped , idmap_mount_tree_invalid )
13731424{
13741425 int open_tree_fd = - EBADF ;
0 commit comments