ACPI: fix acpi fan state set error
Yi Yang [Sat, 14 Jun 2008 04:52:06 +0000 (00:52 -0400)]
Under /proc/acpi, there is a fan control interface, a user can
set 0 or 3 to /proc/acpi/fan/*/state, 0 denotes D0 state, 3
denotes D3 state, but in current implementation, a user can
set a fan to D1 state by any char excluding '1', '2' and '3'.

For example:

[root@localhost acpi]# cat /proc/acpi/fan/C31B/state
status:                  off
[root@localhost acpi]# echo "" > /proc/acpi/fan/C31B/state
[root@localhost acpi]# cat /proc/acpi/fan/C31B/state
status:                  on
[root@localhost acpi]# echo "3" > /proc/acpi/fan/C31B/state
[root@localhost acpi]# cat /proc/acpi/fan/C31B/state
status:                  off
[root@localhost acpi]# echo "xxxxx" > /proc/acpi/fan/C31B/state
[root@localhost acpi]# cat /proc/acpi/fan/C31B/state
status:                  on

Obviously, such inputs as "" and "xxxxx" are invalid for fan state.

This patch fixes this issue, it strictly limits fan state only to
accept 0, 1, 2 and 3, any other inputs are invalid.

Before applying this patch, the test result is:

[root@localhost acpi]# cat /proc/acpi/fan/C31B/state
status:                  off
[root@localhost acpi]# echo "" > /proc/acpi/fan/C31B/state
[root@localhost acpi]# cat /proc/acpi/fan/C31B/state
status:                  on
[root@localhost acpi]# echo "3" > /proc/acpi/fan/C31B/state
[root@localhost acpi]# cat /proc/acpi/fan/C31B/state
status:                  off
[root@localhost acpi]# echo "xxxxx" > /proc/acpi/fan/C31B/state
[root@localhost acpi]# cat /proc/acpi/fan/C31B/state
status:                  on
[root@localhost acpi]# echo "3" > /proc/acpi/fan/C31B/state
[root@localhost acpi]# cat /proc/acpi/fan/C31B/state
status:                  off
[root@localhost acpi]# echo "3x" > /proc/acpi/fan/C31B/state
[root@localhost acpi]# cat /proc/acpi/fan/C31B/state
status:                  off
[root@localhost acpi]# echo "-1x" > /proc/acpi/fan/C31B/state
[root@localhost acpi]# cat /proc/acpi/fan/C31B/state
status:                  on
[root@localhost acpi]#

After applying this patch, the test result is:

[root@localhost ~]# cat /proc/acpi/fan/C31B/state
status:                  off
[root@localhost ~]# echo "" > /proc/acpi/fan/C31B/state
-bash: echo: write error: Invalid argument
[root@localhost ~]# cat /proc/acpi/fan/C31B/state
status:                  off
[root@localhost ~]# echo "3" > /proc/acpi/fan/C31B/state
[root@localhost ~]# cat /proc/acpi/fan/C31B/state
status:                  off
[root@localhost ~]# echo "xxxxx" > /proc/acpi/fan/C31B/state
-bash: echo: write error: Invalid argument
[root@localhost ~]# cat /proc/acpi/fan/C31B/state
status:                  off
[root@localhost ~]# echo "-1x" > /proc/acpi/fan/C31B/state
-bash: echo: write error: Invalid argument
[root@localhost ~]# cat /proc/acpi/fan/C31B/state
status:                  off
[root@localhost ~]# echo "0" > //proc/acpi/fan/C31B/state
[root@localhost ~]# cat /proc/acpi/fan/C31B/state
status:                  on
[root@localhost ~]# echo "4" > //proc/acpi/fan/C31B/state
-bash: echo: write error: Invalid argument
[root@localhost ~]# cat /proc/acpi/fan/C31B/state
status:                  on
[root@localhost ~]# echo "3" > //proc/acpi/fan/C31B/state
[root@localhost ~]# cat /proc/acpi/fan/C31B/state
status:                  off
[root@localhost ~]# echo "0" > //proc/acpi/fan/C31B/state
[root@localhost ~]# cat /proc/acpi/fan/C31B/state
status:                  on
[root@localhost ~]# echo "3x" > //proc/acpi/fan/C31B/state
-bash: echo: write error: Invalid argument
[root@localhost ~]#

Signed-off-by: Yi Yang <yi.y.yang@intel.com>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Acked-by: Zhang Rui <rui.zhang@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>

drivers/acpi/fan.c

index 6cf10cb..55c17af 100644 (file)
@@ -148,7 +148,7 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
        int result = 0;
        struct seq_file *m = file->private_data;
        struct acpi_device *device = m->private;
-       char state_string[12] = { '\0' };
+       char state_string[3] = { '\0' };
 
        if (count > sizeof(state_string) - 1)
                return -EINVAL;
@@ -157,6 +157,12 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
                return -EFAULT;
 
        state_string[count] = '\0';
+       if ((state_string[0] < '0') || (state_string[0] > '3'))
+               return -EINVAL;
+       if (state_string[1] == '\n')
+               state_string[1] = '\0';
+       if (state_string[1] != '\0')
+               return -EINVAL;
 
        result = acpi_bus_set_power(device->handle,
                                    simple_strtoul(state_string, NULL, 0));