@@ -5122,7 +5122,7 @@ static int copy_mnt_id_req(const struct mnt_id_req __user *req,
51225122 int ret ;
51235123 size_t usize ;
51245124
5125- BUILD_BUG_ON (sizeof (struct mnt_id_req ) != MNT_ID_REQ_SIZE_VER0 );
5125+ BUILD_BUG_ON (sizeof (struct mnt_id_req ) != MNT_ID_REQ_SIZE_VER1 );
51265126
51275127 ret = get_user (usize , & req -> size );
51285128 if (ret )
@@ -5140,6 +5140,58 @@ static int copy_mnt_id_req(const struct mnt_id_req __user *req,
51405140 return 0 ;
51415141}
51425142
5143+ static struct mount * listmnt_next (struct mount * curr , bool reverse )
5144+ {
5145+ struct rb_node * node ;
5146+
5147+ if (reverse )
5148+ node = rb_prev (& curr -> mnt_node );
5149+ else
5150+ node = rb_next (& curr -> mnt_node );
5151+
5152+ return node_to_mount (node );
5153+ }
5154+
5155+ static int grab_requested_root (struct mnt_namespace * ns , struct path * root )
5156+ {
5157+ struct mount * first ;
5158+
5159+ rwsem_assert_held (& namespace_sem );
5160+
5161+ /* We're looking at our own ns, just use get_fs_root. */
5162+ if (ns == current -> nsproxy -> mnt_ns ) {
5163+ get_fs_root (current -> fs , root );
5164+ return 0 ;
5165+ }
5166+
5167+ /*
5168+ * We have to find the first mount in our ns and use that, however it
5169+ * may not exist, so handle that properly.
5170+ */
5171+ if (RB_EMPTY_ROOT (& ns -> mounts ))
5172+ return - ENOENT ;
5173+
5174+ first = listmnt_next (ns -> root , false);
5175+ if (!first )
5176+ return - ENOENT ;
5177+ root -> mnt = mntget (& first -> mnt );
5178+ root -> dentry = dget (root -> mnt -> mnt_root );
5179+ return 0 ;
5180+ }
5181+
5182+ /*
5183+ * If the user requested a specific mount namespace id, look that up and return
5184+ * that, or if not simply grab a passive reference on our mount namespace and
5185+ * return that.
5186+ */
5187+ static struct mnt_namespace * grab_requested_mnt_ns (u64 mnt_ns_id )
5188+ {
5189+ if (mnt_ns_id )
5190+ return lookup_mnt_ns (mnt_ns_id );
5191+ refcount_inc (& current -> nsproxy -> mnt_ns -> passive );
5192+ return current -> nsproxy -> mnt_ns ;
5193+ }
5194+
51435195SYSCALL_DEFINE4 (statmount , const struct mnt_id_req __user * , req ,
51445196 struct statmount __user * , buf , size_t , bufsize ,
51455197 unsigned int , flags )
@@ -5185,30 +5237,21 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req,
51855237 return ret ;
51865238}
51875239
5188- static struct mount * listmnt_next (struct mount * curr , bool reverse )
5189- {
5190- struct rb_node * node ;
5191-
5192- if (reverse )
5193- node = rb_prev (& curr -> mnt_node );
5194- else
5195- node = rb_next (& curr -> mnt_node );
5196-
5197- return node_to_mount (node );
5198- }
5199-
5200- static ssize_t do_listmount (u64 mnt_parent_id , u64 last_mnt_id , u64 * mnt_ids ,
5201- size_t nr_mnt_ids , bool reverse )
5240+ static ssize_t do_listmount (struct mnt_namespace * ns , u64 mnt_parent_id ,
5241+ u64 last_mnt_id , u64 * mnt_ids , size_t nr_mnt_ids ,
5242+ bool reverse )
52025243{
52035244 struct path root __free (path_put ) = {};
5204- struct mnt_namespace * ns = current -> nsproxy -> mnt_ns ;
52055245 struct path orig ;
52065246 struct mount * r , * first ;
52075247 ssize_t ret ;
52085248
52095249 rwsem_assert_held (& namespace_sem );
52105250
5211- get_fs_root (current -> fs , & root );
5251+ ret = grab_requested_root (ns , & root );
5252+ if (ret )
5253+ return ret ;
5254+
52125255 if (mnt_parent_id == LSMT_ROOT ) {
52135256 orig = root ;
52145257 } else {
@@ -5260,6 +5303,7 @@ SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req,
52605303{
52615304 u64 * kmnt_ids __free (kvfree ) = NULL ;
52625305 const size_t maxcount = 1000000 ;
5306+ struct mnt_namespace * ns __free (mnt_ns_release ) = NULL ;
52635307 struct mnt_id_req kreq ;
52645308 ssize_t ret ;
52655309
@@ -5286,8 +5330,16 @@ SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req,
52865330 if (!kmnt_ids )
52875331 return - ENOMEM ;
52885332
5333+ ns = grab_requested_mnt_ns (kreq .mnt_ns_id );
5334+ if (!ns )
5335+ return - ENOENT ;
5336+
5337+ if (kreq .mnt_ns_id && (ns != current -> nsproxy -> mnt_ns ) &&
5338+ !ns_capable_noaudit (ns -> user_ns , CAP_SYS_ADMIN ))
5339+ return - ENOENT ;
5340+
52895341 scoped_guard (rwsem_read , & namespace_sem )
5290- ret = do_listmount (kreq .mnt_id , kreq .param , kmnt_ids ,
5342+ ret = do_listmount (ns , kreq .mnt_id , kreq .param , kmnt_ids ,
52915343 nr_mnt_ids , (flags & LISTMOUNT_REVERSE ));
52925344
52935345 if (copy_to_user (mnt_ids , kmnt_ids , ret * sizeof (* mnt_ids )))
0 commit comments