@@ -5040,24 +5040,78 @@ static int copy_statmount_to_user(struct kstatmount *s)
50405040 return 0 ;
50415041}
50425042
5043- static int do_statmount (struct kstatmount * s )
5043+ static struct mount * listmnt_next (struct mount * curr , bool reverse )
50445044{
5045- struct mount * m = real_mount (s -> mnt );
5046- struct mnt_namespace * ns = m -> mnt_ns ;
5045+ struct rb_node * node ;
5046+
5047+ if (reverse )
5048+ node = rb_prev (& curr -> mnt_node );
5049+ else
5050+ node = rb_next (& curr -> mnt_node );
5051+
5052+ return node_to_mount (node );
5053+ }
5054+
5055+ static int grab_requested_root (struct mnt_namespace * ns , struct path * root )
5056+ {
5057+ struct mount * first ;
5058+
5059+ rwsem_assert_held (& namespace_sem );
5060+
5061+ /* We're looking at our own ns, just use get_fs_root. */
5062+ if (ns == current -> nsproxy -> mnt_ns ) {
5063+ get_fs_root (current -> fs , root );
5064+ return 0 ;
5065+ }
5066+
5067+ /*
5068+ * We have to find the first mount in our ns and use that, however it
5069+ * may not exist, so handle that properly.
5070+ */
5071+ if (RB_EMPTY_ROOT (& ns -> mounts ))
5072+ return - ENOENT ;
5073+
5074+ first = listmnt_next (ns -> root , false);
5075+ if (!first )
5076+ return - ENOENT ;
5077+ root -> mnt = mntget (& first -> mnt );
5078+ root -> dentry = dget (root -> mnt -> mnt_root );
5079+ return 0 ;
5080+ }
5081+
5082+ static int do_statmount (struct kstatmount * s , u64 mnt_id , u64 mnt_ns_id ,
5083+ struct mnt_namespace * ns )
5084+ {
5085+ struct path root __free (path_put ) = {};
5086+ struct mount * m ;
50475087 int err ;
50485088
5089+ /* Has the namespace already been emptied? */
5090+ if (mnt_ns_id && RB_EMPTY_ROOT (& ns -> mounts ))
5091+ return - ENOENT ;
5092+
5093+ s -> mnt = lookup_mnt_in_ns (mnt_id , ns );
5094+ if (!s -> mnt )
5095+ return - ENOENT ;
5096+
5097+ err = grab_requested_root (ns , & root );
5098+ if (err )
5099+ return err ;
5100+
50495101 /*
50505102 * Don't trigger audit denials. We just want to determine what
50515103 * mounts to show users.
50525104 */
5053- if (!is_path_reachable (m , m -> mnt .mnt_root , & s -> root ) &&
5105+ m = real_mount (s -> mnt );
5106+ if (!is_path_reachable (m , m -> mnt .mnt_root , & root ) &&
50545107 !ns_capable_noaudit (ns -> user_ns , CAP_SYS_ADMIN ))
50555108 return - EPERM ;
50565109
50575110 err = security_sb_statfs (s -> mnt -> mnt_root );
50585111 if (err )
50595112 return err ;
50605113
5114+ s -> root = root ;
50615115 if (s -> mask & STATMOUNT_SB_BASIC )
50625116 statmount_sb_basic (s );
50635117
@@ -5096,6 +5150,9 @@ static inline bool retry_statmount(const long ret, size_t *seq_size)
50965150 return true;
50975151}
50985152
5153+ #define STATMOUNT_STRING_REQ (STATMOUNT_MNT_ROOT | STATMOUNT_MNT_POINT | \
5154+ STATMOUNT_FS_TYPE)
5155+
50995156static int prepare_kstatmount (struct kstatmount * ks , struct mnt_id_req * kreq ,
51005157 struct statmount __user * buf , size_t bufsize ,
51015158 size_t seq_size )
@@ -5107,10 +5164,18 @@ static int prepare_kstatmount(struct kstatmount *ks, struct mnt_id_req *kreq,
51075164 ks -> mask = kreq -> param ;
51085165 ks -> buf = buf ;
51095166 ks -> bufsize = bufsize ;
5110- ks -> seq .size = seq_size ;
5111- ks -> seq .buf = kvmalloc (seq_size , GFP_KERNEL_ACCOUNT );
5112- if (!ks -> seq .buf )
5113- return - ENOMEM ;
5167+
5168+ if (ks -> mask & STATMOUNT_STRING_REQ ) {
5169+ if (bufsize == sizeof (ks -> sm ))
5170+ return - EOVERFLOW ;
5171+
5172+ ks -> seq .buf = kvmalloc (seq_size , GFP_KERNEL_ACCOUNT );
5173+ if (!ks -> seq .buf )
5174+ return - ENOMEM ;
5175+
5176+ ks -> seq .size = seq_size ;
5177+ }
5178+
51145179 return 0 ;
51155180}
51165181
@@ -5138,45 +5203,6 @@ static int copy_mnt_id_req(const struct mnt_id_req __user *req,
51385203 return 0 ;
51395204}
51405205
5141- static struct mount * listmnt_next (struct mount * curr , bool reverse )
5142- {
5143- struct rb_node * node ;
5144-
5145- if (reverse )
5146- node = rb_prev (& curr -> mnt_node );
5147- else
5148- node = rb_next (& curr -> mnt_node );
5149-
5150- return node_to_mount (node );
5151- }
5152-
5153- static int grab_requested_root (struct mnt_namespace * ns , struct path * root )
5154- {
5155- struct mount * first ;
5156-
5157- rwsem_assert_held (& namespace_sem );
5158-
5159- /* We're looking at our own ns, just use get_fs_root. */
5160- if (ns == current -> nsproxy -> mnt_ns ) {
5161- get_fs_root (current -> fs , root );
5162- return 0 ;
5163- }
5164-
5165- /*
5166- * We have to find the first mount in our ns and use that, however it
5167- * may not exist, so handle that properly.
5168- */
5169- if (RB_EMPTY_ROOT (& ns -> mounts ))
5170- return - ENOENT ;
5171-
5172- first = listmnt_next (ns -> root , false);
5173- if (!first )
5174- return - ENOENT ;
5175- root -> mnt = mntget (& first -> mnt );
5176- root -> dentry = dget (root -> mnt -> mnt_root );
5177- return 0 ;
5178- }
5179-
51805206/*
51815207 * If the user requested a specific mount namespace id, look that up and return
51825208 * that, or if not simply grab a passive reference on our mount namespace and
@@ -5195,9 +5221,8 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req,
51955221 unsigned int , flags )
51965222{
51975223 struct mnt_namespace * ns __free (mnt_ns_release ) = NULL ;
5198- struct vfsmount * mnt ;
5224+ struct kstatmount * ks __free ( kfree ) = NULL ;
51995225 struct mnt_id_req kreq ;
5200- struct kstatmount ks ;
52015226 /* We currently support retrieval of 3 strings. */
52025227 size_t seq_size = 3 * PATH_MAX ;
52035228 int ret ;
@@ -5217,40 +5242,21 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req,
52175242 !ns_capable_noaudit (ns -> user_ns , CAP_SYS_ADMIN ))
52185243 return - ENOENT ;
52195244
5245+ ks = kmalloc (sizeof (* ks ), GFP_KERNEL_ACCOUNT );
5246+ if (!ks )
5247+ return - ENOMEM ;
5248+
52205249retry :
5221- ret = prepare_kstatmount (& ks , & kreq , buf , bufsize , seq_size );
5250+ ret = prepare_kstatmount (ks , & kreq , buf , bufsize , seq_size );
52225251 if (ret )
52235252 return ret ;
52245253
5225- down_read (& namespace_sem );
5226- /* Has the namespace already been emptied? */
5227- if (kreq .mnt_ns_id && RB_EMPTY_ROOT (& ns -> mounts )) {
5228- up_read (& namespace_sem );
5229- kvfree (ks .seq .buf );
5230- return - ENOENT ;
5231- }
5232-
5233- mnt = lookup_mnt_in_ns (kreq .mnt_id , ns );
5234- if (!mnt ) {
5235- up_read (& namespace_sem );
5236- kvfree (ks .seq .buf );
5237- return - ENOENT ;
5238- }
5239-
5240- ks .mnt = mnt ;
5241- ret = grab_requested_root (ns , & ks .root );
5242- if (ret ) {
5243- up_read (& namespace_sem );
5244- kvfree (ks .seq .buf );
5245- return ret ;
5246- }
5247- ret = do_statmount (& ks );
5248- path_put (& ks .root );
5249- up_read (& namespace_sem );
5254+ scoped_guard (rwsem_read , & namespace_sem )
5255+ ret = do_statmount (ks , kreq .mnt_id , kreq .mnt_ns_id , ns );
52505256
52515257 if (!ret )
5252- ret = copy_statmount_to_user (& ks );
5253- kvfree (ks . seq .buf );
5258+ ret = copy_statmount_to_user (ks );
5259+ kvfree (ks -> seq .buf );
52545260 if (retry_statmount (ret , & seq_size ))
52555261 goto retry ;
52565262 return ret ;
0 commit comments