| @@ -32,6 +32,7 @@ · 31 unmodified lines |
| 32 | #include <linux/fs_context.h> | 32 | #include <linux/fs_context.h> |
| 33 | #include <linux/shmem_fs.h> | 33 | #include <linux/shmem_fs.h> |
| 34 | #include <linux/mnt_idmapping.h> | 34 | #include <linux/mnt_idmapping.h> |
| | 35 | #include <linux/nospec.h> |
| 35 | | 36 | |
| 36 | #include "pnode.h" | 37 | #include "pnode.h" |
| 37 | #include "internal.h" | 38 | #include "internal.h" |
| @@ -1009,7 +1010,7 @@ void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp, struct m · 971 unmodified lines |
| 1009 | | 1010 | |
| 1010 | static inline struct mount *node_to_mount(struct rb_node *node) | 1011 | static inline struct mount *node_to_mount(struct rb_node *node) |
| 1011 | { | 1012 | { |
| 1012 | return rb_entry(node, struct mount, mnt_node); | 1013 | return node ? rb_entry(node, struct mount, mnt_node) : NULL; |
| 1013 | } | 1014 | } |
| 1014 | | 1015 | |
| 1015 | static void mnt_add_to_ns(struct mnt_namespace *ns, struct mount *mnt) | 1016 | static void mnt_add_to_ns(struct mnt_namespace *ns, struct mount *mnt) |
| @@ -4945,7 +4946,7 @@ static int prepare_kstatmount(struct kstatmount *ks, struct mnt_id_req *kreq, · 3929 unmodified lines |
| 4945 | return -EFAULT; | 4946 | return -EFAULT; |
| 4946 | | 4947 | |
| 4947 | memset(ks, 0, sizeof(*ks)); | 4948 | memset(ks, 0, sizeof(*ks)); |
| 4948 | ks->mask = kreq->request_mask; | 4949 | ks->mask = kreq->param; |
| 4949 | ks->buf = buf; | 4950 | ks->buf = buf; |
| 4950 | ks->bufsize = bufsize; | 4951 | ks->bufsize = bufsize; |
| 4951 | ks->seq.size = seq_size; | 4952 | ks->seq.size = seq_size; |
| @@ -4999,6 +5000,87 @@ retry: · 47 unmodified lines |
| 4999 | return ret; | 5000 | return ret; |
| 5000 | } | 5001 | } |
| 5001 | | 5002 | |
| | 5003 | static struct mount *listmnt_next(struct mount *curr) |
| | 5004 | { |
| | 5005 | return node_to_mount(rb_next(&curr->mnt_node)); |
| | 5006 | } |
| | 5007 | |
| | 5008 | static ssize_t do_listmount(struct mount *first, struct path *orig, u64 mnt_id, |
| | 5009 | u64 __user *buf, size_t bufsize, |
| | 5010 | const struct path *root) |
| | 5011 | { |
| | 5012 | struct mount *r; |
| | 5013 | ssize_t ctr; |
| | 5014 | int err; |
| | 5015 | |
| | 5016 | /* |
| | 5017 | * Don't trigger audit denials. We just want to determine what |
| | 5018 | * mounts to show users. |
| | 5019 | */ |
| | 5020 | if (!is_path_reachable(real_mount(orig->mnt), orig->dentry, root) && |
| | 5021 | !ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN)) |
| | 5022 | return -EPERM; |
| | 5023 | |
| | 5024 | err = security_sb_statfs(orig->dentry); |
| | 5025 | if (err) |
| | 5026 | return err; |
| | 5027 | |
| | 5028 | for (ctr = 0, r = first; r && ctr < bufsize; r = listmnt_next(r)) { |
| | 5029 | if (r->mnt_id_unique == mnt_id) |
| | 5030 | continue; |
| | 5031 | if (!is_path_reachable(r, r->mnt.mnt_root, orig)) |
| | 5032 | continue; |
| | 5033 | ctr = array_index_nospec(ctr, bufsize); |
| | 5034 | if (put_user(r->mnt_id_unique, buf + ctr)) |
| | 5035 | return -EFAULT; |
| | 5036 | if (check_add_overflow(ctr, 1, &ctr)) |
| | 5037 | return -ERANGE; |
| | 5038 | } |
| | 5039 | return ctr; |
| | 5040 | } |
| | 5041 | |
| | 5042 | SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req, |
| | 5043 | u64 __user *, buf, size_t, bufsize, unsigned int, flags) |
| | 5044 | { |
| | 5045 | struct mnt_namespace *ns = current->nsproxy->mnt_ns; |
| | 5046 | struct mnt_id_req kreq; |
| | 5047 | struct mount *first; |
| | 5048 | struct path root, orig; |
| | 5049 | u64 mnt_id, last_mnt_id; |
| | 5050 | ssize_t ret; |
| | 5051 | |
| | 5052 | if (flags) |
| | 5053 | return -EINVAL; |
| | 5054 | |
| | 5055 | if (copy_from_user(&kreq, req, sizeof(kreq))) |
| | 5056 | return -EFAULT; |
| | 5057 | mnt_id = kreq.mnt_id; |
| | 5058 | last_mnt_id = kreq.param; |
| | 5059 | |
| | 5060 | down_read(&namespace_sem); |
| | 5061 | get_fs_root(current->fs, &root); |
| | 5062 | if (mnt_id == LSMT_ROOT) { |
| | 5063 | orig = root; |
| | 5064 | } else { |
| | 5065 | ret = -ENOENT; |
| | 5066 | orig.mnt = lookup_mnt_in_ns(mnt_id, ns); |
| | 5067 | if (!orig.mnt) |
| | 5068 | goto err; |
| | 5069 | orig.dentry = orig.mnt->mnt_root; |
| | 5070 | } |
| | 5071 | if (!last_mnt_id) |
| | 5072 | first = node_to_mount(rb_first(&ns->mounts)); |
| | 5073 | else |
| | 5074 | first = mnt_find_id_at(ns, last_mnt_id + 1); |
| | 5075 | |
| | 5076 | ret = do_listmount(first, &orig, mnt_id, buf, bufsize, &root); |
| | 5077 | err: |
| | 5078 | path_put(&root); |
| | 5079 | up_read(&namespace_sem); |
| | 5080 | return ret; |
| | 5081 | } |
| | 5082 | |
| | 5083 | |
| 5002 | static void __init init_mount_tree(void) | 5084 | static void __init init_mount_tree(void) |
| 5003 | { | 5085 | { |
| 5004 | struct vfsmount *mnt; | 5086 | struct vfsmount *mnt; |