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

Commit 75521c8e 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 01dafb76
Loading
Loading
Loading
Loading
+17 −27
Original line number Original line Diff line number Diff line
@@ -3093,9 +3093,14 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len,
	send.last = (void *)(buf + len - 1);
	send.last = (void *)(buf + len - 1);
	send.terminate = 1;
	send.terminate = 1;


wait_for_buffer:
	wait_event_interruptible(driver->hdlc_wait_q,
	wait_event_interruptible(driver->hdlc_wait_q,
			(data->flushed == 0));
			(data->flushed == 0));
	spin_lock_irqsave(&driver->diagmem_lock, flags);
	spin_lock_irqsave(&driver->diagmem_lock, flags);
	if (data->flushed) {
		spin_unlock_irqrestore(&driver->diagmem_lock, flags);
		goto wait_for_buffer;
	}
	if (!data->buf) {
	if (!data->buf) {
		data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE +
		data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE +
					APF_DIAG_PADDING,
					APF_DIAG_PADDING,
@@ -3118,19 +3123,7 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len,
			ret = -EIO;
			ret = -EIO;
			goto fail_free_buf;
			goto fail_free_buf;
		}
		}
		wait_event_interruptible(driver->hdlc_wait_q,
		goto wait_for_buffer;
			(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;
	}
	}


	enc.dest = data->buf + data->len;
	enc.dest = data->buf + data->len;
@@ -3152,9 +3145,14 @@ static int diag_process_apps_data_hdlc(unsigned char *buf, int len,
			ret = -EIO;
			ret = -EIO;
			goto fail_free_buf;
			goto fail_free_buf;
		}
		}
wait_for_agg_buff:
		wait_event_interruptible(driver->hdlc_wait_q,
		wait_event_interruptible(driver->hdlc_wait_q,
			(data->flushed == 0));
			(data->flushed == 0));
		spin_lock_irqsave(&driver->diagmem_lock, flags);
		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 +
		data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE +
					APF_DIAG_PADDING,
					APF_DIAG_PADDING,
					 POOL_TYPE_HDLC);
					 POOL_TYPE_HDLC);
@@ -3224,9 +3222,14 @@ static int diag_process_apps_data_non_hdlc(unsigned char *buf, int len,
		       __func__, buf, len);
		       __func__, buf, len);
		return -EIO;
		return -EIO;
	}
	}
wait_for_buffer:
	wait_event_interruptible(driver->hdlc_wait_q,
	wait_event_interruptible(driver->hdlc_wait_q,
			(data->flushed == 0));
			(data->flushed == 0));
	spin_lock_irqsave(&driver->diagmem_lock, flags);
	spin_lock_irqsave(&driver->diagmem_lock, flags);
	if (data->flushed) {
		spin_unlock_irqrestore(&driver->diagmem_lock, flags);
		goto wait_for_buffer;
	}
	if (!data->buf) {
	if (!data->buf) {
		data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE +
		data->buf = diagmem_alloc(driver, DIAG_MAX_HDLC_BUF_SIZE +
					APF_DIAG_PADDING,
					APF_DIAG_PADDING,
@@ -3248,20 +3251,7 @@ static int diag_process_apps_data_non_hdlc(unsigned char *buf, int len,
			ret = -EIO;
			ret = -EIO;
			goto fail_free_buf;
			goto fail_free_buf;
		}
		}
		wait_event_interruptible(driver->hdlc_wait_q,
		goto wait_for_buffer;
			(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;
	}
	}


	header.start = CONTROL_CHAR;
	header.start = CONTROL_CHAR;