Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fs/namespace: correctly handle errors returned by grab_requested_mnt_ns

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: 7b9d14af8777 ("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>

authored by

Andrei Vagin and committed by
Christian Brauner
78f0e33c a3f8f866

+17 -17
+16 -16
fs/namespace.c
··· 141 141 kfree(ns); 142 142 } 143 143 } 144 - DEFINE_FREE(mnt_ns_release, struct mnt_namespace *, if (_T) mnt_ns_release(_T)) 144 + DEFINE_FREE(mnt_ns_release, struct mnt_namespace *, 145 + if (!IS_ERR(_T)) mnt_ns_release(_T)) 145 146 146 147 static void mnt_ns_release_rcu(struct rcu_head *rcu) 147 148 { ··· 5727 5726 ret = copy_struct_from_user(kreq, sizeof(*kreq), req, usize); 5728 5727 if (ret) 5729 5728 return ret; 5730 - if (kreq->spare != 0) 5729 + if (kreq->mnt_ns_fd != 0 && kreq->mnt_ns_id) 5731 5730 return -EINVAL; 5732 5731 /* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */ 5733 5732 if (kreq->mnt_id <= MNT_UNIQUE_ID_OFFSET) ··· 5744 5743 { 5745 5744 struct mnt_namespace *mnt_ns; 5746 5745 5747 - if (kreq->mnt_ns_id && kreq->spare) 5748 - return ERR_PTR(-EINVAL); 5749 - 5750 - if (kreq->mnt_ns_id) 5751 - return lookup_mnt_ns(kreq->mnt_ns_id); 5752 - 5753 - if (kreq->spare) { 5746 + if (kreq->mnt_ns_id) { 5747 + mnt_ns = lookup_mnt_ns(kreq->mnt_ns_id); 5748 + } else if (kreq->mnt_ns_fd) { 5754 5749 struct ns_common *ns; 5755 5750 5756 - CLASS(fd, f)(kreq->spare); 5751 + CLASS(fd, f)(kreq->mnt_ns_fd); 5757 5752 if (fd_empty(f)) 5758 5753 return ERR_PTR(-EBADF); 5759 5754 ··· 5764 5767 } else { 5765 5768 mnt_ns = current->nsproxy->mnt_ns; 5766 5769 } 5770 + if (!mnt_ns) 5771 + return ERR_PTR(-ENOENT); 5767 5772 5768 5773 refcount_inc(&mnt_ns->passive); 5769 5774 return mnt_ns; ··· 5790 5791 return ret; 5791 5792 5792 5793 ns = grab_requested_mnt_ns(&kreq); 5793 - if (!ns) 5794 - return -ENOENT; 5794 + if (IS_ERR(ns)) 5795 + return PTR_ERR(ns); 5795 5796 5796 5797 if (kreq.mnt_ns_id && (ns != current->nsproxy->mnt_ns) && 5797 5798 !ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN)) ··· 5901 5902 static inline int prepare_klistmount(struct klistmount *kls, struct mnt_id_req *kreq, 5902 5903 size_t nr_mnt_ids) 5903 5904 { 5904 - 5905 5905 u64 last_mnt_id = kreq->param; 5906 + struct mnt_namespace *ns; 5906 5907 5907 5908 /* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */ 5908 5909 if (last_mnt_id != 0 && last_mnt_id <= MNT_UNIQUE_ID_OFFSET) ··· 5916 5917 if (!kls->kmnt_ids) 5917 5918 return -ENOMEM; 5918 5919 5919 - kls->ns = grab_requested_mnt_ns(kreq); 5920 - if (!kls->ns) 5921 - return -ENOENT; 5920 + ns = grab_requested_mnt_ns(kreq); 5921 + if (IS_ERR(ns)) 5922 + return PTR_ERR(ns); 5923 + kls->ns = ns; 5922 5924 5923 5925 kls->mnt_parent_id = kreq->mnt_id; 5924 5926 return 0;
+1 -1
include/uapi/linux/mount.h
··· 197 197 */ 198 198 struct mnt_id_req { 199 199 __u32 size; 200 - __u32 spare; 200 + __u32 mnt_ns_fd; 201 201 __u64 mnt_id; 202 202 __u64 param; 203 203 __u64 mnt_ns_id;