lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Fri,  6 Nov 2015 23:51:55 +0800
From:	yalin wang <yalin.wang2010@...il.com>
To:	yalin.wang2010@...il.com, gregkh@...uxfoundation.org,
	peter.senna@...il.com, joe@...ches.com, dan.carpenter@...cle.com,
	linux-kernel@...r.kernel.org
Subject: [PATCH] goldfish: fix goldfish_pipe driver BUG

goldfish_pipe_read_write() should pass the buffer's physical
address to qemu, so that host can copy access data correctly,
currently, the drier write a virtual address into address register,
host can not get correct data, then adbd daemon can not work in guest.
Also I comment off access_with_param() function, seems not used,
we don't need use this function in goldfish_pipe_read_write().

Signed-off-by: yalin wang <yalin.wang2010@...il.com>
---
 drivers/platform/goldfish/goldfish_pipe.c | 56 +++++++++++++++++++------------
 1 file changed, 35 insertions(+), 21 deletions(-)

diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c
index 55b6d7c..bdf6f11 100644
--- a/drivers/platform/goldfish/goldfish_pipe.c
+++ b/drivers/platform/goldfish/goldfish_pipe.c
@@ -112,16 +112,27 @@
 #define PIPE_WAKE_READ         (1 << 1)  /* pipe can now be read from */
 #define PIPE_WAKE_WRITE        (1 << 2)  /* pipe can now be written to */
 
+#ifdef CONFIG_64BIT
 struct access_params {
-	unsigned long channel;
-	u32 size;
-	unsigned long address;
-	u32 cmd;
-	u32 result;
+	uint64_t channel;   /* 0x00 */
+	uint32_t size;      /* 0x08 */
+	uint64_t address;   /* 0x0c */
+	uint32_t cmd;       /* 0x14 */
+	uint32_t result;    /* 0x18 */
 	/* reserved for future extension */
-	u32 flags;
+	uint32_t flags;     /* 0x1c */
 };
-
+#else
+struct access_params {
+	uint32_t channel;   /* 0x00 */
+	uint32_t size;      /* 0x04 */
+	uint32_t address;   /* 0x08 */
+	uint32_t cmd;       /* 0x0c */
+	uint32_t result;    /* 0x10 */
+	/* reserved for future extension */
+	uint32_t flags;     /* 0x14 */
+};
+#endif
 /* The global driver data. Holds a reference to the i/o page used to
  * communicate with the emulator, and a wake queue for blocked tasks
  * waiting to be awoken.
@@ -237,6 +248,7 @@ static int setup_access_params_addr(struct platform_device *pdev,
 		return -1;
 }
 
+#if 0
 /* A value that will not be set by qemu emulator */
 #define INITIAL_BATCH_RESULT (0xdeadbeaf)
 static int access_with_param(struct goldfish_pipe_dev *dev, const int cmd,
@@ -263,6 +275,7 @@ static int access_with_param(struct goldfish_pipe_dev *dev, const int cmd,
 	*status = aps->result;
 	return 0;
 }
+#endif
 
 /* This function is used for both reading from and writing to a given
  * pipe.
@@ -304,6 +317,8 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer,
 								 : address_end;
 		unsigned long  avail    = next - address;
 		int status, wakeBit;
+		struct page *page;
+		phys_addr_t phys_addr;
 
 		/* Ensure that the corresponding page is properly mapped */
 		/* FIXME: this isn't safe or sufficient - use get_user_pages */
@@ -323,23 +338,22 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer,
 				break;
 			}
 		}
-
+		if (get_user_pages_unlocked(current, current->active_mm,
+					address, 1, !is_write, 0, &page) != 1)
+			return -EINVAL;
+		phys_addr = page_to_phys(page) + offset_in_page(address);
 		/* Now, try to transfer the bytes in the current page */
 		spin_lock_irqsave(&dev->lock, irq_flags);
-		if (access_with_param(dev, CMD_WRITE_BUFFER + cmd_offset,
-				address, avail, pipe, &status)) {
-			gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
-				     dev->base + PIPE_REG_CHANNEL_HIGH);
-			writel(avail, dev->base + PIPE_REG_SIZE);
-			gf_write_ptr((void *)address,
-				     dev->base + PIPE_REG_ADDRESS,
-				     dev->base + PIPE_REG_ADDRESS_HIGH);
-			writel(CMD_WRITE_BUFFER + cmd_offset,
-					dev->base + PIPE_REG_COMMAND);
-			status = readl(dev->base + PIPE_REG_STATUS);
-		}
+		gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
+			     dev->base + PIPE_REG_CHANNEL_HIGH);
+		writel(avail, dev->base + PIPE_REG_SIZE);
+		gf_write_ptr((void *)phys_addr, dev->base + PIPE_REG_ADDRESS,
+			     dev->base + PIPE_REG_ADDRESS_HIGH);
+		writel(CMD_WRITE_BUFFER + cmd_offset,
+				dev->base + PIPE_REG_COMMAND);
+		status = readl(dev->base + PIPE_REG_STATUS);
 		spin_unlock_irqrestore(&dev->lock, irq_flags);
-
+		put_page(page);
 		if (status > 0) { /* Correct transfer */
 			ret += status;
 			address += status;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ