Skip to contentSkip to conversation

proc: fix task_struct infoleak

PATCH Superseded Vasiliy Kulikov 3 participants 4 messages Dec 11, 2011 – Dec 12, 2011 Proc filesystem

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 proc: fix task_struct infoleak

proc_pid_permission() doesn't put task_struct on every /proc/$pid/ access. A demo from Hugh Dickins:

while :; do ps; grep KernelStack /proc/meminfo; sleep 1; done

---
This is a patch against a hidepid patchset from -mm.

 fs/proc/base.c |    9 +++++++--
 1 files changed, 7 insertions(+), 2 deletions(-)
fs/proc/base.c +7 -2
index 8caf5cb..0e5c577 100644
@@ -646,9 +646,14 @@ static bool has_pid_permissions(struct pid_namespace *pid,
 static int proc_pid_permission(struct inode *inode, int mask)
 {
 	struct pid_namespace *pid = inode->i_sb->s_fs_info;
-	struct task_struct *task = get_proc_task(inode);
+	struct task_struct *task;
+	int has_perms;
+
+	task = get_proc_task(inode);
+	has_perms = has_pid_permissions(pid, task, 1);
+	put_task_struct(task);
 
-	if (!has_pid_permissions(pid, task, 1)) {
+	if (!has_perms) {
 		if (pid->hide_pid == 2) {
 			/*
 			 * Let's make getdents(), stat(), and open()
Signature · 1 line
1.7.0.4
#1 lore raw
Quoted 9 lines · Vasiliy Kulikov

proc_pid_permission() doesn't put task_struct on every /proc/$pid/ access. A demo from Hugh Dickins:

while :; do ps; grep KernelStack /proc/meminfo; sleep 1; done

---
This is a patch against a hidepid patchset from -mm.

Choose saner commit summary, please. It's not information leak, for pity sake
- it's a plain and simple memory leak...

Speaking of which, I've a couple of memory leaks in mainline procfs and mqueue; Alexey, are you OK with that sucker going directly to Linus or would you rather push it yourself? See the patch below...

fs/proc/root.c +3 -5
index 9a8a2b7..03102d9 100644
@@ -91,20 +91,18 @@ static struct file_system_type proc_fs_type = {
 
 void __init proc_root_init(void)
 {
-	struct vfsmount *mnt;
 	int err;
 
 	proc_init_inodecache();
 	err = register_filesystem(&proc_fs_type);
 	if (err)
 		return;
-	mnt = kern_mount_data(&proc_fs_type, &init_pid_ns);
-	if (IS_ERR(mnt)) {
+	err = pid_ns_prepare_proc(&init_pid_ns);
+	if (err) {
 		unregister_filesystem(&proc_fs_type);
 		return;
 	}
 
-	init_pid_ns.proc_mnt = mnt;
 	proc_symlink("mounts", NULL, "self/mounts");
 
 	proc_net_init();
@@ -209,5 +207,5 @@ int pid_ns_prepare_proc(struct pid_namespace *ns)
 
 void pid_ns_release_proc(struct pid_namespace *ns)
 {
-	mntput(ns->proc_mnt);
+	kern_unmount(ns->proc_mnt);
 }
#2 lore raw
Quoted 6 lines · Al Viro
Quoted 5 lines · Vasiliy Kulikov

proc_pid_permission() doesn't put task_struct on every /proc/$pid/ access. A demo from Hugh Dickins:

while :; do ps; grep KernelStack /proc/meminfo; sleep 1; done

Quoted 7 lines
Quoted 4 lines

---
This is a patch against a hidepid patchset from -mm.

Choose saner commit summary, please. It's not information leak, for pity sake
- it's a plain and simple memory leak...

Oops! s/infoleak/memleak/ surely, bad habit...

Thank you, I'll resend the patch.

Signature · 2 lines
Vasiliy Kulikov
http://www.openwall.com - bringing security into open computing environments
Tested-by on v1 1/1
#3 lore raw
In reply to Vasiliy Kulikov
Quoted 7 lines · Vasiliy Kulikov

proc_pid_permission() doesn't put task_struct on every /proc/$pid/ access. A demo from Hugh Dickins:

while :; do ps; grep KernelStack /proc/meminfo; sleep 1; done

Thank you, yes, that fixes it for me:

but hopefully akpm will just fold this into the original patch.

Hmm, tiny niggle, but I notice that has_pid_permissions() is declared, reasonably, as bool; so wouldn't it be better for has_perms to be declared as bool instead of int? Hardly worth bothering about, but if you've a mind to respin with a corrected Subject as Al rightly suggests.

Quoted 29 lines

---
This is a patch against a hidepid patchset from -mm.

 fs/proc/base.c |    9 +++++++--
 1 files changed, 7 insertions(+), 2 deletions(-)
fs/proc/base.c +7 -2
index 8caf5cb..0e5c577 100644
@@ -646,9 +646,14 @@ static bool has_pid_permissions(struct pid_namespace *pid,
 static int proc_pid_permission(struct inode *inode, int mask)
 {
 	struct pid_namespace *pid = inode->i_sb->s_fs_info;
-	struct task_struct *task = get_proc_task(inode);
+	struct task_struct *task;
+	int has_perms;
+
+	task = get_proc_task(inode);
+	has_perms = has_pid_permissions(pid, task, 1);
+	put_task_struct(task);
 
-	if (!has_pid_permissions(pid, task, 1)) {
+	if (!has_perms) {
 		if (pid->hide_pid == 2) {
 			/*
 			 * Let's make getdents(), stat(), and open()
Signature · 1 line
1.7.0.4