@@ -2410,7 +2410,7 @@ void drop_collected_mounts(struct vfsmount *mnt)
2410
2410
namespace_unlock ();
2411
2411
}
2412
2412
2413
- bool has_locked_children (struct mount * mnt , struct dentry * dentry )
2413
+ static bool __has_locked_children (struct mount * mnt , struct dentry * dentry )
2414
2414
{
2415
2415
struct mount * child ;
2416
2416
@@ -2424,6 +2424,16 @@ bool has_locked_children(struct mount *mnt, struct dentry *dentry)
2424
2424
return false;
2425
2425
}
2426
2426
2427
+ bool has_locked_children (struct mount * mnt , struct dentry * dentry )
2428
+ {
2429
+ bool res ;
2430
+
2431
+ read_seqlock_excl (& mount_lock );
2432
+ res = __has_locked_children (mnt , dentry );
2433
+ read_sequnlock_excl (& mount_lock );
2434
+ return res ;
2435
+ }
2436
+
2427
2437
/*
2428
2438
* Check that there aren't references to earlier/same mount namespaces in the
2429
2439
* specified subtree. Such references can act as pins for mount namespaces
@@ -2468,23 +2478,27 @@ struct vfsmount *clone_private_mount(const struct path *path)
2468
2478
if (IS_MNT_UNBINDABLE (old_mnt ))
2469
2479
return ERR_PTR (- EINVAL );
2470
2480
2471
- if (mnt_has_parent (old_mnt )) {
2472
- if (!check_mnt (old_mnt ))
2473
- return ERR_PTR (- EINVAL );
2474
- } else {
2475
- if (!is_mounted (& old_mnt -> mnt ))
2476
- return ERR_PTR (- EINVAL );
2477
-
2478
- /* Make sure this isn't something purely kernel internal. */
2479
- if (!is_anon_ns (old_mnt -> mnt_ns ))
2481
+ /*
2482
+ * Make sure the source mount is acceptable.
2483
+ * Anything mounted in our mount namespace is allowed.
2484
+ * Otherwise, it must be the root of an anonymous mount
2485
+ * namespace, and we need to make sure no namespace
2486
+ * loops get created.
2487
+ */
2488
+ if (!check_mnt (old_mnt )) {
2489
+ if (!is_mounted (& old_mnt -> mnt ) ||
2490
+ !is_anon_ns (old_mnt -> mnt_ns ) ||
2491
+ mnt_has_parent (old_mnt ))
2480
2492
return ERR_PTR (- EINVAL );
2481
2493
2482
- /* Make sure we don't create mount namespace loops. */
2483
2494
if (!check_for_nsfs_mounts (old_mnt ))
2484
2495
return ERR_PTR (- EINVAL );
2485
2496
}
2486
2497
2487
- if (has_locked_children (old_mnt , path -> dentry ))
2498
+ if (!ns_capable (old_mnt -> mnt_ns -> user_ns , CAP_SYS_ADMIN ))
2499
+ return ERR_PTR (- EPERM );
2500
+
2501
+ if (__has_locked_children (old_mnt , path -> dentry ))
2488
2502
return ERR_PTR (- EINVAL );
2489
2503
2490
2504
new_mnt = clone_mnt (old_mnt , path -> dentry , CL_PRIVATE );
@@ -2930,6 +2944,10 @@ static int do_change_type(struct path *path, int ms_flags)
2930
2944
return - EINVAL ;
2931
2945
2932
2946
namespace_lock ();
2947
+ if (!check_mnt (mnt )) {
2948
+ err = - EINVAL ;
2949
+ goto out_unlock ;
2950
+ }
2933
2951
if (type == MS_SHARED ) {
2934
2952
err = invent_group_ids (mnt , recurse );
2935
2953
if (err )
@@ -3021,7 +3039,7 @@ static struct mount *__do_loopback(struct path *old_path, int recurse)
3021
3039
if (!may_copy_tree (old_path ))
3022
3040
return mnt ;
3023
3041
3024
- if (!recurse && has_locked_children (old , old_path -> dentry ))
3042
+ if (!recurse && __has_locked_children (old , old_path -> dentry ))
3025
3043
return mnt ;
3026
3044
3027
3045
if (recurse )
@@ -3414,7 +3432,7 @@ static int do_set_group(struct path *from_path, struct path *to_path)
3414
3432
goto out ;
3415
3433
3416
3434
/* From mount should not have locked children in place of To's root */
3417
- if (has_locked_children (from , to -> mnt .mnt_root ))
3435
+ if (__has_locked_children (from , to -> mnt .mnt_root ))
3418
3436
goto out ;
3419
3437
3420
3438
/* Setting sharing groups is only allowed on private mounts */
@@ -3428,7 +3446,7 @@ static int do_set_group(struct path *from_path, struct path *to_path)
3428
3446
if (IS_MNT_SLAVE (from )) {
3429
3447
struct mount * m = from -> mnt_master ;
3430
3448
3431
- list_add (& to -> mnt_slave , & m -> mnt_slave_list );
3449
+ list_add (& to -> mnt_slave , & from -> mnt_slave );
3432
3450
to -> mnt_master = m ;
3433
3451
}
3434
3452
@@ -3453,18 +3471,25 @@ static int do_set_group(struct path *from_path, struct path *to_path)
3453
3471
* Check if path is overmounted, i.e., if there's a mount on top of
3454
3472
* @path->mnt with @path->dentry as mountpoint.
3455
3473
*
3456
- * Context: This function expects namespace_lock() to be held.
3474
+ * Context: namespace_sem must be held at least shared.
3475
+ * MUST NOT be called under lock_mount_hash() (there one should just
3476
+ * call __lookup_mnt() and check if it returns NULL).
3457
3477
* Return: If path is overmounted true is returned, false if not.
3458
3478
*/
3459
3479
static inline bool path_overmounted (const struct path * path )
3460
3480
{
3481
+ unsigned seq = read_seqbegin (& mount_lock );
3482
+ bool no_child ;
3483
+
3461
3484
rcu_read_lock ();
3462
- if (unlikely (__lookup_mnt (path -> mnt , path -> dentry ))) {
3463
- rcu_read_unlock ();
3464
- return true;
3465
- }
3485
+ no_child = !__lookup_mnt (path -> mnt , path -> dentry );
3466
3486
rcu_read_unlock ();
3467
- return false;
3487
+ if (need_seqretry (& mount_lock , seq )) {
3488
+ read_seqlock_excl (& mount_lock );
3489
+ no_child = !__lookup_mnt (path -> mnt , path -> dentry );
3490
+ read_sequnlock_excl (& mount_lock );
3491
+ }
3492
+ return unlikely (!no_child );
3468
3493
}
3469
3494
3470
3495
/**
@@ -3623,37 +3648,41 @@ static int do_move_mount(struct path *old_path,
3623
3648
ns = old -> mnt_ns ;
3624
3649
3625
3650
err = - EINVAL ;
3626
- if (!may_use_mount (p ))
3627
- goto out ;
3628
-
3629
3651
/* The thing moved must be mounted... */
3630
3652
if (!is_mounted (& old -> mnt ))
3631
3653
goto out ;
3632
3654
3633
- /* ... and either ours or the root of anon namespace */
3634
- if (!(attached ? check_mnt (old ) : is_anon_ns (ns )))
3635
- goto out ;
3636
-
3637
- if (is_anon_ns (ns ) && ns == p -> mnt_ns ) {
3655
+ if (check_mnt (old )) {
3656
+ /* if the source is in our namespace... */
3657
+ /* ... it should be detachable from parent */
3658
+ if (!mnt_has_parent (old ) || IS_MNT_LOCKED (old ))
3659
+ goto out ;
3660
+ /* ... and the target should be in our namespace */
3661
+ if (!check_mnt (p ))
3662
+ goto out ;
3663
+ } else {
3638
3664
/*
3639
- * Ending up with two files referring to the root of the
3640
- * same anonymous mount namespace would cause an error
3641
- * as this would mean trying to move the same mount
3642
- * twice into the mount tree which would be rejected
3643
- * later. But be explicit about it right here.
3665
+ * otherwise the source must be the root of some anon namespace.
3666
+ * AV: check for mount being root of an anon namespace is worth
3667
+ * an inlined predicate...
3644
3668
*/
3645
- goto out ;
3646
- } else if ( is_anon_ns ( p -> mnt_ns )) {
3669
+ if (! is_anon_ns ( ns ) || mnt_has_parent ( old ))
3670
+ goto out ;
3647
3671
/*
3648
- * Don't allow moving an attached mount tree to an
3649
- * anonymous mount tree.
3672
+ * Bail out early if the target is within the same namespace -
3673
+ * subsequent checks would've rejected that, but they lose
3674
+ * some corner cases if we check it early.
3650
3675
*/
3651
- goto out ;
3676
+ if (ns == p -> mnt_ns )
3677
+ goto out ;
3678
+ /*
3679
+ * Target should be either in our namespace or in an acceptable
3680
+ * anon namespace, sensu check_anonymous_mnt().
3681
+ */
3682
+ if (!may_use_mount (p ))
3683
+ goto out ;
3652
3684
}
3653
3685
3654
- if (old -> mnt .mnt_flags & MNT_LOCKED )
3655
- goto out ;
3656
-
3657
3686
if (!path_mounted (old_path ))
3658
3687
goto out ;
3659
3688
0 commit comments