Commit 886364f6 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: core: Fix possible memory leaks at error path in info.c

Currently, snd_info_init() just returns an error without releasing the
previously assigned resources at error path.  The assigned proc and
info entries have to be released properly.  This patch covers it.

While we are at it, refactor the code a bit, too.
Acked-by: default avatarJaroslav Kysela <perex@perex.cz>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 4adb7bcb
...@@ -446,6 +446,22 @@ static const struct file_operations snd_info_text_entry_ops = ...@@ -446,6 +446,22 @@ static const struct file_operations snd_info_text_entry_ops =
.read = seq_read, .read = seq_read,
}; };
static struct snd_info_entry *create_subdir(struct module *mod,
const char *name)
{
struct snd_info_entry *entry;
entry = snd_info_create_module_entry(mod, name, NULL);
if (!entry)
return NULL;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return NULL;
}
return entry;
}
int __init snd_info_init(void) int __init snd_info_init(void)
{ {
struct proc_dir_entry *p; struct proc_dir_entry *p;
...@@ -455,36 +471,27 @@ int __init snd_info_init(void) ...@@ -455,36 +471,27 @@ int __init snd_info_init(void)
return -ENOMEM; return -ENOMEM;
snd_proc_root = p; snd_proc_root = p;
#ifdef CONFIG_SND_OSSEMUL #ifdef CONFIG_SND_OSSEMUL
{ snd_oss_root = create_subdir(THIS_MODULE, "oss");
struct snd_info_entry *entry; if (!snd_oss_root)
if ((entry = snd_info_create_module_entry(THIS_MODULE, "oss", NULL)) == NULL) goto error;
return -ENOMEM;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return -ENOMEM;
}
snd_oss_root = entry;
}
#endif #endif
#if IS_ENABLED(CONFIG_SND_SEQUENCER) #if IS_ENABLED(CONFIG_SND_SEQUENCER)
{ snd_seq_root = create_subdir(THIS_MODULE, "seq");
struct snd_info_entry *entry; if (!snd_seq_root)
if ((entry = snd_info_create_module_entry(THIS_MODULE, "seq", NULL)) == NULL) goto error;
return -ENOMEM;
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return -ENOMEM;
}
snd_seq_root = entry;
}
#endif #endif
snd_info_version_init(); snd_info_version_init();
snd_minor_info_init(); snd_minor_info_init();
snd_minor_info_oss_init(); snd_minor_info_oss_init();
snd_card_info_init(); snd_card_info_init();
return 0; return 0;
error:
#ifdef CONFIG_SND_OSSEMUL
snd_info_free_entry(snd_oss_root);
#endif
proc_remove(snd_proc_root);
return -ENOMEM;
} }
int __exit snd_info_done(void) int __exit snd_info_done(void)
...@@ -523,13 +530,9 @@ int snd_info_card_create(struct snd_card *card) ...@@ -523,13 +530,9 @@ int snd_info_card_create(struct snd_card *card)
return -ENXIO; return -ENXIO;
sprintf(str, "card%i", card->number); sprintf(str, "card%i", card->number);
if ((entry = snd_info_create_module_entry(card->module, str, NULL)) == NULL) entry = create_subdir(card->module, str);
return -ENOMEM; if (!entry)
entry->mode = S_IFDIR | S_IRUGO | S_IXUGO;
if (snd_info_register(entry) < 0) {
snd_info_free_entry(entry);
return -ENOMEM; return -ENOMEM;
}
card->proc_root = entry; card->proc_root = entry;
return 0; return 0;
} }
...@@ -758,7 +761,6 @@ EXPORT_SYMBOL(snd_info_create_card_entry); ...@@ -758,7 +761,6 @@ EXPORT_SYMBOL(snd_info_create_card_entry);
static void snd_info_disconnect(struct snd_info_entry *entry) static void snd_info_disconnect(struct snd_info_entry *entry)
{ {
struct list_head *p, *n; struct list_head *p, *n;
struct proc_dir_entry *root;
list_for_each_safe(p, n, &entry->children) { list_for_each_safe(p, n, &entry->children) {
snd_info_disconnect(list_entry(p, struct snd_info_entry, list)); snd_info_disconnect(list_entry(p, struct snd_info_entry, list));
...@@ -767,8 +769,6 @@ static void snd_info_disconnect(struct snd_info_entry *entry) ...@@ -767,8 +769,6 @@ static void snd_info_disconnect(struct snd_info_entry *entry)
if (! entry->p) if (! entry->p)
return; return;
list_del_init(&entry->list); list_del_init(&entry->list);
root = entry->parent == NULL ? snd_proc_root : entry->parent->p;
snd_BUG_ON(!root);
proc_remove(entry->p); proc_remove(entry->p);
entry->p = NULL; entry->p = NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment