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

Commit ceb252e1 authored by Hardik Arya's avatar Hardik Arya Committed by Gerrit - the friendly Code Review server
Browse files

diag: Check buffer flush status before processing



There is a possibility of race condition between
drain_apps_data and process_apps_data for flushing
the apps data buffer to mux, Which can cause flushing
buffer twice and can lead to use-after-free issue.
The patch adds checks for buffer flush status before
using the same buffer for processing apps data.

Change-Id: I2cfe67304e73bcb4004884b986ac2bec44b29ba1
Signed-off-by: default avatarHardik Arya <harya@codeaurora.org>
parent 62c8720d
Loading
Loading
Loading
Loading
+17 −27
Original line number Diff line number Diff line
@@ -3079,9 +3079,14 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len,
	send.last = (void *)(buf + len - 1);
	send.terminate = 1;

wait_for_buffer:
	wait_event_interruptible(driver->hdlc_wait_q,
			(data->flushed == 0));
	spin_lock_irqsave(&driver->diagmem_lock, flags);
	if (data->flushed) {
		spin_unlock_irqrestore(&driver->diagmem_lock, flags);
		goto wait_for_buffer;
	}
	if (!data->buf) {
		data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE +
					APF_DIAG_PADDING,
@@ -3104,19 +3109,7 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len,
			ret = -EIO;
			goto fail_free_buf;
		}
		wait_event_interruptible(driver->hdlc_wait_q,
			(data->flushed == 0));
		spin_lock_irqsave(&driver->diagmem_lock, flags);
		data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE +
					APF_DIAG_PADDING,
					  POOL_TYPE_HDLC);
		if (!data->buf) {
			ret = PKT_DROP;
			spin_unlock_irqrestore(&driver->diagmem_lock, flags);
			goto fail_ret;
		}
		data->allocated = 1;
		data->flushed = 0;
		goto wait_for_buffer;
	}

	enc.dest = data->buf + data->len;
@@ -3138,9 +3131,14 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len,
			ret = -EIO;
			goto fail_free_buf;
		}
wait_for_agg_buff:
		wait_event_interruptible(driver->hdlc_wait_q,
			(data->flushed == 0));
		spin_lock_irqsave(&driver->diagmem_lock, flags);
		if (data->flushed) {
			spin_unlock_irqrestore(&driver->diagmem_lock, flags);
			goto wait_for_agg_buff;
		}
		data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE +
					APF_DIAG_PADDING,
					 POOL_TYPE_HDLC);
@@ -3210,9 +3208,14 @@ static int diag_process_apps_data_non_hdlc(unsigned char *buf, int len,
		       __func__, buf, len);
		return -EIO;
	}
wait_for_buffer:
	wait_event_interruptible(driver->hdlc_wait_q,
			(data->flushed == 0));
	spin_lock_irqsave(&driver->diagmem_lock, flags);
	if (data->flushed) {
		spin_unlock_irqrestore(&driver->diagmem_lock, flags);
		goto wait_for_buffer;
	}
	if (!data->buf) {
		data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE +
					APF_DIAG_PADDING,
@@ -3234,20 +3237,7 @@ static int diag_process_apps_data_non_hdlc(unsigned char *buf, int len,
			ret = -EIO;
			goto fail_free_buf;
		}
		wait_event_interruptible(driver->hdlc_wait_q,
			(data->flushed == 0));

		spin_lock_irqsave(&driver->diagmem_lock, flags);
		data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE +
					APF_DIAG_PADDING,
					  POOL_TYPE_HDLC);
		if (!data->buf) {
			ret = PKT_DROP;
			spin_unlock_irqrestore(&driver->diagmem_lock, flags);
			goto fail_ret;
		}
		data->allocated = 1;
		data->flushed = 0;
		goto wait_for_buffer;
	}

	header.start = CONTROL_CHAR;