diff options
author | Alexander Graf <agraf@suse.de> | 2017-12-11 14:29:46 +0100 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2017-12-16 22:51:19 +0100 |
commit | 905cb9e1720294d244bc9273c45dc76c33f6034e (patch) | |
tree | 78b292746edcc51ff54aeb0302e63d632abaf16d /lib | |
parent | 52a250afa53215190e1714ee2c858ab0bbfa0953 (diff) | |
download | u-boot-905cb9e1720294d244bc9273c45dc76c33f6034e.tar.gz |
efi_loader: Ensure efi_dp_find_obj() finds exact matches
When calling efi_dp_find_obj(), we usually want to find the *exact* match
of an object for a given device path. However, I ran into a nasty corner case
where I had the following objects with paths available:
Handle 0x9feffa70
/HardwareVendor(e61d73b9-a384-4acc-aeab-82e828f3628b)[0: ]/USB(6,0)/EndEntire
Handle 0x9feffb58
/HardwareVendor(e61d73b9-a384-4acc-aeab-82e828f3628b)[0: ]/USB(6,0)/HD(1,800,32000,2de808cb00000000,1,1)/EndEntire
and was searching for
/HardwareVendor(e61d73b9-a384-4acc-aeab-82e828f3628b)[0: ]/USB(6,0)/HD(1,800,32000,2de808cb00000000,1,1)/EndEntire
But because our device path search looked for any substring match, it would
return
/HardwareVendor(e61d73b9-a384-4acc-aeab-82e828f3628b)[0: ]/USB(6,0)/EndEntire
because that path is a full substring of the path we were searching for.
So this patch adapts the device path search logic to always look for exact
matches first. The way we distinguish between those cases is by looking at
whether our caller actually deals with remainders.
As a side effect, the code as is from all I can tell now never does a
substring match anymore, because it always gets called with rem=NULL, so
we always only do exact matches now.
Reported-by: Jonathan Gray <jsg@jsg.id.au>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/efi_loader/efi_device_path.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index b4e2f933cb..24a4f40c00 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -126,6 +126,7 @@ static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path, struct efi_device_path **rem) { struct efi_object *efiobj; + unsigned int dp_size = efi_dp_size(dp); list_for_each_entry(efiobj, &efi_obj_list, link) { struct efi_handler *handler; @@ -141,10 +142,18 @@ static struct efi_object *find_obj(struct efi_device_path *dp, bool short_path, do { if (efi_dp_match(dp, obj_dp) == 0) { if (rem) { + /* + * Allow partial matches, but inform + * the caller. + */ *rem = ((void *)dp) + efi_dp_size(obj_dp); + return efiobj; + } else { + /* Only return on exact matches */ + if (efi_dp_size(obj_dp) == dp_size) + return efiobj; } - return efiobj; } obj_dp = shorten_path(efi_dp_next(obj_dp)); @@ -164,8 +173,14 @@ struct efi_object *efi_dp_find_obj(struct efi_device_path *dp, { struct efi_object *efiobj; - efiobj = find_obj(dp, false, rem); + /* Search for an exact match first */ + efiobj = find_obj(dp, false, NULL); + /* Then for a fuzzy match */ + if (!efiobj) + efiobj = find_obj(dp, false, rem); + + /* And now for a fuzzy short match */ if (!efiobj) efiobj = find_obj(dp, true, rem); |