Merge branch 'linus' into timers/core
Reason: Get upstream fixes before adding conflicting code. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
@@ -143,6 +143,7 @@ static const char * const task_state_array[] = {
|
||||
"x (dead)", /* 64 */
|
||||
"K (wakekill)", /* 128 */
|
||||
"W (waking)", /* 256 */
|
||||
"P (parked)", /* 512 */
|
||||
};
|
||||
|
||||
static inline const char *get_task_state(struct task_struct *tsk)
|
||||
|
||||
+89
-30
@@ -755,37 +755,8 @@ void pde_put(struct proc_dir_entry *pde)
|
||||
free_proc_entry(pde);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a /proc entry and free it if it's not currently in use.
|
||||
*/
|
||||
void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
|
||||
static void entry_rundown(struct proc_dir_entry *de)
|
||||
{
|
||||
struct proc_dir_entry **p;
|
||||
struct proc_dir_entry *de = NULL;
|
||||
const char *fn = name;
|
||||
unsigned int len;
|
||||
|
||||
spin_lock(&proc_subdir_lock);
|
||||
if (__xlate_proc_name(name, &parent, &fn) != 0) {
|
||||
spin_unlock(&proc_subdir_lock);
|
||||
return;
|
||||
}
|
||||
len = strlen(fn);
|
||||
|
||||
for (p = &parent->subdir; *p; p=&(*p)->next ) {
|
||||
if (proc_match(len, fn, *p)) {
|
||||
de = *p;
|
||||
*p = de->next;
|
||||
de->next = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&proc_subdir_lock);
|
||||
if (!de) {
|
||||
WARN(1, "name '%s'\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock(&de->pde_unload_lock);
|
||||
/*
|
||||
* Stop accepting new callers into module. If you're
|
||||
@@ -817,6 +788,40 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
|
||||
spin_lock(&de->pde_unload_lock);
|
||||
}
|
||||
spin_unlock(&de->pde_unload_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a /proc entry and free it if it's not currently in use.
|
||||
*/
|
||||
void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
|
||||
{
|
||||
struct proc_dir_entry **p;
|
||||
struct proc_dir_entry *de = NULL;
|
||||
const char *fn = name;
|
||||
unsigned int len;
|
||||
|
||||
spin_lock(&proc_subdir_lock);
|
||||
if (__xlate_proc_name(name, &parent, &fn) != 0) {
|
||||
spin_unlock(&proc_subdir_lock);
|
||||
return;
|
||||
}
|
||||
len = strlen(fn);
|
||||
|
||||
for (p = &parent->subdir; *p; p=&(*p)->next ) {
|
||||
if (proc_match(len, fn, *p)) {
|
||||
de = *p;
|
||||
*p = de->next;
|
||||
de->next = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&proc_subdir_lock);
|
||||
if (!de) {
|
||||
WARN(1, "name '%s'\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
entry_rundown(de);
|
||||
|
||||
if (S_ISDIR(de->mode))
|
||||
parent->nlink--;
|
||||
@@ -827,3 +832,57 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
|
||||
pde_put(de);
|
||||
}
|
||||
EXPORT_SYMBOL(remove_proc_entry);
|
||||
|
||||
int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
|
||||
{
|
||||
struct proc_dir_entry **p;
|
||||
struct proc_dir_entry *root = NULL, *de, *next;
|
||||
const char *fn = name;
|
||||
unsigned int len;
|
||||
|
||||
spin_lock(&proc_subdir_lock);
|
||||
if (__xlate_proc_name(name, &parent, &fn) != 0) {
|
||||
spin_unlock(&proc_subdir_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
len = strlen(fn);
|
||||
|
||||
for (p = &parent->subdir; *p; p=&(*p)->next ) {
|
||||
if (proc_match(len, fn, *p)) {
|
||||
root = *p;
|
||||
*p = root->next;
|
||||
root->next = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!root) {
|
||||
spin_unlock(&proc_subdir_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
de = root;
|
||||
while (1) {
|
||||
next = de->subdir;
|
||||
if (next) {
|
||||
de->subdir = next->next;
|
||||
next->next = NULL;
|
||||
de = next;
|
||||
continue;
|
||||
}
|
||||
spin_unlock(&proc_subdir_lock);
|
||||
|
||||
entry_rundown(de);
|
||||
next = de->parent;
|
||||
if (S_ISDIR(de->mode))
|
||||
next->nlink--;
|
||||
de->nlink = 0;
|
||||
if (de == root)
|
||||
break;
|
||||
pde_put(de);
|
||||
|
||||
spin_lock(&proc_subdir_lock);
|
||||
de = next;
|
||||
}
|
||||
pde_put(root);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(remove_proc_subtree);
|
||||
|
||||
+3
-3
@@ -446,9 +446,10 @@ static const struct file_operations proc_reg_file_ops_no_compat = {
|
||||
|
||||
struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
|
||||
{
|
||||
struct inode *inode = iget_locked(sb, de->low_ino);
|
||||
struct inode *inode = new_inode_pseudo(sb);
|
||||
|
||||
if (inode && (inode->i_state & I_NEW)) {
|
||||
if (inode) {
|
||||
inode->i_ino = de->low_ino;
|
||||
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
|
||||
PROC_I(inode)->pde = de;
|
||||
|
||||
@@ -476,7 +477,6 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
|
||||
inode->i_fop = de->proc_fops;
|
||||
}
|
||||
}
|
||||
unlock_new_inode(inode);
|
||||
} else
|
||||
pde_put(de);
|
||||
return inode;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/user_namespace.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/pid_namespace.h>
|
||||
#include <linux/parser.h>
|
||||
@@ -108,6 +109,9 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
|
||||
} else {
|
||||
ns = task_active_pid_ns(current);
|
||||
options = data;
|
||||
|
||||
if (!current_user_ns()->may_mount_proc)
|
||||
return ERR_PTR(-EPERM);
|
||||
}
|
||||
|
||||
sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns);
|
||||
|
||||
Reference in New Issue
Block a user