X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=sound%2Fcore%2Fcontrol.c;h=268ab7471224a5e42fe4f448df75c7ad4ad7094e;hb=f653398c86a1c104f0992bd788dd4bb065449be4;hp=17b8d47a5cd07f2fca53ec7ef31d935a8958b327;hpb=ef44a1ec6eeef189998f84e7230e1d3535b01074;p=safe%2Fjmp%2Flinux-2.6 diff --git a/sound/core/control.c b/sound/core/control.c index 17b8d47..268ab74 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -75,7 +75,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file) ctl->card = card; ctl->prefer_pcm_subdevice = -1; ctl->prefer_rawmidi_subdevice = -1; - ctl->pid = current->pid; + ctl->pid = get_pid(task_pid(current)); file->private_data = ctl; write_lock_irqsave(&card->ctl_files_rwlock, flags); list_add_tail(&ctl->list, &card->ctl_files); @@ -125,6 +125,7 @@ static int snd_ctl_release(struct inode *inode, struct file *file) control->vd[idx].owner = NULL; up_write(&card->controls_rwsem); snd_ctl_empty_read_queue(ctl); + put_pid(ctl->pid); kfree(ctl); module_put(card->module); snd_card_file_remove(card, file); @@ -414,7 +415,7 @@ int snd_ctl_remove_id(struct snd_card *card, struct snd_ctl_elem_id *id) EXPORT_SYMBOL(snd_ctl_remove_id); /** - * snd_ctl_remove_unlocked_id - remove the unlocked control of the given id and release it + * snd_ctl_remove_user_ctl - remove and release the unlocked user control * @file: active control handle * @id: the control id to remove * @@ -423,8 +424,8 @@ EXPORT_SYMBOL(snd_ctl_remove_id); * * Returns 0 if successful, or a negative error code on failure. */ -static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file, - struct snd_ctl_elem_id *id) +static int snd_ctl_remove_user_ctl(struct snd_ctl_file * file, + struct snd_ctl_elem_id *id) { struct snd_card *card = file->card; struct snd_kcontrol *kctl; @@ -433,15 +434,23 @@ static int snd_ctl_remove_unlocked_id(struct snd_ctl_file * file, down_write(&card->controls_rwsem); kctl = snd_ctl_find_id(card, id); if (kctl == NULL) { - up_write(&card->controls_rwsem); - return -ENOENT; + ret = -ENOENT; + goto error; + } + if (!(kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_USER)) { + ret = -EINVAL; + goto error; } for (idx = 0; idx < kctl->count; idx++) if (kctl->vd[idx].owner != NULL && kctl->vd[idx].owner != file) { - up_write(&card->controls_rwsem); - return -EBUSY; + ret = -EBUSY; + goto error; } ret = snd_ctl_remove(card, kctl); + if (ret < 0) + goto error; + card->user_ctl_count--; +error: up_write(&card->controls_rwsem); return ret; } @@ -664,7 +673,7 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl, info->access |= SNDRV_CTL_ELEM_ACCESS_LOCK; if (vd->owner == ctl) info->access |= SNDRV_CTL_ELEM_ACCESS_OWNER; - info->owner = vd->owner_pid; + info->owner = pid_vnr(vd->owner->pid); } else { info->owner = -1; } @@ -819,7 +828,6 @@ static int snd_ctl_elem_lock(struct snd_ctl_file *file, result = -EBUSY; else { vd->owner = file; - vd->owner_pid = current->pid; result = 0; } } @@ -850,7 +858,6 @@ static int snd_ctl_elem_unlock(struct snd_ctl_file *file, result = -EPERM; else { vd->owner = NULL; - vd->owner_pid = 0; result = 0; } } @@ -951,7 +958,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, if (card->user_ctl_count >= MAX_USER_CONTROLS) return -ENOMEM; - if (info->count > 1024) + if (info->count < 1) return -EINVAL; access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : (info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| @@ -1052,18 +1059,10 @@ static int snd_ctl_elem_remove(struct snd_ctl_file *file, struct snd_ctl_elem_id __user *_id) { struct snd_ctl_elem_id id; - int err; if (copy_from_user(&id, _id, sizeof(id))) return -EFAULT; - err = snd_ctl_remove_unlocked_id(file, &id); - if (! err) { - struct snd_card *card = file->card; - down_write(&card->controls_rwsem); - card->user_ctl_count--; - up_write(&card->controls_rwsem); - } - return err; + return snd_ctl_remove_user_ctl(file, &id); } static int snd_ctl_subscribe_events(struct snd_ctl_file *file, int __user *ptr) @@ -1120,7 +1119,7 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file, goto __kctl_end; } if (vd->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) { - if (file && vd->owner != NULL && vd->owner != file) { + if (vd->owner != NULL && vd->owner != file) { err = -EPERM; goto __kctl_end; }