|
79 | 79 | #include <linux/device.h> |
80 | 80 | #include <linux/slab.h> |
81 | 81 | #include <linux/pstore.h> |
| 82 | +#include <linux/ctype.h> |
82 | 83 |
|
83 | 84 | #include <linux/fs.h> |
84 | 85 | #include <linux/ramfs.h> |
@@ -900,6 +901,48 @@ static struct inode *efivarfs_get_inode(struct super_block *sb, |
900 | 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 | 946 | static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid) |
904 | 947 | { |
905 | 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 | 971 | struct efivar_entry *var; |
929 | 972 | int namelen, i = 0, err = 0; |
930 | 973 |
|
931 | | - /* |
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) |
| 974 | + if (!efivarfs_valid_name(dentry->d_name.name, dentry->d_name.len)) |
936 | 975 | return -EINVAL; |
937 | 976 |
|
938 | 977 | inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0); |
|
0 commit comments