From: Gary Lin <glin@suse.com>
To: Jiaxin Wu <Jiaxin.wu@intel.com>
Cc: edk2-devel@lists.01.org, Ye Ting <ting.ye@intel.com>,
Fu Siyuan <siyuan.fu@intel.com>
Subject: Re: [Patch v3] NetworkPkg/HttpDxe: Fix the bug when parsing HTTP(S) message body.
Date: Wed, 4 Jul 2018 10:14:00 +0800 [thread overview]
Message-ID: <20180704021400.rbmil3o6dm3m5rxb@GaryWorkstation> (raw)
In-Reply-To: <20180704004052.4560-1-Jiaxin.wu@intel.com>
On Wed, Jul 04, 2018 at 08:40:52AM +0800, Jiaxin Wu wrote:
> *v2: Resolve the conflict commit.
>
> *v3: Fixed the failure if BodyLength in HTTP token is less than the received
> size of HTTPS message.
>
> HttpBodyParserCallback function is to parse the HTTP(S) message body so as to
> confirm whether there is the next message header. But it doesn't record the
> parsing message data/length correctly.
>
> This patch is refine the parsing logic so as to fix the potential failure.
>
> Cc: Ye Ting <ting.ye@intel.com>
> Cc: Fu Siyuan <siyuan.fu@intel.com>
> Cc: Gary Lin <glin@suse.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Wu Jiaxin <jiaxin.wu@intel.com>
> Tested-by: Gary Lin <glin@suse.com>
Thanks for the patch. I've tested this patch with shim and grub2 from
SLE15 GM, and they worked as expected. A crash in grub2 https connection is
also gone after applying this patch.
Thanks,
Gary Lin
> ---
> NetworkPkg/HttpDxe/HttpImpl.c | 112 +++++++++++++++++----------------
> NetworkPkg/HttpDxe/HttpProto.c | 10 +++
> NetworkPkg/HttpDxe/HttpProto.h | 10 +++
> 3 files changed, 78 insertions(+), 54 deletions(-)
>
> diff --git a/NetworkPkg/HttpDxe/HttpImpl.c b/NetworkPkg/HttpDxe/HttpImpl.c
> index f70e116f38..17deceb395 100644
> --- a/NetworkPkg/HttpDxe/HttpImpl.c
> +++ b/NetworkPkg/HttpDxe/HttpImpl.c
> @@ -914,10 +914,11 @@ HttpBodyParserCallback (
> IN CHAR8 *Data,
> IN UINTN Length,
> IN VOID *Context
> )
> {
> + HTTP_CALLBACK_DATA *CallbackData;
> HTTP_TOKEN_WRAP *Wrap;
> UINTN BodyLength;
> CHAR8 *Body;
>
> if (EventType != BodyParseEventOnComplete) {
> @@ -926,25 +927,22 @@ HttpBodyParserCallback (
>
> if (Data == NULL || Length != 0 || Context == NULL) {
> return EFI_SUCCESS;
> }
>
> - Wrap = (HTTP_TOKEN_WRAP *) Context;
> - Body = Wrap->HttpToken->Message->Body;
> - BodyLength = Wrap->HttpToken->Message->BodyLength;
> + CallbackData = (HTTP_CALLBACK_DATA *) Context;
> +
> + Wrap = (HTTP_TOKEN_WRAP *) (CallbackData->Wrap);
> + Body = CallbackData->ParseData;
> + BodyLength = CallbackData->ParseDataLength;
> +
> if (Data < Body + BodyLength) {
> Wrap->HttpInstance->NextMsg = Data;
> } else {
> Wrap->HttpInstance->NextMsg = NULL;
> }
>
> -
> - //
> - // Free Tx4Token or Tx6Token since already received corrsponding HTTP response.
> - //
> - FreePool (Wrap);
> -
> return EFI_SUCCESS;
> }
>
> /**
> The work function of EfiHttpResponse().
> @@ -1189,33 +1187,43 @@ HttpResponseWorker (
> HttpInstance->Method,
> HttpMsg->Data.Response->StatusCode,
> HttpMsg->HeaderCount,
> HttpMsg->Headers,
> HttpBodyParserCallback,
> - (VOID *) ValueInItem,
> + (VOID *) (&HttpInstance->CallbackData),
> &HttpInstance->MsgParser
> );
> if (EFI_ERROR (Status)) {
> goto Error2;
> }
>
> //
> // Check whether we received a complete HTTP message.
> //
> if (HttpInstance->CacheBody != NULL) {
> + //
> + // Record the CallbackData data.
> + //
> + HttpInstance->CallbackData.Wrap = (VOID *) Wrap;
> + HttpInstance->CallbackData.ParseData = (VOID *) HttpInstance->CacheBody;
> + HttpInstance->CallbackData.ParseDataLength = HttpInstance->CacheLen;
> +
> + //
> + // Parse message with CallbackData data.
> + //
> Status = HttpParseMessageBody (HttpInstance->MsgParser, HttpInstance->CacheLen, HttpInstance->CacheBody);
> if (EFI_ERROR (Status)) {
> goto Error2;
> }
> + }
>
> - if (HttpIsMessageComplete (HttpInstance->MsgParser)) {
> - //
> - // Free the MsgParse since we already have a full HTTP message.
> - //
> - HttpFreeMsgParser (HttpInstance->MsgParser);
> - HttpInstance->MsgParser = NULL;
> - }
> + if (HttpIsMessageComplete (HttpInstance->MsgParser)) {
> + //
> + // Free the MsgParse since we already have a full HTTP message.
> + //
> + HttpFreeMsgParser (HttpInstance->MsgParser);
> + HttpInstance->MsgParser = NULL;
> }
> }
>
> if ((HttpMsg->Body == NULL) || (HttpMsg->BodyLength == 0)) {
> Status = EFI_SUCCESS;
> @@ -1330,16 +1338,30 @@ HttpResponseWorker (
> if (EFI_ERROR (Status)) {
> goto Error2;
> }
>
> //
> - // Check whether we receive a complete HTTP message.
> + // Process the received the body packet.
> + //
> + HttpMsg->BodyLength = MIN (Fragment.Len, (UINT32) HttpMsg->BodyLength);
> +
> + CopyMem (HttpMsg->Body, Fragment.Bulk, HttpMsg->BodyLength);
> +
> + //
> + // Record the CallbackData data.
> + //
> + HttpInstance->CallbackData.Wrap = (VOID *) Wrap;
> + HttpInstance->CallbackData.ParseData = HttpMsg->Body;
> + HttpInstance->CallbackData.ParseDataLength = HttpMsg->BodyLength;
> +
> + //
> + // Parse Body with CallbackData data.
> //
> Status = HttpParseMessageBody (
> HttpInstance->MsgParser,
> - (UINTN) Fragment.Len,
> - (CHAR8 *) Fragment.Bulk
> + HttpMsg->BodyLength,
> + HttpMsg->Body
> );
> if (EFI_ERROR (Status)) {
> goto Error2;
> }
>
> @@ -1350,50 +1372,32 @@ HttpResponseWorker (
> HttpFreeMsgParser (HttpInstance->MsgParser);
> HttpInstance->MsgParser = NULL;
> }
>
> //
> - // We receive part of header of next HTTP msg.
> + // Check whether there is the next message header in the HttpMsg->Body.
> //
> if (HttpInstance->NextMsg != NULL) {
> - HttpMsg->BodyLength = MIN ((UINTN) HttpInstance->NextMsg - (UINTN) Fragment.Bulk, HttpMsg->BodyLength);
> - CopyMem (HttpMsg->Body, Fragment.Bulk, HttpMsg->BodyLength);
> -
> - HttpInstance->CacheLen = Fragment.Len - HttpMsg->BodyLength;
> - if (HttpInstance->CacheLen != 0) {
> - if (HttpInstance->CacheBody != NULL) {
> - FreePool (HttpInstance->CacheBody);
> - }
> -
> - HttpInstance->CacheBody = AllocateZeroPool (HttpInstance->CacheLen);
> - if (HttpInstance->CacheBody == NULL) {
> - Status = EFI_OUT_OF_RESOURCES;
> - goto Error2;
> - }
> -
> - CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg->BodyLength, HttpInstance->CacheLen);
> - HttpInstance->CacheOffset = 0;
> + HttpMsg->BodyLength = HttpInstance->NextMsg - (CHAR8 *) HttpMsg->Body;
> + }
>
> - HttpInstance->NextMsg = HttpInstance->CacheBody + ((UINTN) HttpInstance->NextMsg - (UINTN) (Fragment.Bulk + HttpMsg->BodyLength));
> + HttpInstance->CacheLen = Fragment.Len - HttpMsg->BodyLength;
> + if (HttpInstance->CacheLen != 0) {
> + if (HttpInstance->CacheBody != NULL) {
> + FreePool (HttpInstance->CacheBody);
> }
> - } else {
> - HttpMsg->BodyLength = MIN (Fragment.Len, (UINT32) HttpMsg->BodyLength);
> - CopyMem (HttpMsg->Body, Fragment.Bulk, HttpMsg->BodyLength);
> - HttpInstance->CacheLen = Fragment.Len - HttpMsg->BodyLength;
> - if (HttpInstance->CacheLen != 0) {
> - if (HttpInstance->CacheBody != NULL) {
> - FreePool (HttpInstance->CacheBody);
> - }
>
> - HttpInstance->CacheBody = AllocateZeroPool (HttpInstance->CacheLen);
> - if (HttpInstance->CacheBody == NULL) {
> - Status = EFI_OUT_OF_RESOURCES;
> - goto Error2;
> - }
> + HttpInstance->CacheBody = AllocateZeroPool (HttpInstance->CacheLen);
> + if (HttpInstance->CacheBody == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto Error2;
> + }
>
> - CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg->BodyLength, HttpInstance->CacheLen);
> - HttpInstance->CacheOffset = 0;
> + CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg->BodyLength, HttpInstance->CacheLen);
> + HttpInstance->CacheOffset = 0;
> + if (HttpInstance->NextMsg != NULL) {
> + HttpInstance->NextMsg = HttpInstance->CacheBody;
> }
> }
>
> if (Fragment.Bulk != NULL) {
> FreePool (Fragment.Bulk);
> diff --git a/NetworkPkg/HttpDxe/HttpProto.c b/NetworkPkg/HttpDxe/HttpProto.c
> index 5356cd35c0..94f89f5665 100644
> --- a/NetworkPkg/HttpDxe/HttpProto.c
> +++ b/NetworkPkg/HttpDxe/HttpProto.c
> @@ -195,10 +195,20 @@ HttpTcpReceiveNotifyDpc (
> Length = (UINTN) Wrap->TcpWrap.Rx6Data.FragmentTable[0].FragmentLength;
> } else {
> Length = (UINTN) Wrap->TcpWrap.Rx4Data.FragmentTable[0].FragmentLength;
> }
>
> + //
> + // Record the CallbackData data.
> + //
> + HttpInstance->CallbackData.Wrap = (VOID *) Wrap;
> + HttpInstance->CallbackData.ParseData = Wrap->HttpToken->Message->Body;
> + HttpInstance->CallbackData.ParseDataLength = Length;
> +
> + //
> + // Parse Body with CallbackData data.
> + //
> Status = HttpParseMessageBody (
> HttpInstance->MsgParser,
> Length,
> Wrap->HttpToken->Message->Body
> );
> diff --git a/NetworkPkg/HttpDxe/HttpProto.h b/NetworkPkg/HttpDxe/HttpProto.h
> index cc6c1eb566..fa57dbfd39 100644
> --- a/NetworkPkg/HttpDxe/HttpProto.h
> +++ b/NetworkPkg/HttpDxe/HttpProto.h
> @@ -89,10 +89,19 @@ typedef struct {
> EFI_TLS_CONNECTION_END ConnectionEnd;
> EFI_TLS_VERIFY VerifyMethod;
> EFI_TLS_SESSION_STATE SessionState;
> } TLS_CONFIG_DATA;
>
> +//
> +// Callback data for HTTP_PARSER_CALLBACK()
> +//
> +typedef struct {
> + UINTN ParseDataLength;
> + VOID *ParseData;
> + VOID *Wrap;
> +} HTTP_CALLBACK_DATA;
> +
> typedef struct _HTTP_PROTOCOL {
> UINT32 Signature;
> EFI_HTTP_PROTOCOL Http;
> EFI_HANDLE Handle;
> HTTP_SERVICE *Service;
> @@ -147,10 +156,11 @@ typedef struct _HTTP_PROTOCOL {
>
> //
> // HTTP message-body parser.
> //
> VOID *MsgParser;
> + HTTP_CALLBACK_DATA CallbackData;
>
> EFI_HTTP_VERSION HttpVersion;
> UINT32 TimeOutMillisec;
> BOOLEAN LocalAddressIsIPv6;
>
> --
> 2.17.1.windows.2
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
>
next prev parent reply other threads:[~2018-07-04 2:14 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-07-04 0:40 [Patch v3] NetworkPkg/HttpDxe: Fix the bug when parsing HTTP(S) message body Jiaxin Wu
2018-07-04 2:14 ` Gary Lin [this message]
2018-07-04 2:21 ` Wu, Jiaxin
2018-07-05 2:20 ` Ye, Ting
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-list 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=20180704021400.rbmil3o6dm3m5rxb@GaryWorkstation \
--to=devel@edk2.groups.io \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox