[ltp] WARNING: security hole in thinkpad-acpi and ibm-acpi kernel modules

Henrique de Moraes Holschuh linux-thinkpad@linux-thinkpad.org
Tue, 21 Jul 2009 14:14:32 -0300


--MfFXiAuoTsnnDAfZ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

See attached patch and analysis.

Considerations:

Nobody has tried to write a exploit for this bug yet, but it does seem like
it is exploitable.

By default, /proc/acpi/ibm/* can only be written to by root, and thus the
bug would only matter if it allows a restricted root user (say, on a SELinux
system) to do more damage.

HOWEVER, it is entirely possible that either distro scripts, or local admin
scripts (running as root) could change the permissions on /proc/acpi/ibm/*
to allow for less restricted write access.  In that case, the bug can be
triggered by non-root users, and thus there is a chance it can be used to
escalate priviledges.

If you give write access to any local accounts (other than root) to any file
under /proc/acpi/ibm, you are at risk of a local root exploit.  You have
been warned.

Please either apply the attached patch (which fixes the security hole for
good), or at least make sure /proc/acpi/ibm/* is only writable by root.

While at it, please make sure to *disable* CONFIG_THINKPAD_ACPI_BAY and
CONFIG_THINKPAD_ACPI_DOCK on your kernel configuration for kernels after
2.6.24, as they can cause a NULL-pointer derreference when the dock or bay
is manipulated, and there is a possibility that it could be exploited for
priviledge escalation depending on the kernel and local configuration.

-- 
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh

--MfFXiAuoTsnnDAfZ
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment; filename="fix-thinkpadacpi-procfs.patch"

Patch by Michael Buesch <mb@bu3sch.de>

thinkpad-acpi: Avoid heap buffer overrun

Avoid a heap buffer overrun triggered by an integer overflow of the userspace
controlled "count" variable.
If userspace passes in a "count" of (size_t)-1l, the kmalloc size will overflow
to ((size_t)-1l + 2) = 1, so only one byte will be allocated. However, copy_from_user()
will attempt to copy 0xFFFFFFFF (or 0xFFFFFFFFFFFFFFFF on 64bit) bytes to the buffer.

A possible testcase could look like this:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char **argv)
{
	int fd;
	char c;

	if (argc != 2) {
		printf("Usage: %s /proc/acpi/ibm/filename\n", argv[0]);
		return 1;
	}
	fd = open(argv[1], O_RDWR);
	if (fd < 0) {
		printf("Could not open proc file\n");
		return 1;
	}
	write(fd, &c, (size_t)-1l);
}

We avoid the integer overrun by putting an arbitrary limit on the count.
PAGE_SIZE sounds like a sane limit.

Signed-off-by: Michael Buesch <mb@bu3sch.de>

---

This patch is completely untested due to lack of supported device.
The proc file is only writeable by root, so it's probably not exploitable as-is.

---
 drivers/platform/x86/thinkpad_acpi.c |    2 ++
 1 file changed, 2 insertions(+)

--- linux-2.6.orig/drivers/platform/x86/thinkpad_acpi.c
+++ linux-2.6/drivers/platform/x86/thinkpad_acpi.c
@@ -777,20 +777,22 @@ static int dispatch_procfs_read(char *pa
 static int dispatch_procfs_write(struct file *file,
 			const char __user *userbuf,
 			unsigned long count, void *data)
 {
 	struct ibm_struct *ibm = data;
 	char *kernbuf;
 	int ret;
 
 	if (!ibm || !ibm->write)
 		return -EINVAL;
+	if (count > PAGE_SIZE - 2)
+		return -EINVAL;
 
 	kernbuf = kmalloc(count + 2, GFP_KERNEL);
 	if (!kernbuf)
 		return -ENOMEM;
 
 	if (copy_from_user(kernbuf, userbuf, count)) {
 		kfree(kernbuf);
 		return -EFAULT;
 	}
 

--MfFXiAuoTsnnDAfZ--