|
@@ -502,17 +502,14 @@ static const struct inode_operations proc_def_inode_operations = {
|
|
|
.setattr = proc_setattr,
|
|
|
};
|
|
|
|
|
|
-extern const struct seq_operations mounts_op;
|
|
|
-struct proc_mounts {
|
|
|
- struct seq_file m;
|
|
|
- int event;
|
|
|
-};
|
|
|
-
|
|
|
-static int mounts_open(struct inode *inode, struct file *file)
|
|
|
+static int mounts_open_common(struct inode *inode, struct file *file,
|
|
|
+ const struct seq_operations *op)
|
|
|
{
|
|
|
struct task_struct *task = get_proc_task(inode);
|
|
|
struct nsproxy *nsp;
|
|
|
struct mnt_namespace *ns = NULL;
|
|
|
+ struct fs_struct *fs = NULL;
|
|
|
+ struct path root;
|
|
|
struct proc_mounts *p;
|
|
|
int ret = -EINVAL;
|
|
|
|
|
@@ -525,40 +522,61 @@ static int mounts_open(struct inode *inode, struct file *file)
|
|
|
get_mnt_ns(ns);
|
|
|
}
|
|
|
rcu_read_unlock();
|
|
|
-
|
|
|
+ if (ns)
|
|
|
+ fs = get_fs_struct(task);
|
|
|
put_task_struct(task);
|
|
|
}
|
|
|
|
|
|
- if (ns) {
|
|
|
- ret = -ENOMEM;
|
|
|
- p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
|
|
|
- if (p) {
|
|
|
- file->private_data = &p->m;
|
|
|
- ret = seq_open(file, &mounts_op);
|
|
|
- if (!ret) {
|
|
|
- p->m.private = ns;
|
|
|
- p->event = ns->event;
|
|
|
- return 0;
|
|
|
- }
|
|
|
- kfree(p);
|
|
|
- }
|
|
|
- put_mnt_ns(ns);
|
|
|
- }
|
|
|
+ if (!ns)
|
|
|
+ goto err;
|
|
|
+ if (!fs)
|
|
|
+ goto err_put_ns;
|
|
|
+
|
|
|
+ read_lock(&fs->lock);
|
|
|
+ root = fs->root;
|
|
|
+ path_get(&root);
|
|
|
+ read_unlock(&fs->lock);
|
|
|
+ put_fs_struct(fs);
|
|
|
+
|
|
|
+ ret = -ENOMEM;
|
|
|
+ p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
|
|
|
+ if (!p)
|
|
|
+ goto err_put_path;
|
|
|
+
|
|
|
+ file->private_data = &p->m;
|
|
|
+ ret = seq_open(file, op);
|
|
|
+ if (ret)
|
|
|
+ goto err_free;
|
|
|
+
|
|
|
+ p->m.private = p;
|
|
|
+ p->ns = ns;
|
|
|
+ p->root = root;
|
|
|
+ p->event = ns->event;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ err_free:
|
|
|
+ kfree(p);
|
|
|
+ err_put_path:
|
|
|
+ path_put(&root);
|
|
|
+ err_put_ns:
|
|
|
+ put_mnt_ns(ns);
|
|
|
+ err:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
static int mounts_release(struct inode *inode, struct file *file)
|
|
|
{
|
|
|
- struct seq_file *m = file->private_data;
|
|
|
- struct mnt_namespace *ns = m->private;
|
|
|
- put_mnt_ns(ns);
|
|
|
+ struct proc_mounts *p = file->private_data;
|
|
|
+ path_put(&p->root);
|
|
|
+ put_mnt_ns(p->ns);
|
|
|
return seq_release(inode, file);
|
|
|
}
|
|
|
|
|
|
static unsigned mounts_poll(struct file *file, poll_table *wait)
|
|
|
{
|
|
|
struct proc_mounts *p = file->private_data;
|
|
|
- struct mnt_namespace *ns = p->m.private;
|
|
|
+ struct mnt_namespace *ns = p->ns;
|
|
|
unsigned res = 0;
|
|
|
|
|
|
poll_wait(file, &ns->poll, wait);
|
|
@@ -573,6 +591,11 @@ static unsigned mounts_poll(struct file *file, poll_table *wait)
|
|
|
return res;
|
|
|
}
|
|
|
|
|
|
+static int mounts_open(struct inode *inode, struct file *file)
|
|
|
+{
|
|
|
+ return mounts_open_common(inode, file, &mounts_op);
|
|
|
+}
|
|
|
+
|
|
|
static const struct file_operations proc_mounts_operations = {
|
|
|
.open = mounts_open,
|
|
|
.read = seq_read,
|
|
@@ -581,38 +604,9 @@ static const struct file_operations proc_mounts_operations = {
|
|
|
.poll = mounts_poll,
|
|
|
};
|
|
|
|
|
|
-extern const struct seq_operations mountstats_op;
|
|
|
static int mountstats_open(struct inode *inode, struct file *file)
|
|
|
{
|
|
|
- int ret = seq_open(file, &mountstats_op);
|
|
|
-
|
|
|
- if (!ret) {
|
|
|
- struct seq_file *m = file->private_data;
|
|
|
- struct nsproxy *nsp;
|
|
|
- struct mnt_namespace *mnt_ns = NULL;
|
|
|
- struct task_struct *task = get_proc_task(inode);
|
|
|
-
|
|
|
- if (task) {
|
|
|
- rcu_read_lock();
|
|
|
- nsp = task_nsproxy(task);
|
|
|
- if (nsp) {
|
|
|
- mnt_ns = nsp->mnt_ns;
|
|
|
- if (mnt_ns)
|
|
|
- get_mnt_ns(mnt_ns);
|
|
|
- }
|
|
|
- rcu_read_unlock();
|
|
|
-
|
|
|
- put_task_struct(task);
|
|
|
- }
|
|
|
-
|
|
|
- if (mnt_ns)
|
|
|
- m->private = mnt_ns;
|
|
|
- else {
|
|
|
- seq_release(inode, file);
|
|
|
- ret = -EINVAL;
|
|
|
- }
|
|
|
- }
|
|
|
- return ret;
|
|
|
+ return mounts_open_common(inode, file, &mountstats_op);
|
|
|
}
|
|
|
|
|
|
static const struct file_operations proc_mountstats_operations = {
|