aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/core/pcm_native.c40
1 files changed, 15 insertions, 25 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index f92818155958..a68d4c6d702c 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1589,29 +1589,16 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
1589} 1589}
1590 1590
1591 1591
1592/* WARNING: Don't forget to fput back the file */ 1592static bool is_pcm_file(struct file *file)
1593static struct file *snd_pcm_file_fd(int fd, int *fput_needed)
1594{ 1593{
1595 struct file *file; 1594 struct inode *inode = file_inode(file);
1596 struct inode *inode;
1597 unsigned int minor; 1595 unsigned int minor;
1598 1596
1599 file = fget_light(fd, fput_needed); 1597 if (!S_ISCHR(inode->i_mode) || imajor(inode) != snd_major)
1600 if (!file) 1598 return false;
1601 return NULL;
1602 inode = file_inode(file);
1603 if (!S_ISCHR(inode->i_mode) ||
1604 imajor(inode) != snd_major) {
1605 fput_light(file, *fput_needed);
1606 return NULL;
1607 }
1608 minor = iminor(inode); 1599 minor = iminor(inode);
1609 if (!snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) && 1600 return snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_PLAYBACK) ||
1610 !snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE)) { 1601 snd_lookup_minor_data(minor, SNDRV_DEVICE_TYPE_PCM_CAPTURE);
1611 fput_light(file, *fput_needed);
1612 return NULL;
1613 }
1614 return file;
1615} 1602}
1616 1603
1617/* 1604/*
@@ -1620,16 +1607,18 @@ static struct file *snd_pcm_file_fd(int fd, int *fput_needed)
1620static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) 1607static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
1621{ 1608{
1622 int res = 0; 1609 int res = 0;
1623 struct file *file;
1624 struct snd_pcm_file *pcm_file; 1610 struct snd_pcm_file *pcm_file;
1625 struct snd_pcm_substream *substream1; 1611 struct snd_pcm_substream *substream1;
1626 struct snd_pcm_group *group; 1612 struct snd_pcm_group *group;
1627 int fput_needed; 1613 struct fd f = fdget(fd);
1628 1614
1629 file = snd_pcm_file_fd(fd, &fput_needed); 1615 if (!f.file)
1630 if (!file)
1631 return -EBADFD; 1616 return -EBADFD;
1632 pcm_file = file->private_data; 1617 if (!is_pcm_file(f.file)) {
1618 res = -EBADFD;
1619 goto _badf;
1620 }
1621 pcm_file = f.file->private_data;
1633 substream1 = pcm_file->substream; 1622 substream1 = pcm_file->substream;
1634 group = kmalloc(sizeof(*group), GFP_KERNEL); 1623 group = kmalloc(sizeof(*group), GFP_KERNEL);
1635 if (!group) { 1624 if (!group) {
@@ -1663,8 +1652,9 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
1663 up_write(&snd_pcm_link_rwsem); 1652 up_write(&snd_pcm_link_rwsem);
1664 _nolock: 1653 _nolock:
1665 snd_card_unref(substream1->pcm->card); 1654 snd_card_unref(substream1->pcm->card);
1666 fput_light(file, fput_needed);
1667 kfree(group); 1655 kfree(group);
1656 _badf:
1657 fdput(f);
1668 return res; 1658 return res;
1669} 1659}
1670 1660