Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <linux/mount.h>
0003 #include <linux/pseudo_fs.h>
0004 #include <linux/file.h>
0005 #include <linux/fs.h>
0006 #include <linux/proc_fs.h>
0007 #include <linux/proc_ns.h>
0008 #include <linux/magic.h>
0009 #include <linux/ktime.h>
0010 #include <linux/seq_file.h>
0011 #include <linux/user_namespace.h>
0012 #include <linux/nsfs.h>
0013 #include <linux/uaccess.h>
0014 
0015 #include "internal.h"
0016 
0017 static struct vfsmount *nsfs_mnt;
0018 
0019 static long ns_ioctl(struct file *filp, unsigned int ioctl,
0020             unsigned long arg);
0021 static const struct file_operations ns_file_operations = {
0022     .llseek     = no_llseek,
0023     .unlocked_ioctl = ns_ioctl,
0024 };
0025 
0026 static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
0027 {
0028     struct inode *inode = d_inode(dentry);
0029     const struct proc_ns_operations *ns_ops = dentry->d_fsdata;
0030 
0031     return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
0032         ns_ops->name, inode->i_ino);
0033 }
0034 
0035 static void ns_prune_dentry(struct dentry *dentry)
0036 {
0037     struct inode *inode = d_inode(dentry);
0038     if (inode) {
0039         struct ns_common *ns = inode->i_private;
0040         atomic_long_set(&ns->stashed, 0);
0041     }
0042 }
0043 
0044 const struct dentry_operations ns_dentry_operations =
0045 {
0046     .d_prune    = ns_prune_dentry,
0047     .d_delete   = always_delete_dentry,
0048     .d_dname    = ns_dname,
0049 };
0050 
0051 static void nsfs_evict(struct inode *inode)
0052 {
0053     struct ns_common *ns = inode->i_private;
0054     clear_inode(inode);
0055     ns->ops->put(ns);
0056 }
0057 
0058 static int __ns_get_path(struct path *path, struct ns_common *ns)
0059 {
0060     struct vfsmount *mnt = nsfs_mnt;
0061     struct dentry *dentry;
0062     struct inode *inode;
0063     unsigned long d;
0064 
0065     rcu_read_lock();
0066     d = atomic_long_read(&ns->stashed);
0067     if (!d)
0068         goto slow;
0069     dentry = (struct dentry *)d;
0070     if (!lockref_get_not_dead(&dentry->d_lockref))
0071         goto slow;
0072     rcu_read_unlock();
0073     ns->ops->put(ns);
0074 got_it:
0075     path->mnt = mntget(mnt);
0076     path->dentry = dentry;
0077     return 0;
0078 slow:
0079     rcu_read_unlock();
0080     inode = new_inode_pseudo(mnt->mnt_sb);
0081     if (!inode) {
0082         ns->ops->put(ns);
0083         return -ENOMEM;
0084     }
0085     inode->i_ino = ns->inum;
0086     inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
0087     inode->i_flags |= S_IMMUTABLE;
0088     inode->i_mode = S_IFREG | S_IRUGO;
0089     inode->i_fop = &ns_file_operations;
0090     inode->i_private = ns;
0091 
0092     dentry = d_alloc_anon(mnt->mnt_sb);
0093     if (!dentry) {
0094         iput(inode);
0095         return -ENOMEM;
0096     }
0097     d_instantiate(dentry, inode);
0098     dentry->d_fsdata = (void *)ns->ops;
0099     d = atomic_long_cmpxchg(&ns->stashed, 0, (unsigned long)dentry);
0100     if (d) {
0101         d_delete(dentry);   /* make sure ->d_prune() does nothing */
0102         dput(dentry);
0103         cpu_relax();
0104         return -EAGAIN;
0105     }
0106     goto got_it;
0107 }
0108 
0109 int ns_get_path_cb(struct path *path, ns_get_path_helper_t *ns_get_cb,
0110              void *private_data)
0111 {
0112     int ret;
0113 
0114     do {
0115         struct ns_common *ns = ns_get_cb(private_data);
0116         if (!ns)
0117             return -ENOENT;
0118         ret = __ns_get_path(path, ns);
0119     } while (ret == -EAGAIN);
0120 
0121     return ret;
0122 }
0123 
0124 struct ns_get_path_task_args {
0125     const struct proc_ns_operations *ns_ops;
0126     struct task_struct *task;
0127 };
0128 
0129 static struct ns_common *ns_get_path_task(void *private_data)
0130 {
0131     struct ns_get_path_task_args *args = private_data;
0132 
0133     return args->ns_ops->get(args->task);
0134 }
0135 
0136 int ns_get_path(struct path *path, struct task_struct *task,
0137           const struct proc_ns_operations *ns_ops)
0138 {
0139     struct ns_get_path_task_args args = {
0140         .ns_ops = ns_ops,
0141         .task   = task,
0142     };
0143 
0144     return ns_get_path_cb(path, ns_get_path_task, &args);
0145 }
0146 
0147 int open_related_ns(struct ns_common *ns,
0148            struct ns_common *(*get_ns)(struct ns_common *ns))
0149 {
0150     struct path path = {};
0151     struct file *f;
0152     int err;
0153     int fd;
0154 
0155     fd = get_unused_fd_flags(O_CLOEXEC);
0156     if (fd < 0)
0157         return fd;
0158 
0159     do {
0160         struct ns_common *relative;
0161 
0162         relative = get_ns(ns);
0163         if (IS_ERR(relative)) {
0164             put_unused_fd(fd);
0165             return PTR_ERR(relative);
0166         }
0167 
0168         err = __ns_get_path(&path, relative);
0169     } while (err == -EAGAIN);
0170 
0171     if (err) {
0172         put_unused_fd(fd);
0173         return err;
0174     }
0175 
0176     f = dentry_open(&path, O_RDONLY, current_cred());
0177     path_put(&path);
0178     if (IS_ERR(f)) {
0179         put_unused_fd(fd);
0180         fd = PTR_ERR(f);
0181     } else
0182         fd_install(fd, f);
0183 
0184     return fd;
0185 }
0186 EXPORT_SYMBOL_GPL(open_related_ns);
0187 
0188 static long ns_ioctl(struct file *filp, unsigned int ioctl,
0189             unsigned long arg)
0190 {
0191     struct user_namespace *user_ns;
0192     struct ns_common *ns = get_proc_ns(file_inode(filp));
0193     uid_t __user *argp;
0194     uid_t uid;
0195 
0196     switch (ioctl) {
0197     case NS_GET_USERNS:
0198         return open_related_ns(ns, ns_get_owner);
0199     case NS_GET_PARENT:
0200         if (!ns->ops->get_parent)
0201             return -EINVAL;
0202         return open_related_ns(ns, ns->ops->get_parent);
0203     case NS_GET_NSTYPE:
0204         return ns->ops->type;
0205     case NS_GET_OWNER_UID:
0206         if (ns->ops->type != CLONE_NEWUSER)
0207             return -EINVAL;
0208         user_ns = container_of(ns, struct user_namespace, ns);
0209         argp = (uid_t __user *) arg;
0210         uid = from_kuid_munged(current_user_ns(), user_ns->owner);
0211         return put_user(uid, argp);
0212     default:
0213         return -ENOTTY;
0214     }
0215 }
0216 
0217 int ns_get_name(char *buf, size_t size, struct task_struct *task,
0218             const struct proc_ns_operations *ns_ops)
0219 {
0220     struct ns_common *ns;
0221     int res = -ENOENT;
0222     const char *name;
0223     ns = ns_ops->get(task);
0224     if (ns) {
0225         name = ns_ops->real_ns_name ? : ns_ops->name;
0226         res = snprintf(buf, size, "%s:[%u]", name, ns->inum);
0227         ns_ops->put(ns);
0228     }
0229     return res;
0230 }
0231 
0232 bool proc_ns_file(const struct file *file)
0233 {
0234     return file->f_op == &ns_file_operations;
0235 }
0236 
0237 struct file *proc_ns_fget(int fd)
0238 {
0239     struct file *file;
0240 
0241     file = fget(fd);
0242     if (!file)
0243         return ERR_PTR(-EBADF);
0244 
0245     if (file->f_op != &ns_file_operations)
0246         goto out_invalid;
0247 
0248     return file;
0249 
0250 out_invalid:
0251     fput(file);
0252     return ERR_PTR(-EINVAL);
0253 }
0254 
0255 /**
0256  * ns_match() - Returns true if current namespace matches dev/ino provided.
0257  * @ns_common: current ns
0258  * @dev: dev_t from nsfs that will be matched against current nsfs
0259  * @ino: ino_t from nsfs that will be matched against current nsfs
0260  *
0261  * Return: true if dev and ino matches the current nsfs.
0262  */
0263 bool ns_match(const struct ns_common *ns, dev_t dev, ino_t ino)
0264 {
0265     return (ns->inum == ino) && (nsfs_mnt->mnt_sb->s_dev == dev);
0266 }
0267 
0268 
0269 static int nsfs_show_path(struct seq_file *seq, struct dentry *dentry)
0270 {
0271     struct inode *inode = d_inode(dentry);
0272     const struct proc_ns_operations *ns_ops = dentry->d_fsdata;
0273 
0274     seq_printf(seq, "%s:[%lu]", ns_ops->name, inode->i_ino);
0275     return 0;
0276 }
0277 
0278 static const struct super_operations nsfs_ops = {
0279     .statfs = simple_statfs,
0280     .evict_inode = nsfs_evict,
0281     .show_path = nsfs_show_path,
0282 };
0283 
0284 static int nsfs_init_fs_context(struct fs_context *fc)
0285 {
0286     struct pseudo_fs_context *ctx = init_pseudo(fc, NSFS_MAGIC);
0287     if (!ctx)
0288         return -ENOMEM;
0289     ctx->ops = &nsfs_ops;
0290     ctx->dops = &ns_dentry_operations;
0291     return 0;
0292 }
0293 
0294 static struct file_system_type nsfs = {
0295     .name = "nsfs",
0296     .init_fs_context = nsfs_init_fs_context,
0297     .kill_sb = kill_anon_super,
0298 };
0299 
0300 void __init nsfs_init(void)
0301 {
0302     nsfs_mnt = kern_mount(&nsfs);
0303     if (IS_ERR(nsfs_mnt))
0304         panic("can't set nsfs up\n");
0305     nsfs_mnt->mnt_sb->s_flags &= ~SB_NOUSER;
0306 }