thinkpad-acpi: lock down video output state access
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Fri, 26 Feb 2010 01:22:22 +0000 (22:22 -0300)
committerHenrique de Moraes Holschuh <hmh@hmh.eng.br>
Fri, 26 Feb 2010 01:22:22 +0000 (22:22 -0300)
Given the right combination of ThinkPad and X.org, just reading the
video output control state is enough to hard-crash X.org.

Until the day I somehow find out a model or BIOS cut date to not
provide this feature to ThinkPads that can do video switching through
X RandR, change permissions so that only processes with CAP_SYS_ADMIN
can access any sort of video output control state.

This bug could be considered a local DoS I suppose, as it allows any
non-privledged local user to cause some versions of X.org to
hard-crash some ThinkPads.

Reported-by: Jidanni <jidanni@jidanni.org>
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
Cc: stable@kernel.org
Documentation/laptops/thinkpad-acpi.txt
drivers/platform/x86/Kconfig
drivers/platform/x86/thinkpad_acpi.c

index 75afa1229fd7e72059ffce02b8c450192617e0c7..39c0a09d0105414b1eaba23e4196398be8412332 100644 (file)
@@ -650,6 +650,10 @@ LCD, CRT or DVI (if available). The following commands are available:
        echo expand_toggle > /proc/acpi/ibm/video
        echo video_switch > /proc/acpi/ibm/video
 
+NOTE: Access to this feature is restricted to processes owning the
+CAP_SYS_ADMIN capability for safety reasons, as it can interact badly
+enough with some versions of X.org to crash it.
+
 Each video output device can be enabled or disabled individually.
 Reading /proc/acpi/ibm/video shows the status of each device.
 
index f526e735c5abee0dbfc27936f6b5d7dbc1d22f2d..11fce79b61d1636be6807045e6a900f1b08a1b2a 100644 (file)
@@ -319,9 +319,15 @@ config THINKPAD_ACPI_VIDEO
          server running, phase of the moon, and the current mood of
          Schroedinger's cat.  If you can use X.org's RandR to control
          your ThinkPad's video output ports instead of this feature,
-         don't think twice: do it and say N here to save some memory.
+         don't think twice: do it and say N here to save memory and avoid
+         bad interactions with X.org.
 
-         If you are not sure, say Y here.
+         NOTE: access to this feature is limited to processes with the
+         CAP_SYS_ADMIN capability, to avoid local DoS issues in platforms
+         where it interacts badly with X.org.
+
+         If you are not sure, say Y here but do try to check if you could
+         be using X.org RandR instead.
 
 config THINKPAD_ACPI_HOTKEY_POLL
        bool "Support NVRAM polling for hot keys"
index 3af4628d7dd19c21ad6ee59ae738b4e12551016a..5d02cc06d1a76a165d2234886ba3941d3045c591 100644 (file)
@@ -286,6 +286,7 @@ struct ibm_init_struct {
        char param[32];
 
        int (*init) (struct ibm_init_struct *);
+       mode_t base_procfs_mode;
        struct ibm_struct *data;
 };
 
@@ -4629,6 +4630,10 @@ static int video_read(struct seq_file *m)
                return 0;
        }
 
+       /* Even reads can crash X.org, so... */
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
        status = video_outputsw_get();
        if (status < 0)
                return status;
@@ -4662,6 +4667,10 @@ static int video_write(char *buf)
        if (video_supported == TPACPI_VIDEO_NONE)
                return -ENODEV;
 
+       /* Even reads can crash X.org, let alone writes... */
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
        enable = 0;
        disable = 0;
 
@@ -8487,9 +8496,10 @@ static int __init ibm_init(struct ibm_init_struct *iibm)
                "%s installed\n", ibm->name);
 
        if (ibm->read) {
-               mode_t mode;
+               mode_t mode = iibm->base_procfs_mode;
 
-               mode = S_IRUGO;
+               if (!mode)
+                       mode = S_IRUGO;
                if (ibm->write)
                        mode |= S_IWUSR;
                entry = proc_create_data(ibm->name, mode, proc_dir,
@@ -8680,6 +8690,7 @@ static struct ibm_init_struct ibms_init[] __initdata = {
 #ifdef CONFIG_THINKPAD_ACPI_VIDEO
        {
                .init = video_init,
+               .base_procfs_mode = S_IRUSR,
                .data = &video_driver_data,
        },
 #endif