All of lore.kernel.org
 help / color / mirror / Atom feed
From: Heinrich Schuchardt <xypron.glpk@gmx.de>
To: u-boot@lists.denx.de
Subject: [PATCH 2/6] efi_loader: Add device path related functions for initrd via Boot####
Date: Thu, 11 Mar 2021 12:00:32 +0100	[thread overview]
Message-ID: <3c7bca26-b4d6-88c5-611a-aaca1f224d39@gmx.de> (raw)
In-Reply-To: <YEnelLeeLrnZYwcl@apalos.home>

On 11.03.21 10:10, Ilias Apalodimas wrote:
> On Thu, Mar 11, 2021 at 08:50:22AM +0100, Heinrich Schuchardt wrote:
>> On 3/5/21 11:22 PM, Ilias Apalodimas wrote:
>>> On the following patches we allow for an initrd path to be stored in
>>> Boot#### variables.  Specifically we encode in the FIlePathList[] of
>>> the EFI_LOAD_OPTIONS for each Boot#### variable.
>>>
>>> The FilePathList[] array looks like this:
>>> kernel - 0xff - VenMedia(initrd GUID) - 0x01 - initrd1 - 0x01 initrd2 -0xff
>>> So let's add the relevant functions to concatenate and retrieve a device
>>> path based on a Vendor GUID.
>>>
>>> Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
>>> ---
>>>   include/efi_loader.h             |  4 ++
>>>   lib/efi_loader/efi_device_path.c | 72 ++++++++++++++++++++++++++++++++
>>>   2 files changed, 76 insertions(+)
>>>
>>> diff --git a/include/efi_loader.h b/include/efi_loader.h
>>> index f470bbd636f4..eb11a8c7d4b1 100644
>>> --- a/include/efi_loader.h
>>> +++ b/include/efi_loader.h
>>> @@ -738,6 +738,10 @@ struct efi_load_option {
>>>   	const u8 *optional_data;
>>>   };
>>>
>>> +struct efi_device_path *efi_dp_from_lo(struct efi_load_option *lo,
>>> +				       efi_uintn_t *size, efi_guid_t guid);
>>> +struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1,
>>> +				      const struct efi_device_path *dp2);
>>>   efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
>>>   					 efi_uintn_t *size);
>>>   unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data);
>>> diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c
>>> index c9315dd45857..cf1321828e87 100644
>>> --- a/lib/efi_loader/efi_device_path.c
>>> +++ b/lib/efi_loader/efi_device_path.c
>>> @@ -310,6 +310,41 @@ struct efi_device_path *efi_dp_append(const struct efi_device_path *dp1,
>>>   	return ret;
>>>   }
>>>
>>> +/** efi_dp_concat() - Concatenate 2 device paths. The final device path will contain
>>> + *                    two device paths separated by and end node (0xff).
>>> + *
>>> + * @dp1:	First device path
>>> + * @size:	Second device path
>>> + *
>>> + * Return:	concatenated device path or NULL. Caller must free the returned value
>>> + */
>>> +struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1,
>>> +				      const struct efi_device_path *dp2)
>>> +{
>>> +	struct efi_device_path *ret;
>>> +	efi_uintn_t sz1, sz2;
>>> +	void *p;
>>> +
>>> +	if (!dp1 || !dp2)
>>> +		return NULL;
>>> +	sz1 = efi_dp_size(dp1);
>>> +	sz2 = efi_dp_size(dp2);
>>> +	p = dp_alloc(sz1 + sz2 + (2 * sizeof(END)));
>>> +	/* both dp1 and dp2 are non-null */
>>> +	if (!p)
>>> +		return NULL;
>>> +	ret = p;
>>> +	memcpy(p, dp1, sz1);
>>> +	p += sz1;
>>> +	memcpy(p, &END, sizeof(END));
>>> +	p += sizeof(END);
>>> +	memcpy(p, dp2, sz2);
>>> +	p += sz2;
>>> +	memcpy(p, &END, sizeof(END));
>>> +
>>> +	return ret;
>>> +}
>>> +
>>>   struct efi_device_path *efi_dp_append_node(const struct efi_device_path *dp,
>>>   					   const struct efi_device_path *node)
>>>   {
>>> @@ -1160,3 +1195,40 @@ ssize_t efi_dp_check_length(const struct efi_device_path *dp,
>>>   		dp = (const struct efi_device_path *)((const u8 *)dp + len);
>>>   	}
>>>   }
>>> +
>>> +/**
>>> + * efi_dp_from_lo() - Get the instance of a Vendor Device Path
>>> + *		      in a multi-instance device path that matches
>>> + *		      a specific GUID
>>
>> The description does make it clear that you are looking for a VenMedia()
>> node.
>>
>> Please, describe what the function is good for (find the device path for
>> an initrd or dtb in a load option).
>>
>
> Ok
>
>>> + *
>>> + * @load_option: device paths to search
>>> + * @size:	 size of the discovered device path
>>> + * @guid:	 guid to search for
>>> + *
>>> + * Return:	device path or NULL. Caller must free the returned value
>>
>> Please, keep the text aligned.
>>
>> Do we need a copy? Isn't a pointer good enough?
>
> A pointer to what?
> I think it's better to a copy here. This is a device path that might be used
> out of a stack context were the load option might disappear.
> Look at how the function is used in efi_get_dp_from_boot().

You are duplicating in get_initrd_fp(). Why should we duplicate twice?

>
>>
>>> + */
>>> +struct
>>> +efi_device_path *efi_dp_from_lo(struct efi_load_option *lo,
>>> +				efi_uintn_t *size, efi_guid_t guid)
>>> +{
>>> +	struct efi_device_path *fp = lo->file_path;
>>> +	struct efi_device_path_vendor *vendor;
>>> +	int lo_len = lo->file_path_length;
>>> +
>>> +	while (lo_len) {
>>
>> lo_len must be at least sizeof(struct efi_device_path).
>>
>>> +		if (fp->type != DEVICE_PATH_TYPE_MEDIA_DEVICE ||
>>> +		    fp->sub_type != DEVICE_PATH_SUB_TYPE_VENDOR_PATH) {
>>> +			lo_len -= fp->length;
>>
>> Could the last device path in the array be followed by zero bytes for
>> padding?
>
> How? Device paths are packed aren't they ?
>
>> Should we check that fp->length >= sizeof(struct efi_device_path)?
>
> Yea probably a good idea

The content of the boot option comes from the user. Just assume that it
can contain malicious content.

We should also check that the identified device-path starting at
VenMedia() ends within fp->length using efi_dp_check_length().

>
>>
>>> +			fp = (void *)fp + fp->length;
>>
>> Please, avoid code duplication.
>>
>> E.g.
>>
>> for (; lo_len >= sizeof(struct efi_device_path);
>>      lo_len -= fp->length, fp = (void *)fp + fp->length) {
>
> I can an switch to that, but I really never liked this format.
> It always seemed way less readable to me for some reason.  Maybe because I
> never got used to it ...

Using "for" is only one option. You could use "goto next;" instead.

>
>>
>>> +			continue;
>>> +		}
>>> +
>>> +		vendor = (struct efi_device_path_vendor *)fp;
>>> +		if (!guidcmp(&vendor->guid, &guid))
>>> +			return efi_dp_dup(fp);
>>
>> Should we strip of the VenMedia() node here?
>
> Why? This is not supposed to get the file path. The function says "get device
> path from load option" and that device includes the VenMedia node.
> It would make more sense for me to strip in efi_get_dp_from_boot() for
> example, if you want a helper function to get the initrd path *only*.

The VenMedia() node is not needed anymore once you have found the entry.

>
> But really it's just one invocation of efi_dp_get_next_instance() after
> whatever device path you get. Which also modifies the device path pointer, so
> I'd really prefer keeping that call in a local context.

Why next instance? I thought next node.

My understanding is that we have:

kernel path,end(0xff),
VenMedia(), /* no end node here */
initrd1, end(0x01),
initrd2, end(0xff)

Please, document the structure.

Best regards

Heinrich

  reply	other threads:[~2021-03-11 11:00 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-05 22:22 [PATCH 1/6] efi_selftest: Remove loadfile2 for initrd selftests Ilias Apalodimas
2021-03-05 22:22 ` [PATCH 2/6] efi_loader: Add device path related functions for initrd via Boot#### Ilias Apalodimas
2021-03-11  7:50   ` Heinrich Schuchardt
2021-03-11  9:10     ` Ilias Apalodimas
2021-03-11 11:00       ` Heinrich Schuchardt [this message]
2021-03-11 11:36         ` Ilias Apalodimas
2021-03-11 11:44           ` Heinrich Schuchardt
2021-03-11 12:31             ` Heinrich Schuchardt
2021-03-11 12:39               ` Ilias Apalodimas
2021-03-11 12:44                 ` Heinrich Schuchardt
2021-03-11 12:49                   ` Ilias Apalodimas
2021-03-11 13:31             ` Ilias Apalodimas
2021-03-11 20:25               ` Heinrich Schuchardt
2021-03-12  2:50           ` AKASHI Takahiro
2021-03-12  4:10             ` Ilias Apalodimas
2021-03-12  4:32               ` AKASHI Takahiro
2021-03-12  4:42                 ` Ilias Apalodimas
2021-03-12  5:02                   ` AKASHI Takahiro
2021-03-12  5:19                     ` Ilias Apalodimas
2021-03-05 22:22 ` [PATCH 3/6] efi_loader: Introduce helper functions for EFI Ilias Apalodimas
2021-03-11  9:15   ` Heinrich Schuchardt
2021-03-05 22:23 ` [PATCH 4/6] efi_loader: Replace config option for initrd loading Ilias Apalodimas
2021-03-11 12:23   ` Heinrich Schuchardt
2021-03-11 12:30     ` Ilias Apalodimas
2021-03-11 12:50       ` Heinrich Schuchardt
2021-03-05 22:23 ` [PATCH 5/6] efidebug: add multiple device path instances on Boot#### Ilias Apalodimas
2021-03-11 12:38   ` Heinrich Schuchardt
2021-03-11 12:42     ` Ilias Apalodimas
2021-03-12  4:44   ` AKASHI Takahiro
2021-03-12  4:55     ` Ilias Apalodimas
2021-03-12  5:23       ` AKASHI Takahiro
2021-03-12  5:37         ` Ilias Apalodimas
2021-03-12  5:58           ` AKASHI Takahiro
2021-03-12  7:19             ` Ilias Apalodimas
2021-03-12 16:25     ` Heinrich Schuchardt
2021-03-05 22:23 ` [PATCH 6/6] doc: Update uefi documentation for initrd loading options Ilias Apalodimas
2021-03-11 12:39   ` Heinrich Schuchardt
2021-03-11  7:26 ` [PATCH 1/6] efi_selftest: Remove loadfile2 for initrd selftests Heinrich Schuchardt
2021-03-13 21:47 [PATCH 0/6 v2] Loadfile2 for initrd loading Ilias Apalodimas
2021-03-13 21:47 ` [PATCH 2/6] efi_loader: Add device path related functions for initrd via Boot#### Ilias Apalodimas
2021-03-14  7:19   ` Heinrich Schuchardt
2021-03-14  7:32     ` Ilias Apalodimas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3c7bca26-b4d6-88c5-611a-aaca1f224d39@gmx.de \
    --to=xypron.glpk@gmx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.