Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 142f8b84 authored by Manoj Prabhu B's avatar Manoj Prabhu B
Browse files

diag: Prevent resource leakage while copying to userspace



Possibility of resource leakage while checking for validity of
pid and its task structures is prevented by proper update of pid
reference count.

Change-Id: Ifb38f91a5c3e45248bb08c5341c8a3095585c16f
Signed-off-by: default avatarManoj Prabhu B <bmanoj@codeaurora.org>
parent 38ae0c3a
Loading
Loading
Loading
Loading
+36 −14
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/sched.h>
#include <linux/sched/task.h>
#include <linux/ratelimit.h>
#include <linux/workqueue.h>
#include <linux/diagchar.h>
@@ -330,7 +331,10 @@ int diag_md_copy_to_user(char __user *buf, int *pret, size_t buf_size,
	int peripheral = 0;
	struct diag_md_session_t *session_info = NULL;
	struct pid *pid_struct = NULL;
	struct task_struct *task_s = NULL;

	if (!info)
		return -EINVAL;
	for (i = 0; i < NUM_DIAG_MD_DEV && !err; i++) {
		ch = &diag_md[i];
		if (!ch->md_info_inited)
@@ -353,11 +357,11 @@ int diag_md_copy_to_user(char __user *buf, int *pret, size_t buf_size,
			if (!session_info)
				goto drop_data;

			if (session_info && info &&
			if (session_info &&
				(session_info->pid != info->pid))
				continue;
			if ((info && (info->peripheral_mask[i] &
			    MD_PERIPHERAL_MASK(peripheral)) == 0))
			if ((info->peripheral_mask[i] &
			    MD_PERIPHERAL_MASK(peripheral)) == 0)
				goto drop_data;
			pid_struct = find_get_pid(session_info->pid);
			if (!pid_struct) {
@@ -386,35 +390,45 @@ int diag_md_copy_to_user(char __user *buf, int *pret, size_t buf_size,
			}
			if (i > 0) {
				remote_token = diag_get_remote(i);
				if (get_pid_task(pid_struct, PIDTYPE_PID)) {
				task_s = get_pid_task(pid_struct, PIDTYPE_PID);
				if (task_s) {
					err = copy_to_user(buf + ret,
							&remote_token,
							sizeof(int));
					if (err)
					if (err) {
						put_task_struct(task_s);
						goto drop_data;
					}
					ret += sizeof(int);
					put_task_struct(task_s);
				}
			}

			task_s = get_pid_task(pid_struct, PIDTYPE_PID);
			if (task_s) {

				/* Copy the length of data being passed */
			if (get_pid_task(pid_struct, PIDTYPE_PID)) {
				err = copy_to_user(buf + ret,
						(void *)&(entry->len),
						sizeof(int));
				if (err)
				if (err) {
					put_task_struct(task_s);
					goto drop_data;
				ret += sizeof(int);
				}
				ret += sizeof(int);

				/* Copy the actual data being passed */
			if (get_pid_task(pid_struct, PIDTYPE_PID)) {
				err = copy_to_user(buf + ret,
						(void *)entry->buf,
						entry->len);
				if (err)
				if (err) {
					put_task_struct(task_s);
					goto drop_data;
				}
				ret += entry->len;
				put_task_struct(task_s);
			}

			/*
			 * The data is now copied to the user space client,
			 * Notify that the write is complete and delete its
@@ -432,14 +446,22 @@ int diag_md_copy_to_user(char __user *buf, int *pret, size_t buf_size,
			entry->len = 0;
			entry->ctx = 0;
			spin_unlock_irqrestore(&ch->lock, flags);

			put_pid(pid_struct);
		}
	}

	*pret = ret;
	if (pid_struct && get_pid_task(pid_struct, PIDTYPE_PID)) {
	pid_struct = find_get_pid(info->pid);
	if (pid_struct) {
		task_s = get_pid_task(pid_struct, PIDTYPE_PID);
		if (task_s) {
			err = copy_to_user(buf + sizeof(int),
				(void *)&num_data,
				sizeof(int));
			put_task_struct(task_s);
		}
		put_pid(pid_struct);
	}
	diag_ws_on_copy_complete(DIAG_WS_MUX);
	if (drain_again)