mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-04-03 12:05:13 +02:00
fs/namespace: correctly handle errors returned by grab_requested_mnt_ns
[ Upstream commit78f0e33cd6] grab_requested_mnt_ns was changed to return error codes on failure, but its callers were not updated to check for error pointers, still checking only for a NULL return value. This commit updates the callers to use IS_ERR() or IS_ERR_OR_NULL() and PTR_ERR() to correctly check for and propagate errors. This also makes sure that the logic actually works and mount namespace file descriptors can be used to refere to mounts. Christian Brauner <brauner@kernel.org> says: Rework the patch to be more ergonomic and in line with our overall error handling patterns. Fixes:7b9d14af87("fs: allow mount namespace fd") Cc: Christian Brauner <brauner@kernel.org> Signed-off-by: Andrei Vagin <avagin@google.com> Link: https://patch.msgid.link/20251111062815.2546189-1-avagin@google.com Reviewed-by: Jan Kara <jack@suse.cz> Signed-off-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
cf327202d9
commit
ba306daa7f
@@ -158,7 +158,8 @@ static void mnt_ns_release(struct mnt_namespace *ns)
|
||||
kfree(ns);
|
||||
}
|
||||
}
|
||||
DEFINE_FREE(mnt_ns_release, struct mnt_namespace *, if (_T) mnt_ns_release(_T))
|
||||
DEFINE_FREE(mnt_ns_release, struct mnt_namespace *,
|
||||
if (!IS_ERR(_T)) mnt_ns_release(_T))
|
||||
|
||||
static void mnt_ns_tree_remove(struct mnt_namespace *ns)
|
||||
{
|
||||
@@ -5325,7 +5326,7 @@ static int copy_mnt_id_req(const struct mnt_id_req __user *req,
|
||||
ret = copy_struct_from_user(kreq, sizeof(*kreq), req, usize);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (kreq->spare != 0)
|
||||
if (kreq->mnt_ns_fd != 0 && kreq->mnt_ns_id)
|
||||
return -EINVAL;
|
||||
/* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */
|
||||
if (kreq->mnt_id <= MNT_UNIQUE_ID_OFFSET)
|
||||
@@ -5342,16 +5343,12 @@ static struct mnt_namespace *grab_requested_mnt_ns(const struct mnt_id_req *kreq
|
||||
{
|
||||
struct mnt_namespace *mnt_ns;
|
||||
|
||||
if (kreq->mnt_ns_id && kreq->spare)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (kreq->mnt_ns_id)
|
||||
return lookup_mnt_ns(kreq->mnt_ns_id);
|
||||
|
||||
if (kreq->spare) {
|
||||
if (kreq->mnt_ns_id) {
|
||||
mnt_ns = lookup_mnt_ns(kreq->mnt_ns_id);
|
||||
} else if (kreq->mnt_ns_fd) {
|
||||
struct ns_common *ns;
|
||||
|
||||
CLASS(fd, f)(kreq->spare);
|
||||
CLASS(fd, f)(kreq->mnt_ns_fd);
|
||||
if (fd_empty(f))
|
||||
return ERR_PTR(-EBADF);
|
||||
|
||||
@@ -5366,6 +5363,8 @@ static struct mnt_namespace *grab_requested_mnt_ns(const struct mnt_id_req *kreq
|
||||
} else {
|
||||
mnt_ns = current->nsproxy->mnt_ns;
|
||||
}
|
||||
if (!mnt_ns)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
refcount_inc(&mnt_ns->passive);
|
||||
return mnt_ns;
|
||||
@@ -5390,8 +5389,8 @@ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req,
|
||||
return ret;
|
||||
|
||||
ns = grab_requested_mnt_ns(&kreq);
|
||||
if (!ns)
|
||||
return -ENOENT;
|
||||
if (IS_ERR(ns))
|
||||
return PTR_ERR(ns);
|
||||
|
||||
if (kreq.mnt_ns_id && (ns != current->nsproxy->mnt_ns) &&
|
||||
!ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN))
|
||||
@@ -5500,8 +5499,8 @@ static void __free_klistmount_free(const struct klistmount *kls)
|
||||
static inline int prepare_klistmount(struct klistmount *kls, struct mnt_id_req *kreq,
|
||||
size_t nr_mnt_ids)
|
||||
{
|
||||
|
||||
u64 last_mnt_id = kreq->param;
|
||||
struct mnt_namespace *ns;
|
||||
|
||||
/* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */
|
||||
if (last_mnt_id != 0 && last_mnt_id <= MNT_UNIQUE_ID_OFFSET)
|
||||
@@ -5515,9 +5514,10 @@ static inline int prepare_klistmount(struct klistmount *kls, struct mnt_id_req *
|
||||
if (!kls->kmnt_ids)
|
||||
return -ENOMEM;
|
||||
|
||||
kls->ns = grab_requested_mnt_ns(kreq);
|
||||
if (!kls->ns)
|
||||
return -ENOENT;
|
||||
ns = grab_requested_mnt_ns(kreq);
|
||||
if (IS_ERR(ns))
|
||||
return PTR_ERR(ns);
|
||||
kls->ns = ns;
|
||||
|
||||
kls->mnt_parent_id = kreq->mnt_id;
|
||||
return 0;
|
||||
|
||||
@@ -186,7 +186,7 @@ struct statmount {
|
||||
*/
|
||||
struct mnt_id_req {
|
||||
__u32 size;
|
||||
__u32 spare;
|
||||
__u32 mnt_ns_fd;
|
||||
__u64 mnt_id;
|
||||
__u64 param;
|
||||
__u64 mnt_ns_id;
|
||||
|
||||
Reference in New Issue
Block a user