Subject: ACPI: fix processor limit set error
From: Yi Yang <yi.y.yang@intel.com>
when echo some invalid values to /proc/acpi/processor/CPU*/limit,
it doesn't return any error info, on the contrary, it successes
and sets some other values, for example:
[root@localhost /]# echo "0:0A" >/proc/acpi/processor/CPU0/limit
[root@localhost /]# cat /proc/acpi/processor/CPU0/limit
active limit: P0:T0
user limit: P0:T0
thermal limit: P0:T0
[root@localhost /]# echo "0:0F" >/proc/acpi/processor/CPU0/limit
[root@localhost /]# cat /proc/acpi/processor/CPU0/limit
active limit: P0:T0
user limit: P0:T0
thermal limit: P0:T0
[root@localhost /]# echo "0:0 0:1 0:2" >/proc/acpi/processor/CPU0/limit
[root@localhost /]# cat /proc/acpi/processor/CPU0/limit
active limit: P0:T0
user limit: P0:T0
thermal limit: P0:T0
[root@localhost /]#
A correct way is that it should fail and return error info.
This patch fixed this issue, it accepts not only such inputs as "*:*",
but also accepts such inputs as "p*:t*" or "P*:T*" or "p*:*" or "*:t*",
the former "*" in inputs means the allowed processor performance state,
currently it is only a stub and not set to the processor limit data
structure, the latter "*" means the allowed processor throttling state
which rages from 0 to 7 generally. This patch strictly limits inputs to
meet the above conditions, any input which can't meet the above conditions
is considered as invalid input.
Before applying this patch, the test result is below:
[root@localhost /]# echo "0:0A" >/proc/acpi/processor/CPU0/limit
[root@localhost /]# cat /proc/acpi/processor/CPU0/limit
active limit: P0:T0
user limit: P0:T0
thermal limit: P0:T0
[root@localhost /]# echo "0:0F" >/proc/acpi/processor/CPU0/limit
[root@localhost /]# cat /proc/acpi/processor/CPU0/limit
active limit: P0:T0
user limit: P0:T0
thermal limit: P0:T0
[root@localhost /]# echo "10:2F" >/proc/acpi/processor/CPU0/limit
[root@localhost /]# cat /proc/acpi/processor/CPU0/limit
active limit: P0:T2
user limit: P0:T2
thermal limit: P0:T0
[root@localhost /]# echo "0:0 0:1 0:2" >/proc/acpi/processor/CPU0/limit
[root@localhost /]# cat /proc/acpi/processor/CPU0/limit
active limit: P0:T0
user limit: P0:T0
thermal limit: P0:T0
[root@localhost /]#
After applying this patch, the test result is below:
[root@localhost ~]# cat /proc/acpi/processor/CPU0/limit
active limit: P0:T0
user limit: P0:T0
thermal limit: P0:T0
[root@localhost ~]# echo "0:0A" > /proc/acpi/processor/CPU0/limit
-bash: echo: write error: Invalid argument
[root@localhost ~]# echo "0:0F" > /proc/acpi/processor/CPU0/limit
-bash: echo: write error: Invalid argument
[root@localhost ~]# echo "P0:T1" > /proc/acpi/processor/CPU0/limit
[root@localhost ~]# cat /proc/acpi/processor/CPU0/limit
active limit: P0:T1
user limit: P0:T1
thermal limit: P0:T0
[root@localhost ~]# echo "p0:t1" > /proc/acpi/processor/CPU0/limit
[root@localhost ~]# cat /proc/acpi/processor/CPU0/limit
active limit: P0:T1
user limit: P0:T1
thermal limit: P0:T0
[root@localhost ~]# echo "p0:x1" > /proc/acpi/processor/CPU0/limit
-bash: echo: write error: Invalid argument
[root@localhost ~]# echo "q0:x1" > /proc/acpi/processor/CPU0/limit
-bash: echo: write error: Invalid argument
[root@localhost ~]# echo "p0:1" > /proc/acpi/processor/CPU0/limit
[root@localhost ~]# echo "q0:x1" > /proc/acpi/processor/CPU0/limit
-bash: echo: write error: Invalid argument
[root@localhost ~]# cat /proc/acpi/processor/CPU0/limit
active limit: P0:T1
user limit: P0:T1
thermal limit: P0:T0
[root@localhost ~]# echo "0:t1" > /proc/acpi/processor/CPU0/limit
[root@localhost ~]# cat /proc/acpi/processor/CPU0/limit
active limit: P0:T1
user limit: P0:T1
thermal limit: P0:T0
[root@localhost ~]# echo "0:t1F" > /proc/acpi/processor/CPU0/limit
-bash: echo: write error: Invalid argument
[root@localhost ~]# echo "" > /proc/acpi/processor/CPU0/limit
-bash: echo: write error: Invalid argument
[root@localhost ~]# echo "0:0 0:0 0:2 " > /proc/acpi/processor/CPU0/limit
-bash: echo: write error: Invalid argument
[root@localhost ~]# echo "P0:T1" > /proc/acpi/processor/CPU0/limit
[root@localhost ~]# cat /proc/acpi/processor/CPU0/limit
active limit: P0:T1
user limit: P0:T1
thermal limit: P0:T0
[root@localhost ~]#
Signed-off-by: Yi Yang <yi.y.yang@intel.com>
---
processor_thermal.c | 42 +++++++++++++++++++++++++++++++-----------
1 file changed, 31 insertions(+), 11 deletions(-)
diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c
index 06e6f3f..262d56e 100644
--- a/drivers/acpi/processor_thermal.c
+++ b/drivers/acpi/processor_thermal.c
@@ -349,9 +349,11 @@ static ssize_t acpi_processor_write_limit(struct file * file,
int result = 0;
struct seq_file *m = file->private_data;
struct acpi_processor *pr = m->private;
- char limit_string[25] = { '\0' };
+ char limit_string[10] = "";
int px = 0;
int tx = 0;
+ char *tmpp = NULL;
+ char tmpstring[10] = "";
if (!pr || (count > sizeof(limit_string) - 1)) {
@@ -363,21 +365,39 @@ static ssize_t acpi_processor_write_limit(struct file * file,
}
limit_string[count] = '\0';
+ if ((count > 0) && (limit_string[count-1] == '\n'))
+ limit_string[count-1] = '\0';
- if (sscanf(limit_string, "%d:%d", &px, &tx) != 2) {
- printk(KERN_ERR PREFIX "Invalid data format\n");
+ tmpp = memchr(limit_string, ':', count);
+ if (tmpp == NULL)
+ return -EINVAL;
+
+ *tmpp = '\0';
+ tmpp = limit_string;
+ if ((limit_string[0] == 'p') || (limit_string[0] == 'P'))
+ tmpp++;
+ px = simple_strtoul(tmpp, NULL, 0);
+ snprintf(tmpstring, 10, "%d", px);
+ if (strcmp(tmpp, tmpstring) != 0)
+ return -EINVAL;
+
+ tmpp += strlen(tmpp) + 1;
+ if ((tmpp[0] == 't') || (tmpp[0] == 'T'))
+ tmpp++;
+ tx = simple_strtoul(tmpp, NULL, 0);
+ if (tx > (pr->throttling.state_count - 1))
+ return -EINVAL;
+ snprintf(tmpstring, 10, "%d", tx);
+ if (strcmp(tmpp, tmpstring) != 0)
return -EINVAL;
- }
if (pr->flags.throttling) {
- if ((tx < 0) || (tx > (pr->throttling.state_count - 1))) {
- printk(KERN_ERR PREFIX "Invalid tx\n");
- return -EINVAL;
- }
pr->limit.user.tx = tx;
- }
-
- result = acpi_processor_apply_limit(pr);
+ result = acpi_processor_apply_limit(pr);
+ if (result != 0)
+ return result;
+ } else
+ return -ENODEV;
return count;
}
--
| Greg KH | [GIT PATCH] driver core patches against 2.6.24 |
| Bart Van Assche | Integration of SCST in the mainstream Linux kernel |
| Riki Oktarianto | [PATCH] Add quirk to set AHCI mode on ICH boards |
| Alex Chiang | [PATCH v5 00/16] PCI: let the core manage slot names |
git: | |
| Sam Song | Fwd: [OT] Re: Git via a proxy server? |
| Toby White | Using Filemerge.app as a git-diff viewer |
| Sam Vilain | [PATCH] git-mergetool: add support for ediff |
| Adrian Bunk | git-revert is a memory hog |
| Marcos Laufer | dmesg IBM x3650 OpenBSD 4.3 |
| Stephan A. Rickauer | Re: New tcp stack attack |
| Richard Stallman | Real men don't attack straw men |
| Ondřej Surý | openbgp not exporing ipv6 to routing tables |
| Michael Chan | [PATCH net-next 2/6] bnx2: Check netif_running() in all ethtool operations. |
| Herbert Xu | Re: xfrm_state locking regression... |
| adobriyan | [PATCH 10/38] netns ct: per-netns expectations |
| Dale Farnsworth | Re: [PATCH 01/39] mv643xx_eth: reverse topological sort of functions |
| How to make my PCIE ATA storage device running in Linux | 8 hours ago | Linux general |
| sata/ide timeout errors on asus server-mb | 11 hours ago | Linux kernel |
| Shared swap partition | 12 hours ago | Linux general |
| usb mic not detected | 16 hours ago | Applications and Utilities |
| Problem in Inserting a module | 17 hours ago | Linux kernel |
| Treason Uncloaked | 22 hours ago | Linux kernel |
| high memory | 3 days ago | Linux kernel |
| semaphore access speed | 3 days ago | Applications and Utilities |
| the kernel how to power off the machine | 3 days ago | Linux kernel |
| Easter Eggs in windows XP | 3 days ago | Windows |
