@@ -4498,65 +4498,27 @@ bool path_is_under(const struct path *path1, const struct path *path2)
44984498}
44994499EXPORT_SYMBOL (path_is_under );
45004500
4501- /*
4502- * pivot_root Semantics:
4503- * Moves the root file system of the current process to the directory put_old,
4504- * makes new_root as the new root file system of the current process, and sets
4505- * root/cwd of all processes which had them on the current root to new_root.
4506- *
4507- * Restrictions:
4508- * The new_root and put_old must be directories, and must not be on the
4509- * same file system as the current process root. The put_old must be
4510- * underneath new_root, i.e. adding a non-zero number of /.. to the string
4511- * pointed to by put_old must yield the same directory as new_root. No other
4512- * file system may be mounted on put_old. After all, new_root is a mountpoint.
4513- *
4514- * Also, the current root cannot be on the 'rootfs' (initial ramfs) filesystem.
4515- * See Documentation/filesystems/ramfs-rootfs-initramfs.rst for alternatives
4516- * in this situation.
4517- *
4518- * Notes:
4519- * - we don't move root/cwd if they are not at the root (reason: if something
4520- * cared enough to change them, it's probably wrong to force them elsewhere)
4521- * - it's okay to pick a root that isn't the root of a file system, e.g.
4522- * /nfs/my_root where /nfs is the mount point. It must be a mountpoint,
4523- * though, so you may need to say mount --bind /nfs/my_root /nfs/my_root
4524- * first.
4525- */
4526- SYSCALL_DEFINE2 (pivot_root , const char __user * , new_root ,
4527- const char __user * , put_old )
4501+ int path_pivot_root (struct path * new , struct path * old )
45284502{
4529- struct path new __free (path_put ) = {};
4530- struct path old __free (path_put ) = {};
45314503 struct path root __free (path_put ) = {};
45324504 struct mount * new_mnt , * root_mnt , * old_mnt , * root_parent , * ex_parent ;
45334505 int error ;
45344506
45354507 if (!may_mount ())
45364508 return - EPERM ;
45374509
4538- error = user_path_at (AT_FDCWD , new_root ,
4539- LOOKUP_FOLLOW | LOOKUP_DIRECTORY , & new );
4540- if (error )
4541- return error ;
4542-
4543- error = user_path_at (AT_FDCWD , put_old ,
4544- LOOKUP_FOLLOW | LOOKUP_DIRECTORY , & old );
4545- if (error )
4546- return error ;
4547-
4548- error = security_sb_pivotroot (& old , & new );
4510+ error = security_sb_pivotroot (old , new );
45494511 if (error )
45504512 return error ;
45514513
45524514 get_fs_root (current -> fs , & root );
45534515
4554- LOCK_MOUNT (old_mp , & old );
4516+ LOCK_MOUNT (old_mp , old );
45554517 old_mnt = old_mp .parent ;
45564518 if (IS_ERR (old_mnt ))
45574519 return PTR_ERR (old_mnt );
45584520
4559- new_mnt = real_mount (new . mnt );
4521+ new_mnt = real_mount (new -> mnt );
45604522 root_mnt = real_mount (root .mnt );
45614523 ex_parent = new_mnt -> mnt_parent ;
45624524 root_parent = root_mnt -> mnt_parent ;
@@ -4568,23 +4530,23 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
45684530 return - EINVAL ;
45694531 if (new_mnt -> mnt .mnt_flags & MNT_LOCKED )
45704532 return - EINVAL ;
4571- if (d_unlinked (new . dentry ))
4533+ if (d_unlinked (new -> dentry ))
45724534 return - ENOENT ;
45734535 if (new_mnt == root_mnt || old_mnt == root_mnt )
45744536 return - EBUSY ; /* loop, on the same file system */
45754537 if (!path_mounted (& root ))
45764538 return - EINVAL ; /* not a mountpoint */
45774539 if (!mnt_has_parent (root_mnt ))
45784540 return - EINVAL ; /* absolute root */
4579- if (!path_mounted (& new ))
4541+ if (!path_mounted (new ))
45804542 return - EINVAL ; /* not a mountpoint */
45814543 if (!mnt_has_parent (new_mnt ))
45824544 return - EINVAL ; /* absolute root */
45834545 /* make sure we can reach put_old from new_root */
4584- if (!is_path_reachable (old_mnt , old_mp .mp -> m_dentry , & new ))
4546+ if (!is_path_reachable (old_mnt , old_mp .mp -> m_dentry , new ))
45854547 return - EINVAL ;
45864548 /* make certain new is below the root */
4587- if (!is_path_reachable (new_mnt , new . dentry , & root ))
4549+ if (!is_path_reachable (new_mnt , new -> dentry , & root ))
45884550 return - EINVAL ;
45894551 lock_mount_hash ();
45904552 umount_mnt (new_mnt );
@@ -4603,10 +4565,55 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
46034565 unlock_mount_hash ();
46044566 mnt_notify_add (root_mnt );
46054567 mnt_notify_add (new_mnt );
4606- chroot_fs_refs (& root , & new );
4568+ chroot_fs_refs (& root , new );
46074569 return 0 ;
46084570}
46094571
4572+ /*
4573+ * pivot_root Semantics:
4574+ * Moves the root file system of the current process to the directory put_old,
4575+ * makes new_root as the new root file system of the current process, and sets
4576+ * root/cwd of all processes which had them on the current root to new_root.
4577+ *
4578+ * Restrictions:
4579+ * The new_root and put_old must be directories, and must not be on the
4580+ * same file system as the current process root. The put_old must be
4581+ * underneath new_root, i.e. adding a non-zero number of /.. to the string
4582+ * pointed to by put_old must yield the same directory as new_root. No other
4583+ * file system may be mounted on put_old. After all, new_root is a mountpoint.
4584+ *
4585+ * Also, the current root cannot be on the 'rootfs' (initial ramfs) filesystem.
4586+ * See Documentation/filesystems/ramfs-rootfs-initramfs.rst for alternatives
4587+ * in this situation.
4588+ *
4589+ * Notes:
4590+ * - we don't move root/cwd if they are not at the root (reason: if something
4591+ * cared enough to change them, it's probably wrong to force them elsewhere)
4592+ * - it's okay to pick a root that isn't the root of a file system, e.g.
4593+ * /nfs/my_root where /nfs is the mount point. It must be a mountpoint,
4594+ * though, so you may need to say mount --bind /nfs/my_root /nfs/my_root
4595+ * first.
4596+ */
4597+ SYSCALL_DEFINE2 (pivot_root , const char __user * , new_root ,
4598+ const char __user * , put_old )
4599+ {
4600+ struct path new __free (path_put ) = {};
4601+ struct path old __free (path_put ) = {};
4602+ int error ;
4603+
4604+ error = user_path_at (AT_FDCWD , new_root ,
4605+ LOOKUP_FOLLOW | LOOKUP_DIRECTORY , & new );
4606+ if (error )
4607+ return error ;
4608+
4609+ error = user_path_at (AT_FDCWD , put_old ,
4610+ LOOKUP_FOLLOW | LOOKUP_DIRECTORY , & old );
4611+ if (error )
4612+ return error ;
4613+
4614+ return path_pivot_root (& new , & old );
4615+ }
4616+
46104617static unsigned int recalc_flags (struct mount_kattr * kattr , struct mount * mnt )
46114618{
46124619 unsigned int flags = mnt -> mnt .mnt_flags ;
0 commit comments