diff options
| -rw-r--r-- | drivers/firmware/efivars.c | 49 |
1 files changed, 44 insertions, 5 deletions
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 371c44129525..868cea5cd4b8 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c | |||
| @@ -79,6 +79,7 @@ | |||
| 79 | #include <linux/device.h> | 79 | #include <linux/device.h> |
| 80 | #include <linux/slab.h> | 80 | #include <linux/slab.h> |
| 81 | #include <linux/pstore.h> | 81 | #include <linux/pstore.h> |
| 82 | #include <linux/ctype.h> | ||
| 82 | 83 | ||
| 83 | #include <linux/fs.h> | 84 | #include <linux/fs.h> |
| 84 | #include <linux/ramfs.h> | 85 | #include <linux/ramfs.h> |
| @@ -900,6 +901,48 @@ static struct inode *efivarfs_get_inode(struct super_block *sb, | |||
| 900 | return inode; | 901 | return inode; |
| 901 | } | 902 | } |
| 902 | 903 | ||
| 904 | /* | ||
| 905 | * Return true if 'str' is a valid efivarfs filename of the form, | ||
| 906 | * | ||
| 907 | * VariableName-12345678-1234-1234-1234-1234567891bc | ||
| 908 | */ | ||
| 909 | static bool efivarfs_valid_name(const char *str, int len) | ||
| 910 | { | ||
| 911 | static const char dashes[GUID_LEN] = { | ||
| 912 | [8] = 1, [13] = 1, [18] = 1, [23] = 1 | ||
| 913 | }; | ||
| 914 | const char *s = str + len - GUID_LEN; | ||
| 915 | int i; | ||
| 916 | |||
| 917 | /* | ||
| 918 | * We need a GUID, plus at least one letter for the variable name, | ||
| 919 | * plus the '-' separator | ||
| 920 | */ | ||
| 921 | if (len < GUID_LEN + 2) | ||
| 922 | return false; | ||
| 923 | |||
| 924 | /* GUID should be right after the first '-' */ | ||
| 925 | if (s - 1 != strchr(str, '-')) | ||
| 926 | return false; | ||
| 927 | |||
| 928 | /* | ||
| 929 | * Validate that 's' is of the correct format, e.g. | ||
| 930 | * | ||
| 931 | * 12345678-1234-1234-1234-123456789abc | ||
| 932 | */ | ||
| 933 | for (i = 0; i < GUID_LEN; i++) { | ||
| 934 | if (dashes[i]) { | ||
| 935 | if (*s++ != '-') | ||
| 936 | return false; | ||
| 937 | } else { | ||
| 938 | if (!isxdigit(*s++)) | ||
| 939 | return false; | ||
| 940 | } | ||
| 941 | } | ||
| 942 | |||
| 943 | return true; | ||
| 944 | } | ||
| 945 | |||
| 903 | static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid) | 946 | static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid) |
| 904 | { | 947 | { |
| 905 | guid->b[0] = hex_to_bin(str[6]) << 4 | hex_to_bin(str[7]); | 948 | guid->b[0] = hex_to_bin(str[6]) << 4 | hex_to_bin(str[7]); |
| @@ -928,11 +971,7 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry, | |||
| 928 | struct efivar_entry *var; | 971 | struct efivar_entry *var; |
| 929 | int namelen, i = 0, err = 0; | 972 | int namelen, i = 0, err = 0; |
| 930 | 973 | ||
| 931 | /* | 974 | if (!efivarfs_valid_name(dentry->d_name.name, dentry->d_name.len)) |
| 932 | * We need a GUID, plus at least one letter for the variable name, | ||
| 933 | * plus the '-' separator | ||
| 934 | */ | ||
| 935 | if (dentry->d_name.len < GUID_LEN + 2) | ||
| 936 | return -EINVAL; | 975 | return -EINVAL; |
| 937 | 976 | ||
| 938 | inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); | 977 | inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); |
