patch-2.4.22 linux-2.4.22/fs/proc/base.c

Next file: linux-2.4.22/fs/proc/proc_misc.c
Previous file: linux-2.4.22/fs/pipe.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/fs/proc/base.c linux-2.4.22/fs/proc/base.c
@@ -124,20 +124,56 @@
 	return result;
 }
 
+#define MAY_PTRACE(task) \
+	(task == current || \
+	(task->p_pptr == current && \
+	(task->ptrace & PT_PTRACED) && task->state == TASK_STOPPED))
+
+static int may_ptrace_attach(struct task_struct *task)
+{
+	int retval = 0;
+
+	task_lock(task);
+
+	if (((current->uid != task->euid) ||
+	    (current->uid != task->suid) ||
+	    (current->uid != task->uid) ||
+	    (current->gid != task->egid) ||
+	    (current->gid != task->sgid) ||
+	    (!cap_issubset(task->cap_permitted, current->cap_permitted)) ||
+	    (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
+		goto out;
+	rmb();
+	if (!is_dumpable(task) && !capable(CAP_SYS_PTRACE))
+		goto out;
+
+	retval = 1;
+
+out:
+	task_unlock(task);
+	return retval;
+}
+
 static int proc_pid_environ(struct task_struct *task, char * buffer)
 {
 	struct mm_struct *mm;
 	int res = 0;
+
+	if (!may_ptrace_attach(task))
+		return -ESRCH;
+
 	task_lock(task);
 	mm = task->mm;
 	if (mm)
 		atomic_inc(&mm->mm_users);
 	task_unlock(task);
 	if (mm) {
-		int len = mm->env_end - mm->env_start;
+		unsigned int len = mm->env_end - mm->env_start;
 		if (len > PAGE_SIZE)
 			len = PAGE_SIZE;
 		res = access_process_vm(task, mm->env_start, buffer, len, 0);
+		if (!may_ptrace_attach(task))
+			res = -ESRCH;
 		mmput(mm);
 	}
 	return res;
@@ -328,10 +364,6 @@
 	read:		proc_info_read,
 };
 
-#define MAY_PTRACE(p) \
-(p==current||(p->p_pptr==current&&(p->ptrace & PT_PTRACED)&&p->state==TASK_STOPPED))
-
-
 static int mem_open(struct inode* inode, struct file* file)
 {
 	file->private_data = (void*)((long)current->self_exec_id);
@@ -347,8 +379,7 @@
 	int copied = 0;
 	struct mm_struct *mm;
 
-
-	if (!MAY_PTRACE(task))
+	if (!MAY_PTRACE(task) || !may_ptrace_attach(task))
 		return -ESRCH;
 
 	page = (char *)__get_free_page(GFP_USER);
@@ -370,14 +401,13 @@
 		copied = -EIO;
 		goto out_free;
 	}
-		
 
 	while (count > 0) {
 		int this_len, retval;
 
 		this_len = (count > PAGE_SIZE) ? PAGE_SIZE : count;
 		retval = access_process_vm(task, src, page, this_len, 0);
-		if (!retval) {
+		if (!retval || !MAY_PTRACE(task) || !may_ptrace_attach(task)) {
 			if (!copied)
 				copied = -EIO;
 			break;
@@ -411,7 +441,7 @@
 	struct task_struct *task = file->f_dentry->d_inode->u.proc_i.task;
 	unsigned long dst = *ppos;
 
-	if (!MAY_PTRACE(task))
+	if (!MAY_PTRACE(task) || !may_ptrace_attach(task))
 		return -ESRCH;
 
 	page = (char *)__get_free_page(GFP_USER);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)