* [PATCH 0/2] efivarfs patch queue
@ 2013-02-11 14:28 Matt Fleming
[not found] ` <1360592935-26026-1-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
0 siblings, 1 reply; 15+ messages in thread
From: Matt Fleming @ 2013-02-11 14:28 UTC (permalink / raw)
To: linux-efi-u79uwXL29TY76Z2rM5mHXA
Cc: Lingzhu Xiang, Matthew Garrett, Jeremy Kerr, Al Viro, Matt Fleming
From: Matt Fleming <matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
I've queued up the following fixes in the 'next' branch of the EFI
tree. Both bugs were reported by Lingzhu Xiang and are caused by a
lack of filename validation in efivarfs.
Matt Fleming (2):
efivarfs: Validate filenames much more aggressively
efivarfs: guid part of filenames are case-insensitive
drivers/firmware/efivars.c | 156 +++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 150 insertions(+), 6 deletions(-)
--
1.7.11.7
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/2] efivarfs: Validate filenames much more aggressively
[not found] ` <1360592935-26026-1-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
@ 2013-02-11 14:28 ` Matt Fleming
[not found] ` <1360592935-26026-2-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2013-02-11 14:28 ` [PATCH 2/2] efivarfs: guid part of filenames are case-insensitive Matt Fleming
1 sibling, 1 reply; 15+ messages in thread
From: Matt Fleming @ 2013-02-11 14:28 UTC (permalink / raw)
To: linux-efi-u79uwXL29TY76Z2rM5mHXA
Cc: Lingzhu Xiang, Matthew Garrett, Jeremy Kerr, Al Viro, Matt Fleming
From: Matt Fleming <matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
The only thing that efivarfs does to enforce a valid filename is
ensure that the name isn't too short. We need to strongly sanitise any
filenames, not least because variable creation is delayed until
efivarfs_file_write(), which means we can't rely on the firmware to
inform us of an invalid name, because if the file is never written to
we'll never know it's invalid.
Perform a couple of steps before agreeing to create a new file,
* hex_to_bin() returns a value indicating whether or not it was able
to convert its arguments to a binary representation - we should
check it.
* Ensure that the GUID portion of the filename is the correct length
and format.
* The variable name portion of the filename needs to be at least one
character in size.
Reported-by: Lingzhu Xiang <lxiang-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Cc: Matthew Garrett <mjg59-1xO5oi07KQx4cg9Nei1l7Q@public.gmane.org>
Cc: Jeremy Kerr <jeremy.kerr-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
Cc: Al Viro <viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
Signed-off-by: Matt Fleming <matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
drivers/firmware/efivars.c | 55 +++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 50 insertions(+), 5 deletions(-)
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 371c441..a4fa409 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -900,6 +900,55 @@ static struct inode *efivarfs_get_inode(struct super_block *sb,
return inode;
}
+/*
+ * Return 1 if 'str' is a valid efivarfs filename of the form,
+ *
+ * VariableName-12345678-1234-1234-1234-1234567891bc
+ */
+static int efivarfs_valid_name(const char *str, int len)
+{
+ const char *s;
+ int i, j;
+ int ranges[2][5] = {
+ { 0, 9, 14, 19, 24 },
+ { 8, 13, 18, 23, 36 }
+ };
+
+ /*
+ * We need a GUID, plus at least one letter for the variable name,
+ * plus the '-' separator
+ */
+ if (len < GUID_LEN + 2)
+ return 0;
+
+ s = strchr(str, '-');
+ if (!s)
+ return 0;
+
+ s++; /* Skip '-' */
+
+ /* Ensure we have enough characters for a GUID */
+ if (len - (s - str) != GUID_LEN)
+ return 0;
+
+ /*
+ * Validate that 's' is of the correct format, e.g.
+ *
+ * 12345678-1234-1234-1234-123456789abc
+ */
+ for (i = 0; i < 5; i++) {
+ for (j = ranges[0][i]; j < ranges[1][i]; j++) {
+ if (hex_to_bin(s[j]) < 0)
+ return 0;
+ }
+
+ if (j < GUID_LEN && s[j] != '-')
+ return 0;
+ }
+
+ return 1;
+}
+
static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid)
{
guid->b[0] = hex_to_bin(str[6]) << 4 | hex_to_bin(str[7]);
@@ -928,11 +977,7 @@ static int efivarfs_create(struct inode *dir, struct dentry *dentry,
struct efivar_entry *var;
int namelen, i = 0, err = 0;
- /*
- * We need a GUID, plus at least one letter for the variable name,
- * plus the '-' separator
- */
- if (dentry->d_name.len < GUID_LEN + 2)
+ if (!efivarfs_valid_name(dentry->d_name.name, dentry->d_name.len))
return -EINVAL;
inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
--
1.7.11.7
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 2/2] efivarfs: guid part of filenames are case-insensitive
[not found] ` <1360592935-26026-1-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2013-02-11 14:28 ` [PATCH 1/2] efivarfs: Validate filenames much more aggressively Matt Fleming
@ 2013-02-11 14:28 ` Matt Fleming
[not found] ` <1360592935-26026-3-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
1 sibling, 1 reply; 15+ messages in thread
From: Matt Fleming @ 2013-02-11 14:28 UTC (permalink / raw)
To: linux-efi-u79uwXL29TY76Z2rM5mHXA
Cc: Lingzhu Xiang, Matthew Garrett, Jeremy Kerr, Al Viro, Matt Fleming
From: Matt Fleming <matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
It makes no sense to treat the following filenames as unique,
VarName-abcdefab-abcd-abcd-abcd-abcdefabcdef
VarName-ABCDEFAB-ABCD-ABCD-ABCD-ABCDEFABCDEF
VarName-ABcDEfAB-ABcD-ABcD-ABcD-ABcDEfABcDEf
VarName-aBcDEfAB-aBcD-aBcD-aBcD-aBcDEfaBcDEf
... etc ...
since the guid will be converted into a binary representation, which
has no case.
Roll our own dentry operations so that we can treat the variable name
part of filenames ("VarName" in the above example) as case-sensitive,
but the guid portion as case-insensitive. That way, efivarfs will
refuse to create the above files if any one already exists.
Reported-by: Lingzhu Xiang <lxiang-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Cc: Matthew Garrett <mjg59-1xO5oi07KQx4cg9Nei1l7Q@public.gmane.org>
Cc: Jeremy Kerr <jeremy.kerr-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
Cc: Al Viro <viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
Signed-off-by: Matt Fleming <matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
drivers/firmware/efivars.c | 101 ++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 100 insertions(+), 1 deletion(-)
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index a4fa409..10088fd 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -79,6 +79,7 @@
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/pstore.h>
+#include <linux/ctype.h>
#include <linux/fs.h>
#include <linux/ramfs.h>
@@ -1049,6 +1050,91 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry)
return -EINVAL;
};
+/*
+ * Compare two efivarfs file names.
+ *
+ * An efivarfs filename is composed of two parts,
+ *
+ * 1. A case-sensitive variable name
+ * 2. A case-insensitive GUID
+ *
+ * So we need to perform a case-sensitive match on part 1 and a
+ * case-insensitive match on part 2.
+ */
+static int efivarfs_d_compare(const struct dentry *parent, const struct inode *pinode,
+ const struct dentry *dentry, const struct inode *inode,
+ unsigned int len, const char *str,
+ const struct qstr *name)
+{
+ const char *q;
+ int guid;
+
+ /*
+ * If the string we're being asked to compare doesn't match
+ * the expected format return "no match".
+ */
+ if (!efivarfs_valid_name(str, len))
+ return 1;
+
+ if (!(q = strchr(name->name, '-')))
+ return 1;
+
+ /* Find part 1, the variable name. */
+ guid = q - (const char *)name->name;
+
+ /* Case-sensitive compare for the variable name */
+ if (memcmp(str, name->name, guid))
+ return 1;
+
+ /* Case-insensitive compare for the GUID */
+ return strcasecmp(&name->name[guid], &str[guid]);
+}
+
+static int efivarfs_d_hash(const struct dentry *dentry,
+ const struct inode *inode, struct qstr *qstr)
+{
+ const unsigned char *us;
+ char lower[NAME_MAX];
+ int guid;
+
+ if (!efivarfs_valid_name(qstr->name, qstr->len))
+ return -EINVAL;
+
+ if (qstr->len > NAME_MAX)
+ return -ENAMETOOLONG;
+
+ us = strchr(qstr->name, '-');
+ if (!us)
+ return -EINVAL;
+
+ /* The variable name part is case-sensitive */
+ guid = us - qstr->name;
+ memcpy(lower, qstr->name, guid);
+
+ /* GUID is case-insensitive. */
+ for (us = &qstr->name[guid]; guid < qstr->len; guid++)
+ lower[guid] = tolower(*us++);
+ lower[guid] = '\0';
+
+ qstr->hash = full_name_hash(lower, qstr->len);
+ return 0;
+}
+
+/*
+ * Retaining negative dentries for an in-memory filesystem just wastes
+ * memory and lookup time: arrange for them to be deleted immediately.
+ */
+static int efivarfs_delete_dentry(const struct dentry *dentry)
+{
+ return 1;
+}
+
+static struct dentry_operations efivarfs_d_ops = {
+ .d_compare = efivarfs_d_compare,
+ .d_hash = efivarfs_d_hash,
+ .d_delete = efivarfs_delete_dentry,
+};
+
static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
{
struct inode *inode = NULL;
@@ -1064,6 +1150,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = EFIVARFS_MAGIC;
sb->s_op = &efivarfs_ops;
+ sb->s_d_op = &efivarfs_d_ops;
sb->s_time_gran = 1;
inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0);
@@ -1154,8 +1241,20 @@ static struct file_system_type efivarfs_type = {
.kill_sb = efivarfs_kill_sb,
};
+/*
+ * Handle negative dentry.
+ */
+static struct dentry *efivarfs_lookup(struct inode *dir, struct dentry *dentry,
+ unsigned int flags)
+{
+ if (dentry->d_name.len > NAME_MAX)
+ return ERR_PTR(-ENAMETOOLONG);
+ d_add(dentry, NULL);
+ return NULL;
+}
+
static const struct inode_operations efivarfs_dir_inode_operations = {
- .lookup = simple_lookup,
+ .lookup = efivarfs_lookup,
.unlink = efivarfs_unlink,
.create = efivarfs_create,
};
--
1.7.11.7
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] efivarfs: Validate filenames much more aggressively
[not found] ` <1360592935-26026-2-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
@ 2013-02-11 15:01 ` Al Viro
[not found] ` <20130211150109.GK4503-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
2013-02-12 12:36 ` [PATCH 1/2 v2] " Matt Fleming
1 sibling, 1 reply; 15+ messages in thread
From: Al Viro @ 2013-02-11 15:01 UTC (permalink / raw)
To: Matt Fleming
Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, Lingzhu Xiang, Matthew Garrett,
Jeremy Kerr, Matt Fleming
On Mon, Feb 11, 2013 at 02:28:54PM +0000, Matt Fleming wrote:
> + * Return 1 if 'str' is a valid efivarfs filename of the form,
> + *
> + * VariableName-12345678-1234-1234-1234-1234567891bc
> + */
> +static int efivarfs_valid_name(const char *str, int len)
> +{
> + const char *s;
> + int i, j;
> + int ranges[2][5] = {
> + { 0, 9, 14, 19, 24 },
> + { 8, 13, 18, 23, 36 }
> + };
> +
> + /*
> + * We need a GUID, plus at least one letter for the variable name,
> + * plus the '-' separator
> + */
> + if (len < GUID_LEN + 2)
> + return 0;
> +
> + s = strchr(str, '-');
> + if (!s)
> + return 0;
> +
> + s++; /* Skip '-' */
> +
> + /* Ensure we have enough characters for a GUID */
> + if (len - (s - str) != GUID_LEN)
> + return 0;
> +
> + /*
> + * Validate that 's' is of the correct format, e.g.
> + *
> + * 12345678-1234-1234-1234-123456789abc
> + */
> + for (i = 0; i < 5; i++) {
> + for (j = ranges[0][i]; j < ranges[1][i]; j++) {
> + if (hex_to_bin(s[j]) < 0)
> + return 0;
> + }
> +
> + if (j < GUID_LEN && s[j] != '-')
> + return 0;
> + }
> +
> + return 1;
Yecchhh... How about
static const char dashes[GUID_LEN] = {
[8] = 1, [13] = 1, [18] = 1, [23] = 1
};
const char *s = str + len - GUID_LEN;
int i;
/*
* We need a GUID, plus at least one letter for the variable name,
* plus the '-' separator
*/
if (len < GUID_LEN + 2)
return 0;
/* GUID should be right after the first '-' */
if (s - 1 != strchr(str, '-'))
return 0;
/*
* Validate that 's' is of the correct format, e.g.
*
* 12345678-1234-1234-1234-123456789abc
*/
for (i = 0; i < GUID_LEN; i++) {
if (dashes[i]) {
if (*s++ != '-')
return 0;
} else {
if (!isxdigit(*s++))
return 0;
}
}
return 1;
instead?
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 1/2] efivarfs: Validate filenames much more aggressively
[not found] ` <20130211150109.GK4503-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
@ 2013-02-11 15:12 ` Matt Fleming
0 siblings, 0 replies; 15+ messages in thread
From: Matt Fleming @ 2013-02-11 15:12 UTC (permalink / raw)
To: Al Viro
Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, Lingzhu Xiang, Matthew Garrett,
Jeremy Kerr, Matt Fleming
On Mon, 11 Feb, at 03:01:09PM, Al Viro wrote:
>
> Yecchhh... How about
> static const char dashes[GUID_LEN] = {
> [8] = 1, [13] = 1, [18] = 1, [23] = 1
> };
> const char *s = str + len - GUID_LEN;
> int i;
> /*
> * We need a GUID, plus at least one letter for the variable name,
> * plus the '-' separator
> */
> if (len < GUID_LEN + 2)
> return 0;
>
> /* GUID should be right after the first '-' */
> if (s - 1 != strchr(str, '-'))
> return 0;
>
> /*
> * Validate that 's' is of the correct format, e.g.
> *
> * 12345678-1234-1234-1234-123456789abc
> */
> for (i = 0; i < GUID_LEN; i++) {
> if (dashes[i]) {
> if (*s++ != '-')
> return 0;
> } else {
> if (!isxdigit(*s++))
> return 0;
> }
> }
> return 1;
>
> instead?
Sure, that's a nice improvement.
Also, I did have a version of this patch that returned a boolean, but
that seems to have been lost in one of my topic branches.
I'll respind this, thanks Al.
--
Matt Fleming, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] efivarfs: guid part of filenames are case-insensitive
[not found] ` <1360592935-26026-3-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
@ 2013-02-11 15:22 ` Al Viro
[not found] ` <20130211152221.GL4503-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
2013-02-12 12:39 ` [PATCH 2/2 v2] " Matt Fleming
1 sibling, 1 reply; 15+ messages in thread
From: Al Viro @ 2013-02-11 15:22 UTC (permalink / raw)
To: Matt Fleming
Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, Lingzhu Xiang, Matthew Garrett,
Jeremy Kerr, Matt Fleming
On Mon, Feb 11, 2013 at 02:28:55PM +0000, Matt Fleming wrote:
> From: Matt Fleming <matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
>
> It makes no sense to treat the following filenames as unique,
>
> VarName-abcdefab-abcd-abcd-abcd-abcdefabcdef
> VarName-ABCDEFAB-ABCD-ABCD-ABCD-ABCDEFABCDEF
> VarName-ABcDEfAB-ABcD-ABcD-ABcD-ABcDEfABcDEf
> VarName-aBcDEfAB-aBcD-aBcD-aBcD-aBcDEfaBcDEf
> ... etc ...
>
> since the guid will be converted into a binary representation, which
> has no case.
>
> Roll our own dentry operations so that we can treat the variable name
> part of filenames ("VarName" in the above example) as case-sensitive,
> but the guid portion as case-insensitive. That way, efivarfs will
> refuse to create the above files if any one already exists.
>
> Reported-by: Lingzhu Xiang <lxiang-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> Cc: Matthew Garrett <mjg59-1xO5oi07KQx4cg9Nei1l7Q@public.gmane.org>
> Cc: Jeremy Kerr <jeremy.kerr-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
> Cc: Al Viro <viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
> Signed-off-by: Matt Fleming <matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> ---
> drivers/firmware/efivars.c | 101 ++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 100 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
> index a4fa409..10088fd 100644
> --- a/drivers/firmware/efivars.c
> +++ b/drivers/firmware/efivars.c
> @@ -79,6 +79,7 @@
> #include <linux/device.h>
> #include <linux/slab.h>
> #include <linux/pstore.h>
> +#include <linux/ctype.h>
>
> #include <linux/fs.h>
> #include <linux/ramfs.h>
> @@ -1049,6 +1050,91 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry)
> return -EINVAL;
> };
>
> +/*
> + * Compare two efivarfs file names.
> + *
> + * An efivarfs filename is composed of two parts,
> + *
> + * 1. A case-sensitive variable name
> + * 2. A case-insensitive GUID
> + *
> + * So we need to perform a case-sensitive match on part 1 and a
> + * case-insensitive match on part 2.
> + */
> +static int efivarfs_d_compare(const struct dentry *parent, const struct inode *pinode,
> + const struct dentry *dentry, const struct inode *inode,
> + unsigned int len, const char *str,
> + const struct qstr *name)
> +{
> + const char *q;
> + int guid;
> +
> + /*
> + * If the string we're being asked to compare doesn't match
> + * the expected format return "no match".
> + */
> + if (!efivarfs_valid_name(str, len))
> + return 1;
> + if (!(q = strchr(name->name, '-')))
> + return 1;
No. Why check that again, when we'd already called ->d_hash() on the
incoming name *and* candidate dentry? And buggered off on any potential
errors.
> +
> + /* Find part 1, the variable name. */
> + guid = q - (const char *)name->name;
No need to do strchr() for that - you know that name passes
efivarfs_valid_name(), so you know how far from the end will GUID part begin.
> + /* Case-sensitive compare for the variable name */
> + if (memcmp(str, name->name, guid))
> + return 1;
> +
> + /* Case-insensitive compare for the GUID */
> + return strcasecmp(&name->name[guid], &str[guid]);
> +}
> +static int efivarfs_d_hash(const struct dentry *dentry,
> + const struct inode *inode, struct qstr *qstr)
> +{
Egads, man...
[snip the horror with copying the name]
unsigned long hash = init_name_hash();
const unsigned char *s = qstr->name;
int len = qstr->len;
if (!efivarfs_valid_name(s, len))
return -EINVAL;
while (len-- > GUID_LEN)
hash = partial_name_hash(*s++, hash);
/* GUID is case-insensitive. */
while (len--)
hash = partial_name_hash(tolower(*s++), hash);
return end_name_hash(hash);
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] efivarfs: guid part of filenames are case-insensitive
[not found] ` <20130211152221.GL4503-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
@ 2013-02-11 15:37 ` Al Viro
2013-02-11 16:05 ` Matt Fleming
1 sibling, 0 replies; 15+ messages in thread
From: Al Viro @ 2013-02-11 15:37 UTC (permalink / raw)
To: Matt Fleming
Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, Lingzhu Xiang, Matthew Garrett,
Jeremy Kerr, Matt Fleming
On Mon, Feb 11, 2013 at 03:22:21PM +0000, Al Viro wrote:
> > +static int efivarfs_d_compare(const struct dentry *parent, const struct inode *pinode,
> > + const struct dentry *dentry, const struct inode *inode,
> > + unsigned int len, const char *str,
> > + const struct qstr *name)
> > +{
> > + const char *q;
> > + int guid;
> > +
> > + /*
> > + * If the string we're being asked to compare doesn't match
> > + * the expected format return "no match".
> > + */
> > + if (!efivarfs_valid_name(str, len))
> > + return 1;
> > + if (!(q = strchr(name->name, '-')))
> > + return 1;
>
> No. Why check that again, when we'd already called ->d_hash() on the
> incoming name *and* candidate dentry? And buggered off on any potential
> errors.
>
> > +
> > + /* Find part 1, the variable name. */
> > + guid = q - (const char *)name->name;
>
> No need to do strchr() for that - you know that name passes
> efivarfs_valid_name(), so you know how far from the end will GUID part begin.
>
> > + /* Case-sensitive compare for the variable name */
> > + if (memcmp(str, name->name, guid))
> > + return 1;
... and by the way, you need to compare lengths first, or that memcmp()
risks running out of mapped page. Sure, it's NUL-terminated, but memcmp()
is *not* required to compare left-to-right; it's arch-dependent and the
very first memory access have every right to be at str + guid - 1.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] efivarfs: guid part of filenames are case-insensitive
[not found] ` <20130211152221.GL4503-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
2013-02-11 15:37 ` Al Viro
@ 2013-02-11 16:05 ` Matt Fleming
[not found] ` <20130211160557.GB26681-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
1 sibling, 1 reply; 15+ messages in thread
From: Matt Fleming @ 2013-02-11 16:05 UTC (permalink / raw)
To: Al Viro
Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, Lingzhu Xiang, Matthew Garrett,
Jeremy Kerr, Matt Fleming
On Mon, 11 Feb, at 03:22:21PM, Al Viro wrote:
> > + /*
> > + * If the string we're being asked to compare doesn't match
> > + * the expected format return "no match".
> > + */
> > + if (!efivarfs_valid_name(str, len))
> > + return 1;
> > + if (!(q = strchr(name->name, '-')))
> > + return 1;
>
> No. Why check that again, when we'd already called ->d_hash() on the
> incoming name *and* candidate dentry? And buggered off on any potential
> errors.
Good point.
> > +
> > + /* Find part 1, the variable name. */
> > + guid = q - (const char *)name->name;
>
> No need to do strchr() for that - you know that name passes
> efivarfs_valid_name(), so you know how far from the end will GUID part begin.
Right.
> > + /* Case-sensitive compare for the variable name */
> > + if (memcmp(str, name->name, guid))
> > + return 1;
> > +
> > + /* Case-insensitive compare for the GUID */
> > + return strcasecmp(&name->name[guid], &str[guid]);
> > +}
>
> > +static int efivarfs_d_hash(const struct dentry *dentry,
> > + const struct inode *inode, struct qstr *qstr)
> > +{
> Egads, man...
> [snip the horror with copying the name]
>
> unsigned long hash = init_name_hash();
> const unsigned char *s = qstr->name;
> int len = qstr->len;
>
> if (!efivarfs_valid_name(s, len))
> return -EINVAL;
> while (len-- > GUID_LEN)
> hash = partial_name_hash(*s++, hash);
> /* GUID is case-insensitive. */
> while (len--)
> hash = partial_name_hash(tolower(*s++), hash);
> return end_name_hash(hash);
Oh, wow, yes that is much nicer. I didn't realise we could build the
hash incrementally like that. Very cool.
--
Matt Fleming, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] efivarfs: guid part of filenames are case-insensitive
[not found] ` <20130211160557.GB26681-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
@ 2013-02-11 17:30 ` Al Viro
[not found] ` <20130211173057.GM4503-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
0 siblings, 1 reply; 15+ messages in thread
From: Al Viro @ 2013-02-11 17:30 UTC (permalink / raw)
To: Matt Fleming
Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, Lingzhu Xiang, Matthew Garrett,
Jeremy Kerr, Matt Fleming
On Mon, Feb 11, 2013 at 04:05:57PM +0000, Matt Fleming wrote:
> > Egads, man...
> > [snip the horror with copying the name]
> >
> > unsigned long hash = init_name_hash();
> > const unsigned char *s = qstr->name;
> > int len = qstr->len;
> >
> > if (!efivarfs_valid_name(s, len))
> > return -EINVAL;
> > while (len-- > GUID_LEN)
> > hash = partial_name_hash(*s++, hash);
> > /* GUID is case-insensitive. */
> > while (len--)
> > hash = partial_name_hash(tolower(*s++), hash);
> > return end_name_hash(hash);
>
> Oh, wow, yes that is much nicer. I didn't realise we could build the
> hash incrementally like that. Very cool.
... except that it should end with qstr->hash = end_name_hash(hash); return 0;
instead. My apologies.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2] efivarfs: guid part of filenames are case-insensitive
[not found] ` <20130211173057.GM4503-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
@ 2013-02-12 12:31 ` Matt Fleming
0 siblings, 0 replies; 15+ messages in thread
From: Matt Fleming @ 2013-02-12 12:31 UTC (permalink / raw)
To: Al Viro
Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, Lingzhu Xiang, Matthew Garrett,
Jeremy Kerr, Matt Fleming
On Mon, 11 Feb, at 05:30:57PM, Al Viro wrote:
> On Mon, Feb 11, 2013 at 04:05:57PM +0000, Matt Fleming wrote:
> > > Egads, man...
> > > [snip the horror with copying the name]
> > >
> > > unsigned long hash = init_name_hash();
> > > const unsigned char *s = qstr->name;
> > > int len = qstr->len;
> > >
> > > if (!efivarfs_valid_name(s, len))
> > > return -EINVAL;
> > > while (len-- > GUID_LEN)
> > > hash = partial_name_hash(*s++, hash);
> > > /* GUID is case-insensitive. */
> > > while (len--)
> > > hash = partial_name_hash(tolower(*s++), hash);
> > > return end_name_hash(hash);
> >
> > Oh, wow, yes that is much nicer. I didn't realise we could build the
> > hash incrementally like that. Very cool.
>
> ... except that it should end with qstr->hash = end_name_hash(hash); return 0;
> instead. My apologies.
Oh, efivarfs also needs to stop using d_alloc_name(), which calls
full_name_hash(), because we now need to use our fs-specific hash
function.
Updated versions of both patches coming shortly.
--
Matt Fleming, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH 1/2 v2] efivarfs: Validate filenames much more aggressively
[not found] ` <1360592935-26026-2-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2013-02-11 15:01 ` Al Viro
@ 2013-02-12 12:36 ` Matt Fleming
1 sibling, 0 replies; 15+ messages in thread
From: Matt Fleming @ 2013-02-12 12:36 UTC (permalink / raw)
To: linux-efi-u79uwXL29TY76Z2rM5mHXA
Cc: Lingzhu Xiang, Matthew Garrett, Jeremy Kerr, Al Viro, Matt Fleming
The only thing that efivarfs does to enforce a valid filename is
ensure that the name isn't too short. We need to strongly sanitise any
filenames, not least because variable creation is delayed until
efivarfs_file_write(), which means we can't rely on the firmware to
inform us of an invalid name, because if the file is never written to
we'll never know it's invalid.
Perform a couple of steps before agreeing to create a new file,
* Ensure the GUID only contains hexadecimal digits and dashes.
* Ensure that the GUID portion of the filename is the correct length
and format.
* The variable name portion of the filename needs to be at least one
character in size.
Reported-by: Lingzhu Xiang <lxiang-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Cc: Matthew Garrett <mjg59-1xO5oi07KQx4cg9Nei1l7Q@public.gmane.org>
Cc: Jeremy Kerr <jeremy.kerr-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
Cc: Al Viro <viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
Signed-off-by: Matt Fleming <matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
v2: Use Al's much improve filename parsing code and make
efivarfs_valid_name() return the more natural boolean type.
drivers/firmware/efivars.c | 49 +++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 44 insertions(+), 5 deletions(-)
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 371c441..868cea5 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -79,6 +79,7 @@
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/pstore.h>
+#include <linux/ctype.h>
#include <linux/fs.h>
#include <linux/ramfs.h>
@@ -900,6 +901,48 @@ static struct inode *efivarfs_get_inode(struct super_block *sb,
return inode;
}
+/*
+ * Return true if 'str' is a valid efivarfs filename of the form,
+ *
+ * VariableName-12345678-1234-1234-1234-1234567891bc
+ */
+static bool efivarfs_valid_name(const char *str, int len)
+{
+ static const char dashes[GUID_LEN] = {
+ [8] = 1, [13] = 1, [18] = 1, [23] = 1
+ };
+ const char *s = str + len - GUID_LEN;
+ int i;
+
+ /*
+ * We need a GUID, plus at least one letter for the variable name,
+ * plus the '-' separator
+ */
+ if (len < GUID_LEN + 2)
+ return false;
+
+ /* GUID should be right after the first '-' */
+ if (s - 1 != strchr(str, '-'))
+ return false;
+
+ /*
+ * Validate that 's' is of the correct format, e.g.
+ *
+ * 12345678-1234-1234-1234-123456789abc
+ */
+ for (i = 0; i < GUID_LEN; i++) {
+ if (dashes[i]) {
+ if (*s++ != '-')
+ return false;
+ } else {
+ if (!isxdigit(*s++))
+ return false;
+ }
+ }
+
+ return true;
+}
+
static void efivarfs_hex_to_guid(const char *str, efi_guid_t *guid)
{
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,
struct efivar_entry *var;
int namelen, i = 0, err = 0;
- /*
- * We need a GUID, plus at least one letter for the variable name,
- * plus the '-' separator
- */
- if (dentry->d_name.len < GUID_LEN + 2)
+ if (!efivarfs_valid_name(dentry->d_name.name, dentry->d_name.len))
return -EINVAL;
inode = efivarfs_get_inode(dir->i_sb, dir, mode, 0);
--
1.7.11.7
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PATCH 2/2 v2] efivarfs: guid part of filenames are case-insensitive
[not found] ` <1360592935-26026-3-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2013-02-11 15:22 ` Al Viro
@ 2013-02-12 12:39 ` Matt Fleming
[not found] ` <20130212123934.GC14790-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
1 sibling, 1 reply; 15+ messages in thread
From: Matt Fleming @ 2013-02-12 12:39 UTC (permalink / raw)
To: linux-efi-u79uwXL29TY76Z2rM5mHXA
Cc: Lingzhu Xiang, Matthew Garrett, Jeremy Kerr, Al Viro, Matt Fleming
It makes no sense to treat the following filenames as unique,
VarName-abcdefab-abcd-abcd-abcd-abcdefabcdef
VarName-ABCDEFAB-ABCD-ABCD-ABCD-ABCDEFABCDEF
VarName-ABcDEfAB-ABcD-ABcD-ABcD-ABcDEfABcDEf
VarName-aBcDEfAB-aBcD-aBcD-aBcD-aBcDEfaBcDEf
... etc ...
since the guid will be converted into a binary representation, which
has no case.
Roll our own dentry operations so that we can treat the variable name
part of filenames ("VarName" in the above example) as case-sensitive,
but the guid portion as case-insensitive. That way, efivarfs will
refuse to create the above files if any one already exists.
Reported-by: Lingzhu Xiang <lxiang-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Cc: Matthew Garrett <mjg59-1xO5oi07KQx4cg9Nei1l7Q@public.gmane.org>
Cc: Jeremy Kerr <jeremy.kerr-Z7WLFzj8eWMS+FvcfC7Uqw@public.gmane.org>
Cc: Al Viro <viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
Signed-off-by: Matt Fleming <matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
v2: Use Al's non-eye-watering code for calculating the hash. Optimise
efivarfs_d_compare() slightly by firstly checking whether the
string lens match, this also avoids a possible out-of-bounds
condition when performing the memcmp().
drivers/firmware/efivars.c | 95 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 93 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 868cea5..5d055dc 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -1043,6 +1043,84 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry)
return -EINVAL;
};
+/*
+ * Compare two efivarfs file names.
+ *
+ * An efivarfs filename is composed of two parts,
+ *
+ * 1. A case-sensitive variable name
+ * 2. A case-insensitive GUID
+ *
+ * So we need to perform a case-sensitive match on part 1 and a
+ * case-insensitive match on part 2.
+ */
+static int efivarfs_d_compare(const struct dentry *parent, const struct inode *pinode,
+ const struct dentry *dentry, const struct inode *inode,
+ unsigned int len, const char *str,
+ const struct qstr *name)
+{
+ int guid = len - GUID_LEN;
+
+ if (name->len != len)
+ return 1;
+
+ /* Case-sensitive compare for the variable name */
+ if (memcmp(str, name->name, guid))
+ return 1;
+
+ /* Case-insensitive compare for the GUID */
+ return strcasecmp(name->name + guid, str + guid);
+}
+
+static int efivarfs_d_hash(const struct dentry *dentry,
+ const struct inode *inode, struct qstr *qstr)
+{
+ unsigned long hash = init_name_hash();
+ const unsigned char *s = qstr->name;
+ unsigned int len = qstr->len;
+
+ if (!efivarfs_valid_name(s, len))
+ return -EINVAL;
+
+ while (len-- > GUID_LEN)
+ hash = partial_name_hash(*s++, hash);
+
+ /* GUID is case-insensitive. */
+ while (len--)
+ hash = partial_name_hash(tolower(*s++), hash);
+
+ qstr->hash = end_name_hash(hash);
+ return 0;
+}
+
+/*
+ * Retaining negative dentries for an in-memory filesystem just wastes
+ * memory and lookup time: arrange for them to be deleted immediately.
+ */
+static int efivarfs_delete_dentry(const struct dentry *dentry)
+{
+ return 1;
+}
+
+static struct dentry_operations efivarfs_d_ops = {
+ .d_compare = efivarfs_d_compare,
+ .d_hash = efivarfs_d_hash,
+ .d_delete = efivarfs_delete_dentry,
+};
+
+static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name)
+{
+ struct qstr q;
+
+ q.name = name;
+ q.len = strlen(name);
+
+ if (efivarfs_d_hash(NULL, NULL, &q))
+ return NULL;
+
+ return d_alloc(parent, &q);
+}
+
static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
{
struct inode *inode = NULL;
@@ -1058,6 +1136,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
sb->s_magic = EFIVARFS_MAGIC;
sb->s_op = &efivarfs_ops;
+ sb->s_d_op = &efivarfs_d_ops;
sb->s_time_gran = 1;
inode = efivarfs_get_inode(sb, NULL, S_IFDIR | 0755, 0);
@@ -1098,7 +1177,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
if (!inode)
goto fail_name;
- dentry = d_alloc_name(root, name);
+ dentry = efivarfs_alloc_dentry(root, name);
if (!dentry)
goto fail_inode;
@@ -1148,8 +1227,20 @@ static struct file_system_type efivarfs_type = {
.kill_sb = efivarfs_kill_sb,
};
+/*
+ * Handle negative dentry.
+ */
+static struct dentry *efivarfs_lookup(struct inode *dir, struct dentry *dentry,
+ unsigned int flags)
+{
+ if (dentry->d_name.len > NAME_MAX)
+ return ERR_PTR(-ENAMETOOLONG);
+ d_add(dentry, NULL);
+ return NULL;
+}
+
static const struct inode_operations efivarfs_dir_inode_operations = {
- .lookup = simple_lookup,
+ .lookup = efivarfs_lookup,
.unlink = efivarfs_unlink,
.create = efivarfs_create,
};
--
1.7.11.7
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2 v2] efivarfs: guid part of filenames are case-insensitive
[not found] ` <20130212123934.GC14790-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
@ 2013-02-14 16:04 ` Al Viro
[not found] ` <20130214160405.GU4503-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
0 siblings, 1 reply; 15+ messages in thread
From: Al Viro @ 2013-02-14 16:04 UTC (permalink / raw)
To: Matt Fleming
Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, Lingzhu Xiang, Matthew Garrett,
Jeremy Kerr, Matt Fleming
On Tue, Feb 12, 2013 at 12:39:34PM +0000, Matt Fleming wrote:
> +static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name)
> +{
> + struct qstr q;
> +
> + q.name = name;
> + q.len = strlen(name);
> +
> + if (efivarfs_d_hash(NULL, NULL, &q))
> + return NULL;
> +
> + return d_alloc(parent, &q);
> +}
> @@ -1098,7 +1177,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
> if (!inode)
> goto fail_name;
>
> - dentry = d_alloc_name(root, name);
> + dentry = efivarfs_alloc_dentry(root, name);
> if (!dentry)
> goto fail_inode;
Umm... That name has just been built by efivarfs_fill_super() itself, and
AFAICS there's no way for its GUID part to be _not_ lowercase
hex and with proper locations of dashes. So
a) hash value will be exactly full_name_hash(name), unless
efivarfs_valid_name() manages to fail.
b) efivarfs_valid_name() is a serious overkill here - the only things
that might go wrong are length of and dashes in entry->var.VariableName.
Both are trivially checked while we are constructing name (before we do
inode allocation, etc.) and IMO they would be better off there.
IOW, I think this part of the patch is better handled by doing those two
checks several lines before d_alloc_name() and not bothering with
efivarfs_alloc_dentry() at all. I.e.
if (len + 1 + GUID_LEN > NAME_MAX)
goto fail;
name = kmalloc(len + 1 + GUID_LEN + 1, GFP_ATOMIC);
if (!name)
goto fail;
for (i = 0; i < len; i++) {
name[i] = entry->var.VariableName[i] & 0xFF;
if (name[i] == '-')
goto fail_name;
}
and then as in the current efivarfs_fill_super().
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2 v2] efivarfs: guid part of filenames are case-insensitive
[not found] ` <20130214160405.GU4503-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
@ 2013-02-14 17:11 ` Matt Fleming
[not found] ` <1360861876.24917.52.camel-ZqTwcBeJ+wsBof6jY8KHXm7IUlhRatedral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
0 siblings, 1 reply; 15+ messages in thread
From: Matt Fleming @ 2013-02-14 17:11 UTC (permalink / raw)
To: Al Viro
Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, Lingzhu Xiang, Matthew Garrett,
Jeremy Kerr
On Thu, 2013-02-14 at 16:04 +0000, Al Viro wrote:
> On Tue, Feb 12, 2013 at 12:39:34PM +0000, Matt Fleming wrote:
>
> > +static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name)
> > +{
> > + struct qstr q;
> > +
> > + q.name = name;
> > + q.len = strlen(name);
> > +
> > + if (efivarfs_d_hash(NULL, NULL, &q))
> > + return NULL;
> > +
> > + return d_alloc(parent, &q);
> > +}
>
> > @@ -1098,7 +1177,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
> > if (!inode)
> > goto fail_name;
> >
> > - dentry = d_alloc_name(root, name);
> > + dentry = efivarfs_alloc_dentry(root, name);
> > if (!dentry)
> > goto fail_inode;
>
> Umm... That name has just been built by efivarfs_fill_super() itself, and
> AFAICS there's no way for its GUID part to be _not_ lowercase
> hex and with proper locations of dashes. So
> a) hash value will be exactly full_name_hash(name), unless
> efivarfs_valid_name() manages to fail.
In my testing calling full_name_hash() and doing the partial_name_hash()
loop returned different results. This is on x86, with
CONFIG_DCACHE_WORD_ACCESS=y. I assumed they weren't compatible because
most (all?) file systems that do fs-specific hashing also fill out the
hash member using their fs-specific function, whereas efivarfs was
previously using d_alloc_name().
Is this mismatch indicative of a bug in efivarfs hashing?
--
Matt Fleming, Intel Open Source Technology Center
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH 2/2 v2] efivarfs: guid part of filenames are case-insensitive
[not found] ` <1360861876.24917.52.camel-ZqTwcBeJ+wsBof6jY8KHXm7IUlhRatedral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
@ 2013-02-14 17:55 ` Al Viro
0 siblings, 0 replies; 15+ messages in thread
From: Al Viro @ 2013-02-14 17:55 UTC (permalink / raw)
To: Matt Fleming
Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA, Lingzhu Xiang, Matthew Garrett,
Jeremy Kerr
On Thu, Feb 14, 2013 at 05:11:16PM +0000, Matt Fleming wrote:
> On Thu, 2013-02-14 at 16:04 +0000, Al Viro wrote:
> > On Tue, Feb 12, 2013 at 12:39:34PM +0000, Matt Fleming wrote:
> >
> > > +static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name)
> > > +{
> > > + struct qstr q;
> > > +
> > > + q.name = name;
> > > + q.len = strlen(name);
> > > +
> > > + if (efivarfs_d_hash(NULL, NULL, &q))
> > > + return NULL;
> > > +
> > > + return d_alloc(parent, &q);
> > > +}
> >
> > > @@ -1098,7 +1177,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent)
> > > if (!inode)
> > > goto fail_name;
> > >
> > > - dentry = d_alloc_name(root, name);
> > > + dentry = efivarfs_alloc_dentry(root, name);
> > > if (!dentry)
> > > goto fail_inode;
> >
> > Umm... That name has just been built by efivarfs_fill_super() itself, and
> > AFAICS there's no way for its GUID part to be _not_ lowercase
> > hex and with proper locations of dashes. So
> > a) hash value will be exactly full_name_hash(name), unless
> > efivarfs_valid_name() manages to fail.
>
> In my testing calling full_name_hash() and doing the partial_name_hash()
> loop returned different results. This is on x86, with
> CONFIG_DCACHE_WORD_ACCESS=y. I assumed they weren't compatible because
> most (all?) file systems that do fs-specific hashing also fill out the
> hash member using their fs-specific function, whereas efivarfs was
> previously using d_alloc_name().
>
> Is this mismatch indicative of a bug in efivarfs hashing?
No, just me forgetting about DCACHE_WORD_ACCESS. Nevermind...
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2013-02-14 17:55 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-02-11 14:28 [PATCH 0/2] efivarfs patch queue Matt Fleming
[not found] ` <1360592935-26026-1-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2013-02-11 14:28 ` [PATCH 1/2] efivarfs: Validate filenames much more aggressively Matt Fleming
[not found] ` <1360592935-26026-2-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2013-02-11 15:01 ` Al Viro
[not found] ` <20130211150109.GK4503-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
2013-02-11 15:12 ` Matt Fleming
2013-02-12 12:36 ` [PATCH 1/2 v2] " Matt Fleming
2013-02-11 14:28 ` [PATCH 2/2] efivarfs: guid part of filenames are case-insensitive Matt Fleming
[not found] ` <1360592935-26026-3-git-send-email-matt-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2013-02-11 15:22 ` Al Viro
[not found] ` <20130211152221.GL4503-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
2013-02-11 15:37 ` Al Viro
2013-02-11 16:05 ` Matt Fleming
[not found] ` <20130211160557.GB26681-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2013-02-11 17:30 ` Al Viro
[not found] ` <20130211173057.GM4503-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
2013-02-12 12:31 ` Matt Fleming
2013-02-12 12:39 ` [PATCH 2/2 v2] " Matt Fleming
[not found] ` <20130212123934.GC14790-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2013-02-14 16:04 ` Al Viro
[not found] ` <20130214160405.GU4503-3bDd1+5oDREiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
2013-02-14 17:11 ` Matt Fleming
[not found] ` <1360861876.24917.52.camel-ZqTwcBeJ+wsBof6jY8KHXm7IUlhRatedral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2013-02-14 17:55 ` Al Viro
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.