# This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/06/23 09:08:01-03:00 marcelo@logos.cnet # Al Viro sparse fixes: decnet user pointer dereference # # net/decnet/dn_dev.c # 2004/06/15 23:54:14-03:00 marcelo@logos.cnet +15 -7 # Import patch decnet-fix # diff -Nru a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c --- a/net/decnet/dn_dev.c 2004-06-25 05:11:19 -07:00 +++ b/net/decnet/dn_dev.c 2004-06-25 05:11:19 -07:00 @@ -1061,31 +1061,39 @@ { struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; struct dn_ifaddr *ifa; - struct ifreq *ifr = (struct ifreq *)buf; + char buffer[DN_IFREQ_SIZE]; + struct ifreq *ifr = (struct ifreq *)buffer; + struct sockaddr_dn *addr = (struct sockaddr_dn *)&ifr->ifr_addr; int done = 0; if ((dn_db == NULL) || ((ifa = dn_db->ifa_list) == NULL)) return 0; for(; ifa; ifa = ifa->ifa_next) { - if (!ifr) { + if (!buf) { done += sizeof(DN_IFREQ_SIZE); continue; } if (len < DN_IFREQ_SIZE) return done; - memset(ifr, 0, DN_IFREQ_SIZE); + memset(buffer, 0, DN_IFREQ_SIZE); if (ifa->ifa_label) strcpy(ifr->ifr_name, ifa->ifa_label); else strcpy(ifr->ifr_name, dev->name); - (*(struct sockaddr_dn *) &ifr->ifr_addr).sdn_family = AF_DECnet; - (*(struct sockaddr_dn *) &ifr->ifr_addr).sdn_add.a_len = 2; - (*(dn_address *)(*(struct sockaddr_dn *) &ifr->ifr_addr).sdn_add.a_addr) = ifa->ifa_local; + addr->sdn_family = AF_DECnet; + addr->sdn_add.a_len = 2; + memcpy(addr->sdn_add.a_addr, &ifa->ifa_local, + sizeof(dn_address)); - ifr = (struct ifreq *)((char *)ifr + DN_IFREQ_SIZE); + if (copy_to_user(buf, buffer, DN_IFREQ_SIZE)) { + done = -EFAULT; + break; + } + + buf += DN_IFREQ_SIZE; len -= DN_IFREQ_SIZE; done += DN_IFREQ_SIZE; } # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/06/23 09:09:39-03:00 marcelo@logos.cnet # Al Viro sparse fixes: mpu401 user pointer dereference # # drivers/sound/mpu401.c # 2004/06/16 00:07:29-03:00 marcelo@logos.cnet +28 -11 # Import patch mpu401-fix # diff -Nru a/drivers/sound/mpu401.c b/drivers/sound/mpu401.c --- a/drivers/sound/mpu401.c 2004-06-25 05:15:29 -07:00 +++ b/drivers/sound/mpu401.c 2004-06-25 05:15:29 -07:00 @@ -1513,14 +1513,16 @@ static int mpu_timer_ioctl(int dev, unsigned int command, caddr_t arg) { int midi_dev = sound_timer_devs[dev]->devlink; + int *p = (int *)arg; switch (command) { case SNDCTL_TMR_SOURCE: { int parm; - - parm = *(int *) arg; + + if (get_user(parm, p)) + return -EFAULT; parm &= timer_caps; if (parm != 0) @@ -1532,7 +1534,9 @@ else if (timer_mode & TMR_MODE_SMPTE) mpu_cmd(midi_dev, 0x3d, 0); /* Use SMPTE sync */ } - return (*(int *) arg = timer_mode); + if (put_user(timer_mode, p)) + return -EFAULT; + return timer_mode; } break; @@ -1557,10 +1561,13 @@ { int val; - val = *(int *) arg; + if (get_user(val, p)) + return -EFAULT; if (val) set_timebase(midi_dev, val); - return (*(int *) arg = curr_timebase); + if (put_user(curr_timebase, p)) + return -EFAULT; + return curr_timebase; } break; @@ -1569,7 +1576,8 @@ int val; int ret; - val = *(int *) arg; + if (get_user(val, p)) + return -EFAULT; if (val) { @@ -1584,7 +1592,9 @@ } curr_tempo = val; } - return (*(int *) arg = curr_tempo); + if (put_user(curr_tempo, p)) + return -EFAULT; + return curr_tempo; } break; @@ -1592,18 +1602,25 @@ { int val; - val = *(int *) arg; + if (get_user(val, p)) + return -EFAULT; if (val != 0) /* Can't change */ return -EINVAL; - return (*(int *) arg = ((curr_tempo * curr_timebase) + 30) / 60); + val = (curr_tempo * curr_timebase + 30) / 60; + if (put_user(val, p)) + return -EFAULT; + return val; } break; case SNDCTL_SEQ_GETTIME: - return (*(int *) arg = curr_ticks); + if (put_user(curr_ticks, p)) + return -EFAULT; + return curr_ticks; case SNDCTL_TMR_METRONOME: - metronome_mode = *(int *) arg; + if (get_user(metronome_mode, p)) + return -EFAULT; setup_metronome(midi_dev); return 0; # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/06/23 09:11:47-03:00 marcelo@logos.cnet # Al Viro sparse fixes: msnd user pointer dereference & assorted fixes # # drivers/sound/msnd.c # 2004/06/16 02:42:38-03:00 marcelo@logos.cnet +4 -18 # Import patch msnd-fix # # drivers/sound/msnd.h # 2004/06/16 02:42:26-03:00 marcelo@logos.cnet +2 -2 # Import patch msnd-fix # # drivers/sound/msnd_pinnacle.c # 2004/06/16 02:42:11-03:00 marcelo@logos.cnet +56 -32 # Import patch msnd-fix # diff -Nru a/drivers/sound/msnd.c b/drivers/sound/msnd.c --- a/drivers/sound/msnd.c 2004-06-25 05:15:38 -07:00 +++ b/drivers/sound/msnd.c 2004-06-25 05:15:38 -07:00 @@ -155,13 +155,10 @@ f->len = f->tail = f->head = 0; } -int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len, int user) +int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len) { int count = 0; - if (f->len == f->n) - return 0; - while ((count < len) && (f->len != f->n)) { int nwritten; @@ -177,11 +174,7 @@ nwritten = len - count; } - if (user) { - if (copy_from_user(f->data + f->tail, buf, nwritten)) - return -EFAULT; - } else - isa_memcpy_fromio(f->data + f->tail, (unsigned long) buf, nwritten); + isa_memcpy_fromio(f->data + f->tail, (unsigned long) buf, nwritten); count += nwritten; buf += nwritten; @@ -193,13 +186,10 @@ return count; } -int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len, int user) +int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len) { int count = 0; - if (f->len == 0) - return f->len; - while ((count < len) && (f->len > 0)) { int nread; @@ -215,11 +205,7 @@ nread = len - count; } - if (user) { - if (copy_to_user(buf, f->data + f->head, nread)) - return -EFAULT; - } else - isa_memcpy_toio((unsigned long) buf, f->data + f->head, nread); + isa_memcpy_toio((unsigned long) buf, f->data + f->head, nread); count += nread; buf += nread; diff -Nru a/drivers/sound/msnd.h b/drivers/sound/msnd.h --- a/drivers/sound/msnd.h 2004-06-25 05:15:38 -07:00 +++ b/drivers/sound/msnd.h 2004-06-25 05:15:38 -07:00 @@ -266,8 +266,8 @@ void msnd_fifo_free(msnd_fifo *f); int msnd_fifo_alloc(msnd_fifo *f, size_t n); void msnd_fifo_make_empty(msnd_fifo *f); -int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len, int user); -int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len, int user); +int msnd_fifo_write(msnd_fifo *f, const char *buf, size_t len); +int msnd_fifo_read(msnd_fifo *f, char *buf, size_t len); int msnd_wait_TXDE(multisound_dev_t *dev); int msnd_wait_HC0(multisound_dev_t *dev); diff -Nru a/drivers/sound/msnd_pinnacle.c b/drivers/sound/msnd_pinnacle.c --- a/drivers/sound/msnd_pinnacle.c 2004-06-25 05:15:38 -07:00 +++ b/drivers/sound/msnd_pinnacle.c 2004-06-25 05:15:38 -07:00 @@ -804,7 +804,7 @@ static __inline__ int pack_DARQ_to_DARF(register int bank) { - register int size, n, timeout = 3; + register int size, timeout = 3; register WORD wTmp; LPDAQD DAQD; @@ -825,13 +825,10 @@ /* Read data from the head (unprotected bank 1 access okay since this is only called inside an interrupt) */ outb(HPBLKSEL_1, dev.io + HP_BLKS); - if ((n = msnd_fifo_write( + msnd_fifo_write( &dev.DARF, (char *)(dev.base + bank * DAR_BUFF_SIZE), - size, 0)) <= 0) { - outb(HPBLKSEL_0, dev.io + HP_BLKS); - return n; - } + size); outb(HPBLKSEL_0, dev.io + HP_BLKS); return 1; @@ -853,21 +850,16 @@ if (protect) { /* Critical section: protect fifo in non-interrupt */ spin_lock_irqsave(&dev.lock, flags); - if ((n = msnd_fifo_read( + n = msnd_fifo_read( &dev.DAPF, (char *)(dev.base + bank_num * DAP_BUFF_SIZE), - DAP_BUFF_SIZE, 0)) < 0) { - spin_unlock_irqrestore(&dev.lock, flags); - return n; - } + DAP_BUFF_SIZE); spin_unlock_irqrestore(&dev.lock, flags); } else { - if ((n = msnd_fifo_read( + n = msnd_fifo_read( &dev.DAPF, (char *)(dev.base + bank_num * DAP_BUFF_SIZE), - DAP_BUFF_SIZE, 0)) < 0) { - return n; - } + DAP_BUFF_SIZE); } if (!n) break; @@ -894,30 +886,43 @@ static int dsp_read(char *buf, size_t len) { int count = len; + char *page = (char *)__get_free_page(PAGE_SIZE); + + if (!page) + return -ENOMEM; while (count > 0) { - int n; + int n, k; unsigned long flags; + k = PAGE_SIZE; + if (k > count) + k = count; + /* Critical section: protect fifo in non-interrupt */ spin_lock_irqsave(&dev.lock, flags); - if ((n = msnd_fifo_read(&dev.DARF, buf, count, 1)) < 0) { - printk(KERN_WARNING LOGNAME ": FIFO read error\n"); - spin_unlock_irqrestore(&dev.lock, flags); - return n; - } + n = msnd_fifo_read(&dev.DARF, page, k); spin_unlock_irqrestore(&dev.lock, flags); + if (copy_to_user(buf, page, n)) { + free_page((unsigned long)page); + return -EFAULT; + } buf += n; count -= n; + if (n == k && count) + continue; + if (!test_bit(F_READING, &dev.flags) && dev.mode & FMODE_READ) { dev.last_recbank = -1; if (chk_send_dsp_cmd(&dev, HDEX_RECORD_START) == 0) set_bit(F_READING, &dev.flags); } - if (dev.rec_ndelay) + if (dev.rec_ndelay) { + free_page((unsigned long)page); return count == len ? -EAGAIN : len - count; + } if (count > 0) { set_bit(F_READBLOCK, &dev.flags); @@ -926,41 +931,57 @@ get_rec_delay_jiffies(DAR_BUFF_SIZE))) clear_bit(F_READING, &dev.flags); clear_bit(F_READBLOCK, &dev.flags); - if (signal_pending(current)) + if (signal_pending(current)) { + free_page((unsigned long)page); return -EINTR; + } } } - + free_page((unsigned long)page); return len - count; } static int dsp_write(const char *buf, size_t len) { int count = len; + char *page = (char *)__get_free_page(GFP_KERNEL); + + if (!page) + return -ENOMEM; while (count > 0) { - int n; + int n, k; unsigned long flags; + k = PAGE_SIZE; + if (k > count) + k = count; + + if (copy_from_user(page, buf, k)) { + free_page((unsigned long)page); + return -EFAULT; + } + /* Critical section: protect fifo in non-interrupt */ spin_lock_irqsave(&dev.lock, flags); - if ((n = msnd_fifo_write(&dev.DAPF, buf, count, 1)) < 0) { - printk(KERN_WARNING LOGNAME ": FIFO write error\n"); - spin_unlock_irqrestore(&dev.lock, flags); - return n; - } + n = msnd_fifo_write(&dev.DAPF, page, k); spin_unlock_irqrestore(&dev.lock, flags); buf += n; count -= n; + if (count && n == k) + continue; + if (!test_bit(F_WRITING, &dev.flags) && (dev.mode & FMODE_WRITE)) { dev.last_playbank = -1; if (pack_DAPF_to_DAPQ(1) > 0) set_bit(F_WRITING, &dev.flags); } - if (dev.play_ndelay) + if (dev.play_ndelay) { + free_page((unsigned long)page); return count == len ? -EAGAIN : len - count; + } if (count > 0) { set_bit(F_WRITEBLOCK, &dev.flags); @@ -968,11 +989,14 @@ &dev.writeblock, get_play_delay_jiffies(DAP_BUFF_SIZE)); clear_bit(F_WRITEBLOCK, &dev.flags); - if (signal_pending(current)) + if (signal_pending(current)) { + free_page((unsigned long)page); return -EINTR; + } } } + free_page((unsigned long)page); return len - count; } # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/06/23 09:13:13-03:00 marcelo@logos.cnet # Al Viro sparse fixes: pss user pointer dereference # # drivers/sound/pss.c # 2004/06/16 00:31:33-03:00 marcelo@logos.cnet +63 -29 # Import patch pss-fix # diff -Nru a/drivers/sound/pss.c b/drivers/sound/pss.c --- a/drivers/sound/pss.c 2004-06-25 05:15:47 -07:00 +++ b/drivers/sound/pss.c 2004-06-25 05:15:47 -07:00 @@ -450,20 +450,36 @@ } } -static void arg_to_volume_mono(unsigned int volume, int *aleft) +static int set_volume_mono(caddr_t p, int *aleft) { int left; + unsigned volume; + if (get_user(volume, (unsigned *)p)) + return -EFAULT; - left = volume & 0x00ff; + left = volume & 0xff; if (left > 100) left = 100; *aleft = left; + return 0; } -static void arg_to_volume_stereo(unsigned int volume, int *aleft, int *aright) +static int set_volume_stereo(caddr_t p, int *aleft, int *aright) { - arg_to_volume_mono(volume, aleft); - arg_to_volume_mono(volume >> 8, aright); + int left, right; + unsigned volume; + if (get_user(volume, (unsigned *)p)) + return -EFAULT; + + left = volume & 0xff; + if (left > 100) + left = 100; + right = (volume >> 8) & 0xff; + if (right > 100) + right = 100; + *aleft = left; + *aright = right; + return 0; } static int ret_vol_mono(int left) @@ -510,33 +526,38 @@ return call_ad_mixer(devc, cmd, arg); else { - if (*(int *)arg != 0) + int v; + if (get_user(v, (int *)arg)) + return -EFAULT; + if (v != 0) return -EINVAL; return 0; } case SOUND_MIXER_VOLUME: - arg_to_volume_stereo(*(unsigned int *)arg, &devc->mixer.volume_l, - &devc->mixer.volume_r); + if (set_volume_stereo(arg, + &devc->mixer.volume_l, + &devc->mixer.volume_r)) + return -EFAULT; set_master_volume(devc, devc->mixer.volume_l, devc->mixer.volume_r); return ret_vol_stereo(devc->mixer.volume_l, devc->mixer.volume_r); case SOUND_MIXER_BASS: - arg_to_volume_mono(*(unsigned int *)arg, - &devc->mixer.bass); + if (set_volume_mono(arg, &devc->mixer.bass)) + return -EFAULT; set_bass(devc, devc->mixer.bass); return ret_vol_mono(devc->mixer.bass); case SOUND_MIXER_TREBLE: - arg_to_volume_mono(*(unsigned int *)arg, - &devc->mixer.treble); + if (set_volume_mono(arg, &devc->mixer.treble)) + return -EFAULT; set_treble(devc, devc->mixer.treble); return ret_vol_mono(devc->mixer.treble); case SOUND_MIXER_SYNTH: - arg_to_volume_mono(*(unsigned int *)arg, - &devc->mixer.synth); + if (set_volume_mono(arg, &devc->mixer.synth)) + return -EFAULT; set_synth_volume(devc, devc->mixer.synth); return ret_vol_mono(devc->mixer.synth); @@ -546,54 +567,67 @@ } else { + int val, and_mask = 0, or_mask = 0; /* * Return parameters */ switch (cmdf) { - case SOUND_MIXER_DEVMASK: if (call_ad_mixer(devc, cmd, arg) == -EINVAL) - *(int *)arg = 0; /* no mixer devices */ - return (*(int *)arg |= SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_SYNTH); + break; + and_mask = ~0; + or_mask = SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_SYNTH; + break; case SOUND_MIXER_STEREODEVS: if (call_ad_mixer(devc, cmd, arg) == -EINVAL) - *(int *)arg = 0; /* no stereo devices */ - return (*(int *)arg |= SOUND_MASK_VOLUME); + break; + and_mask = ~0; + or_mask = SOUND_MASK_VOLUME; + break; case SOUND_MIXER_RECMASK: if (devc->ad_mixer_dev != NO_WSS_MIXER) return call_ad_mixer(devc, cmd, arg); - else - return (*(int *)arg = 0); /* no record devices */ + break; case SOUND_MIXER_CAPS: if (devc->ad_mixer_dev != NO_WSS_MIXER) return call_ad_mixer(devc, cmd, arg); - else - return (*(int *)arg = SOUND_CAP_EXCL_INPUT); + or_mask = SOUND_CAP_EXCL_INPUT; + break; case SOUND_MIXER_RECSRC: if (devc->ad_mixer_dev != NO_WSS_MIXER) return call_ad_mixer(devc, cmd, arg); - else - return (*(int *)arg = 0); /* no record source */ + break; case SOUND_MIXER_VOLUME: - return (*(int *)arg = ret_vol_stereo(devc->mixer.volume_l, devc->mixer.volume_r)); + or_mask = ret_vol_stereo(devc->mixer.volume_l, devc->mixer.volume_r); + break; case SOUND_MIXER_BASS: - return (*(int *)arg = ret_vol_mono(devc->mixer.bass)); + or_mask = ret_vol_mono(devc->mixer.bass); + break; case SOUND_MIXER_TREBLE: - return (*(int *)arg = ret_vol_mono(devc->mixer.treble)); + or_mask = ret_vol_mono(devc->mixer.treble); + break; case SOUND_MIXER_SYNTH: - return (*(int *)arg = ret_vol_mono(devc->mixer.synth)); + or_mask = ret_vol_mono(devc->mixer.synth); + break; default: return -EINVAL; } + if (get_user(val, (int *)arg)) + return -EFAULT; + val &= and_mask; + val |= or_mask; + if (put_user(val, (int *)arg)) + return -EFAULT; + return val; } } # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/06/23 09:14:50-03:00 marcelo@logos.cnet # Al Viro sparse fixes: aironet # # drivers/net/wireless/airo.c # 2004/06/16 02:34:27-03:00 marcelo@logos.cnet +27 -24 # Import patch airo-fix # diff -Nru a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c --- a/drivers/net/wireless/airo.c 2004-06-25 05:15:55 -07:00 +++ b/drivers/net/wireless/airo.c 2004-06-25 05:15:55 -07:00 @@ -3666,19 +3666,22 @@ size_t len, loff_t *offset ) { - int i; - int pos; + loff_t pos = *offset; struct proc_data *priv = (struct proc_data*)file->private_data; - if( !priv->rbuffer ) return -EINVAL; + if (!priv->rbuffer) + return -EINVAL; - pos = *offset; - for( i = 0; i+pos < priv->readlen && i < len; i++ ) { - if (put_user( priv->rbuffer[i+pos], buffer+i )) - return -EFAULT; - } - *offset += i; - return i; + if (pos < 0) + return -EINVAL; + if (pos >= priv->readlen) + return 0; + if (len > priv->readlen - pos) + len = priv->readlen - pos; + if (copy_to_user(buffer, priv->rbuffer + pos, len)) + return -EFAULT; + *offset = pos + len; + return len; } /* @@ -3690,24 +3693,24 @@ size_t len, loff_t *offset ) { - int i; - int pos; + loff_t pos = *offset; struct proc_data *priv = (struct proc_data*)file->private_data; - if ( !priv->wbuffer ) { + if (!priv->wbuffer) return -EINVAL; - } - pos = *offset; - - for( i = 0; i + pos < priv->maxwritelen && - i < len; i++ ) { - if (get_user( priv->wbuffer[i+pos], buffer + i )) - return -EFAULT; - } - if ( i+pos > priv->writelen ) priv->writelen = i+file->f_pos; - *offset += i; - return i; + if (pos < 0) + return -EINVAL; + if (pos >= priv->maxwritelen) + return 0; + if (len > priv->maxwritelen - pos) + len = priv->maxwritelen - pos; + if (copy_from_user(priv->wbuffer + pos, buffer, len)) + return -EFAULT; + if (pos + len > priv->writelen) + priv->writelen = pos + len; + *offset = pos + len; + return len; } static int proc_status_open( struct inode *inode, struct file *file ) { # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/06/23 09:20:50-03:00 marcelo@logos.cnet # Al Viro sparse fixes: asus_acpi user pointer dereference # # drivers/acpi/asus_acpi.c # 2004/06/18 23:44:13-03:00 marcelo@logos.cnet +34 -12 # Import patch acpi.solar # diff -Nru a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c --- a/drivers/acpi/asus_acpi.c 2004-06-25 05:10:44 -07:00 +++ b/drivers/acpi/asus_acpi.c 2004-06-25 05:10:44 -07:00 @@ -40,6 +40,7 @@ #include #include #include +#include #define ASUS_ACPI_VERSION "0.28" @@ -455,6 +456,21 @@ return len; } + +static int parse_arg(const char *buf, unsigned long count, int *val) +{ + char s[32]; + if (!count) + return 0; + if (count > 31) + return -EINVAL; + if (copy_from_user(s, buf, count)) + return -EFAULT; + s[count] = 0; + if (sscanf(s, "%i", val) != 1) + return -EINVAL; + return count; +} /* @@ -486,11 +502,14 @@ write_led(const char *buffer, unsigned long count, struct asus_hotk *hotk, char *ledname, int ledmask, int invert) { - int value; + int value, retval; int led_out = 0; - if (sscanf(buffer, "%i", &value) == 1) - led_out = value ? 1 : 0; + retval = parse_arg(buffer, count, &value); + if (retval <= 0) + return retval; + count = retval; + led_out = value ? 1 : 0; hotk->status = (led_out) ? (hotk->status | ledmask) : (hotk->status & ~ledmask); @@ -643,12 +662,13 @@ proc_write_lcd(struct file *file, const char *buffer, unsigned long count, void *data) { - int value; + int value, retval; struct asus_hotk *hotk = (struct asus_hotk *) data; - if (sscanf(buffer, "%i", &value) == 1) + retval = parse_arg(buffer, count, &value); + if (retval > 0) set_lcd_state(hotk, value); - return count; + return retval; } @@ -710,10 +730,11 @@ proc_write_brn(struct file *file, const char *buffer, unsigned long count, void *data) { - int value; + int value, retval; struct asus_hotk *hotk = (struct asus_hotk *) data; - if (sscanf(buffer, "%d", &value) == 1) { + retval = parse_arg(buffer, count, &value); + if (retval > 0) { value = (0 < value) ? ((15 < value) ? 15 : value) : 0; /* 0 <= value <= 15 */ set_brightness(value, hotk); @@ -721,7 +742,7 @@ printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); } - return count; + return retval; } static void set_display(int value, struct asus_hotk *hotk) @@ -759,16 +780,17 @@ proc_write_disp(struct file *file, const char *buffer, unsigned long count, void *data) { - int value; + int value, retval; struct asus_hotk *hotk = (struct asus_hotk *) data; - if (sscanf(buffer, "%d", &value) == 1) + retval = parse_arg(buffer, count, &value); + if (retval > 0) set_display(value, hotk); else { printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); } - return count; + return retval; }