diff options
author | Andy Whitcroft <apw@canonical.com> | 2012-10-11 06:32:21 -0400 |
---|---|---|
committer | Matt Fleming <matt.fleming@intel.com> | 2012-10-30 06:39:23 -0400 |
commit | 5ba6e2919b9e18a051e5bdd6c21f52ee4976513f (patch) | |
tree | 3596645096f15d3b9423fa67cc3421f3f72458cd /drivers/firmware | |
parent | c0359db1a1c484ea810f4d5a877d3b00d107908b (diff) |
efivarfs: efivarfs_fill_super() ensure we clean up correctly on error
Ensure we free both the name and inode on error when building the
individual variables.
Signed-off-by: Andy Whitcroft <apw@canonical.com>
Acked-by: Matthew Garrett <mjg@redhat.com>
Acked-by: Jeremy Kerr <jeremy.kerr@canonical.com>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/efivars.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 36b3dd6e1e5e..216086d88380 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c | |||
@@ -948,6 +948,7 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) | |||
948 | struct dentry *root; | 948 | struct dentry *root; |
949 | struct efivar_entry *entry, *n; | 949 | struct efivar_entry *entry, *n; |
950 | struct efivars *efivars = &__efivars; | 950 | struct efivars *efivars = &__efivars; |
951 | char *name; | ||
951 | 952 | ||
952 | efivarfs_sb = sb; | 953 | efivarfs_sb = sb; |
953 | 954 | ||
@@ -969,16 +970,18 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) | |||
969 | return -ENOMEM; | 970 | return -ENOMEM; |
970 | 971 | ||
971 | list_for_each_entry_safe(entry, n, &efivars->list, list) { | 972 | list_for_each_entry_safe(entry, n, &efivars->list, list) { |
972 | struct inode *inode; | ||
973 | struct dentry *dentry, *root = efivarfs_sb->s_root; | 973 | struct dentry *dentry, *root = efivarfs_sb->s_root; |
974 | char *name; | ||
975 | unsigned long size = 0; | 974 | unsigned long size = 0; |
976 | int len, i; | 975 | int len, i; |
977 | 976 | ||
977 | inode = NULL; | ||
978 | |||
978 | len = utf16_strlen(entry->var.VariableName); | 979 | len = utf16_strlen(entry->var.VariableName); |
979 | 980 | ||
980 | /* GUID plus trailing NULL */ | 981 | /* GUID plus trailing NULL */ |
981 | name = kmalloc(len + 38, GFP_ATOMIC); | 982 | name = kmalloc(len + 38, GFP_ATOMIC); |
983 | if (!name) | ||
984 | goto fail; | ||
982 | 985 | ||
983 | for (i = 0; i < len; i++) | 986 | for (i = 0; i < len; i++) |
984 | name[i] = entry->var.VariableName[i] & 0xFF; | 987 | name[i] = entry->var.VariableName[i] & 0xFF; |
@@ -991,7 +994,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) | |||
991 | 994 | ||
992 | inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, | 995 | inode = efivarfs_get_inode(efivarfs_sb, root->d_inode, |
993 | S_IFREG | 0644, 0); | 996 | S_IFREG | 0644, 0); |
997 | if (!inode) | ||
998 | goto fail_name; | ||
999 | |||
994 | dentry = d_alloc_name(root, name); | 1000 | dentry = d_alloc_name(root, name); |
1001 | if (!dentry) | ||
1002 | goto fail_inode; | ||
1003 | |||
995 | /* copied by the above to local storage in the dentry. */ | 1004 | /* copied by the above to local storage in the dentry. */ |
996 | kfree(name); | 1005 | kfree(name); |
997 | 1006 | ||
@@ -1009,6 +1018,13 @@ int efivarfs_fill_super(struct super_block *sb, void *data, int silent) | |||
1009 | } | 1018 | } |
1010 | 1019 | ||
1011 | return 0; | 1020 | return 0; |
1021 | |||
1022 | fail_inode: | ||
1023 | iput(inode); | ||
1024 | fail_name: | ||
1025 | kfree(name); | ||
1026 | fail: | ||
1027 | return -ENOMEM; | ||
1012 | } | 1028 | } |
1013 | 1029 | ||
1014 | static struct dentry *efivarfs_mount(struct file_system_type *fs_type, | 1030 | static struct dentry *efivarfs_mount(struct file_system_type *fs_type, |