--- la-2.6.8.1/drivers/acpi/pcc_acpi.c 2004-08-22 11:05:27.000000000 -0700 +++ linux-2.6.8.1/drivers/acpi/pcc_acpi.c 2004-08-22 13:30:54.000000000 -0700 @@ -20,9 +20,15 @@ *--------------------------------------------------------------------------- * * ChangeLog: - * Aug.21, 2004 David Bronaugh - * - v0.6.1 Fix a silly error with status checking - * Aug.20, 2004 David Bronaugh + * Aug.22, 2004 David Bronaugh + * -v0.6.2 Add check on ACPI data (num_sifr) + * Coding style cleanups, better error messages/handling + * Fixed an off-by-one error in memory allocation + * + * Aug.21, 2004 David Bronaugh + * -v0.6.1 Fix a silly error with status checking + * + * Aug.20, 2004 David Bronaugh * - v0.6 Correct brightness controls to reflect reality * based on information gleaned by Hiroshi Miura * and discussions with Hiroshi Miura @@ -46,7 +52,7 @@ * */ -#define ACPI_PCC_VERSION "0.6.1" +#define ACPI_PCC_VERSION "0.6.2" #include #include @@ -162,7 +168,7 @@ if (ACPI_FAILURE(status)) { printk(KERN_INFO LOGPREFIX "acpi evaluate error on %s\n", methodName); - return (-EFAULT); + return -EFAULT; } if (out_objs[0].type == ACPI_TYPE_INTEGER) { @@ -213,12 +219,21 @@ * destination so that sscanf can be used on it safely. */ tmp_buffer = kmalloc(count + 1, GFP_KERNEL); + if (!tmp_buffer) { + printk(KERN_INFO LOGPREFIX "dispatch_write: Couldn't allocate buffer"); + return -EFAULT; + } + if (copy_from_user(tmp_buffer, buffer, count)) { + printk(KERN_INFO LOGPREFIX "dispatch_write: Couldn't copy data from userspace"); result = -EFAULT; - } else { - tmp_buffer[count] = 0; - result = item->write_func(tmp_buffer, count); + goto end; } + + tmp_buffer[count] = 0; + result = item->write_func(tmp_buffer, count); + +end: kfree(tmp_buffer); return result; } @@ -236,7 +251,6 @@ "evaluation error HKEY.SQTY\n")); return -EINVAL; } - } static int acpi_pcc_retrieve_biosdata(u32* sinf) @@ -270,8 +284,9 @@ union acpi_object *element = &(hkey->package.elements[i]); if (likely(element->type == ACPI_TYPE_INTEGER)) { sinf[i] = element->integer.value; - } else + } else { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF data\n")); + } } sinf[hkey->package.count] = -1; @@ -282,9 +297,9 @@ static char* acpi_pcc_read_sinf_field(char* p, int field) { - u32* sinf; + u32* sinf = kmalloc(sizeof(u32) * (num_sifr + 1), GFP_KERNEL); - if (!(sinf = kmalloc(sizeof(u32) * num_sifr, GFP_KERNEL))) { + if (!sinf) { printk(KERN_INFO LOGPREFIX "Couldn't allocate %i bytes\n", sizeof(u32) * num_sifr); return p; @@ -369,9 +384,9 @@ int cur_index) { u32 bright; - u32* sinf; + u32* sinf = kmalloc(sizeof(u32) * (num_sifr + 1), GFP_KERNEL); - if (!(sinf = kmalloc(sizeof(u32) * num_sifr, GFP_KERNEL))) { + if (!sinf) { printk(KERN_INFO LOGPREFIX "Couldn't allocate %i bytes\n", sizeof(u32) * num_sifr); return count; @@ -421,7 +436,6 @@ return p; } - /* hotkey driver */ static int acpi_pcc_hotkey_get_key(struct acpi_hotkey *hotkey) { @@ -438,14 +452,10 @@ return (status); } -void -acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data) +void acpi_pcc_hotkey_notify(acpi_handle handle, u32 event, void *data) { struct acpi_hotkey *hotkey = (struct acpi_hotkey *) data; - if (!hotkey || !hotkey->device) - return; - switch(event) { case HKEY_NOTIFY: if (acpi_pcc_hotkey_get_key(hotkey)) { @@ -475,11 +485,11 @@ { "dc_brightness_max" , acpi_pcc_read_dc_max_brightness, NULL }, { "dc_brightness_min" , acpi_pcc_read_dc_min_brightness, NULL }, { "dc_brightness" , acpi_pcc_read_dc_brightness, - acpi_pcc_write_dc_brightness}, - { "mute", acpi_pcc_read_mute, acpi_pcc_write_mute}, - { "version", acpi_pcc_read_version , NULL}, + acpi_pcc_write_dc_brightness }, + { "mute", acpi_pcc_read_mute, acpi_pcc_write_mute }, + { "version", acpi_pcc_read_version , NULL }, { "environment_state", acpi_pcc_read_env_state, NULL }, - { NULL , NULL , NULL}, + { NULL , NULL , NULL }, }; static acpi_status __init add_device(ProcItem *proc_items, @@ -504,20 +514,22 @@ } } - return(AE_OK); + return AE_OK; } - static int __init acpi_pcc_proc_init(void) { acpi_status status = AE_OK; + acpi_pcc_dir = proc_mkdir(PROC_PCC, acpi_root_dir); - if (unlikely(!(acpi_pcc_dir = proc_mkdir(PROC_PCC, acpi_root_dir)))) + if (unlikely(!acpi_pcc_dir)) { + printk(KERN_INFO LOGPREFIX "Couldn't create dir in /proc\n"); return -ENODEV; + } acpi_pcc_dir->owner = THIS_MODULE; status = add_device(pcc_proc_items, acpi_pcc_dir); - if (ACPI_FAILURE(status)){ + if (ACPI_FAILURE(status)) { remove_proc_entry(PROC_PCC, acpi_root_dir); return -ENODEV; } @@ -530,12 +542,12 @@ { ProcItem* item; - for (item = proc_items; item->name; ++item) + for (item = proc_items; item->name; ++item) { remove_proc_entry(item->name, proc_entry); + } return(AE_OK); } - static int acpi_pcc_hotkey_add (struct acpi_device *device) { acpi_status status = AE_OK; @@ -543,12 +555,22 @@ ACPI_FUNCTION_TRACE("acpi_pcc_hotkey_add"); - if (!device) + if (!device) { return_VALUE(-EINVAL); + } + + num_sifr = acpi_pcc_get_sqty(); + + if (num_sifr > 255) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "num_sifr too large")); + return_VALUE(-ENODEV); + } hotkey = kmalloc(sizeof(struct acpi_hotkey), GFP_KERNEL); - if (!hotkey) + if (!hotkey) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Couldn't allocate mem for hotkey")); return_VALUE(-ENOMEM); + } memset(hotkey, 0, sizeof(struct acpi_hotkey)); @@ -570,8 +592,6 @@ return_VALUE(-ENODEV); } - num_sifr = acpi_pcc_get_sqty(); - acpi_pcc_proc_init(); return_VALUE(0); @@ -601,7 +621,6 @@ ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Error removing notify handler\n")); kfree(hotkey); - return_VALUE(status == AE_OK); } @@ -611,8 +630,9 @@ ACPI_FUNCTION_TRACE("acpi_pcc_init"); - if (acpi_disabled) + if (acpi_disabled) { return_VALUE(-ENODEV); + } result = acpi_bus_register_driver(&acpi_hotkey_driver); if (ACPI_FAILURE(result)) {