@@ -5963,23 +5963,34 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req,
59635963 return ret ;
59645964}
59655965
5966- static ssize_t do_listmount (struct mnt_namespace * ns , u64 mnt_parent_id ,
5967- u64 last_mnt_id , u64 * mnt_ids , size_t nr_mnt_ids ,
5968- bool reverse )
5966+ struct klistmount {
5967+ u64 last_mnt_id ;
5968+ u64 mnt_parent_id ;
5969+ u64 * kmnt_ids ;
5970+ u32 nr_mnt_ids ;
5971+ struct mnt_namespace * ns ;
5972+ struct path root ;
5973+ };
5974+
5975+ static ssize_t do_listmount (struct klistmount * kls , bool reverse )
59695976{
5970- struct path root __free (path_put ) = {};
5977+ struct mnt_namespace * ns = kls -> ns ;
5978+ u64 mnt_parent_id = kls -> mnt_parent_id ;
5979+ u64 last_mnt_id = kls -> last_mnt_id ;
5980+ u64 * mnt_ids = kls -> kmnt_ids ;
5981+ size_t nr_mnt_ids = kls -> nr_mnt_ids ;
59715982 struct path orig ;
59725983 struct mount * r , * first ;
59735984 ssize_t ret ;
59745985
59755986 rwsem_assert_held (& namespace_sem );
59765987
5977- ret = grab_requested_root (ns , & root );
5988+ ret = grab_requested_root (ns , & kls -> root );
59785989 if (ret )
59795990 return ret ;
59805991
59815992 if (mnt_parent_id == LSMT_ROOT ) {
5982- orig = root ;
5993+ orig = kls -> root ;
59835994 } else {
59845995 orig .mnt = lookup_mnt_in_ns (mnt_parent_id , ns );
59855996 if (!orig .mnt )
@@ -5991,7 +6002,7 @@ static ssize_t do_listmount(struct mnt_namespace *ns, u64 mnt_parent_id,
59916002 * Don't trigger audit denials. We just want to determine what
59926003 * mounts to show users.
59936004 */
5994- if (!is_path_reachable (real_mount (orig .mnt ), orig .dentry , & root ) &&
6005+ if (!is_path_reachable (real_mount (orig .mnt ), orig .dentry , & kls -> root ) &&
59956006 !ns_capable_noaudit (ns -> user_ns , CAP_SYS_ADMIN ))
59966007 return - EPERM ;
59976008
@@ -6024,14 +6035,45 @@ static ssize_t do_listmount(struct mnt_namespace *ns, u64 mnt_parent_id,
60246035 return ret ;
60256036}
60266037
6038+ static void __free_klistmount_free (const struct klistmount * kls )
6039+ {
6040+ path_put (& kls -> root );
6041+ kvfree (kls -> kmnt_ids );
6042+ mnt_ns_release (kls -> ns );
6043+ }
6044+
6045+ static inline int prepare_klistmount (struct klistmount * kls , struct mnt_id_req * kreq ,
6046+ size_t nr_mnt_ids )
6047+ {
6048+
6049+ u64 last_mnt_id = kreq -> param ;
6050+
6051+ /* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */
6052+ if (last_mnt_id != 0 && last_mnt_id <= MNT_UNIQUE_ID_OFFSET )
6053+ return - EINVAL ;
6054+
6055+ kls -> last_mnt_id = last_mnt_id ;
6056+
6057+ kls -> nr_mnt_ids = nr_mnt_ids ;
6058+ kls -> kmnt_ids = kvmalloc_array (nr_mnt_ids , sizeof (* kls -> kmnt_ids ),
6059+ GFP_KERNEL_ACCOUNT );
6060+ if (!kls -> kmnt_ids )
6061+ return - ENOMEM ;
6062+
6063+ kls -> ns = grab_requested_mnt_ns (kreq );
6064+ if (!kls -> ns )
6065+ return - ENOENT ;
6066+
6067+ kls -> mnt_parent_id = kreq -> mnt_id ;
6068+ return 0 ;
6069+ }
6070+
60276071SYSCALL_DEFINE4 (listmount , const struct mnt_id_req __user * , req ,
60286072 u64 __user * , mnt_ids , size_t , nr_mnt_ids , unsigned int , flags )
60296073{
6030- u64 * kmnt_ids __free (kvfree ) = NULL ;
6074+ struct klistmount kls __free (klistmount_free ) = {} ;
60316075 const size_t maxcount = 1000000 ;
6032- struct mnt_namespace * ns __free (mnt_ns_release ) = NULL ;
60336076 struct mnt_id_req kreq ;
6034- u64 last_mnt_id ;
60356077 ssize_t ret ;
60366078
60376079 if (flags & ~LISTMOUNT_REVERSE )
@@ -6052,35 +6094,24 @@ SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req,
60526094 if (ret )
60536095 return ret ;
60546096
6055- last_mnt_id = kreq .param ;
6056- /* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */
6057- if (last_mnt_id != 0 && last_mnt_id <= MNT_UNIQUE_ID_OFFSET )
6058- return - EINVAL ;
6059-
6060- kmnt_ids = kvmalloc_array (nr_mnt_ids , sizeof (* kmnt_ids ),
6061- GFP_KERNEL_ACCOUNT );
6062- if (!kmnt_ids )
6063- return - ENOMEM ;
6064-
6065- ns = grab_requested_mnt_ns (& kreq );
6066- if (!ns )
6067- return - ENOENT ;
6097+ ret = prepare_klistmount (& kls , & kreq , nr_mnt_ids );
6098+ if (ret )
6099+ return ret ;
60686100
6069- if (kreq .mnt_ns_id && (ns != current -> nsproxy -> mnt_ns ) &&
6070- !ns_capable_noaudit (ns -> user_ns , CAP_SYS_ADMIN ))
6101+ if (kreq .mnt_ns_id && (kls . ns != current -> nsproxy -> mnt_ns ) &&
6102+ !ns_capable_noaudit (kls . ns -> user_ns , CAP_SYS_ADMIN ))
60716103 return - ENOENT ;
60726104
60736105 /*
60746106 * We only need to guard against mount topology changes as
60756107 * listmount() doesn't care about any mount properties.
60766108 */
60776109 scoped_guard (rwsem_read , & namespace_sem )
6078- ret = do_listmount (ns , kreq .mnt_id , last_mnt_id , kmnt_ids ,
6079- nr_mnt_ids , (flags & LISTMOUNT_REVERSE ));
6110+ ret = do_listmount (& kls , (flags & LISTMOUNT_REVERSE ));
60806111 if (ret <= 0 )
60816112 return ret ;
60826113
6083- if (copy_to_user (mnt_ids , kmnt_ids , ret * sizeof (* mnt_ids )))
6114+ if (copy_to_user (mnt_ids , kls . kmnt_ids , ret * sizeof (* mnt_ids )))
60846115 return - EFAULT ;
60856116
60866117 return ret ;
0 commit comments