Hey Mike,

In contrast to setting 'BackLink' and 'ForwardLink' to dummy values such as 
EFI_BAD_POINTER, verifying that a node is part of a known list is a safe way to 
determine whether a link is still valid without needing to keep the memory 
allocated. If the Node, which had its links set to dummys, is freed, the dummy 
values may be overwriten and the check would pass despite the node being 
invalid. This can, for example, be used in OpenKabylake's PchSmiDispatcher, 
which does the described check against EFI_BAD_POINTER (though if I remember 
correctly, the value is actually never explicitely set). The issue is that some 
function may pass a handle that was unregistered to the function. 
IsNodeInList() can be used to determine whether it was previously removed.

Thanks for your response!

Regards,
Marvin.

> -----Original Message-----
> From: Kinney, Michael D [mailto:michael.d.kin...@intel.com]
> Sent: Monday, July 24, 2017 6:31 PM
> To: Marvin Häuser <marvin.haeu...@outlook.com>; edk2-
> de...@lists.01.org; Kinney, Michael D <michael.d.kin...@intel.com>
> Cc: Gao, Liming <liming....@intel.com>
> Subject: RE: [PATCH 1/2] MdePkg/BaseLib: Add IsNodeInList() function.
> 
> Hi Marvin,
> 
> Can you provide a few more details on why you would like to see tis internal
> function promoted to a library class API?
> 
> Thanks,
> 
> Mike
> 
> > -----Original Message-----
> > From: Marvin Häuser [mailto:marvin.haeu...@outlook.com]
> > Sent: Sunday, July 23, 2017 3:11 AM
> > To: edk2-devel@lists.01.org
> > Cc: Kinney, Michael D <michael.d.kin...@intel.com>; Gao, Liming
> > <liming....@intel.com>
> > Subject: [PATCH 1/2] MdePkg/BaseLib: Add IsNodeInList() function.
> >
> > This patch adds IsNodeInList() to BaseLib, which verifies the given
> > Node is part of the doubly-linked List provided.
> >
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Marvin Haeuser <marvin.haeu...@outlook.com>
> > ---
> >  MdePkg/Library/BaseLib/LinkedList.c       | 70
> > +++++++++++++++++++-
> >  MdePkg/Include/Library/BaseLib.h          | 25 +++++++
> >  MdePkg/Library/BaseLib/BaseLibInternals.h | 28 --------
> >  3 files changed, 94 insertions(+), 29 deletions(-)
> >
> > diff --git a/MdePkg/Library/BaseLib/LinkedList.c
> > b/MdePkg/Library/BaseLib/LinkedList.c
> > index ba373f4b7be3..b364ae41c647 100644
> > --- a/MdePkg/Library/BaseLib/LinkedList.c
> > +++ b/MdePkg/Library/BaseLib/LinkedList.c
> > @@ -1,7 +1,7 @@
> >  /** @file
> >    Linked List Library Functions.
> >
> > -  Copyright (c) 2006 - 2013, Intel Corporation. All rights
> > reserved.<BR>
> > +  Copyright (c) 2006 - 2017, Intel Corporation. All rights
> > reserved.<BR>
> >    This program and the accompanying materials
> >    are licensed and made available under the terms and conditions of
> > the BSD License
> >    which accompanies this distribution.  The full text of the license
> > may be found at @@ -113,6 +113,74 @@ InternalBaseLibIsNodeInList (  }
> >
> >  /**
> > +  Checks whether Node is part of a doubly-linked list.
> > +
> > +  If List is NULL, then ASSERT().
> > +  If List->ForwardLink is NULL, then ASSERT().
> > +  If List->BackLink is NULL, then ASSERT().
> > +  If Node is NULL, then ASSERT();
> > +  If PcdMaximumLinkedListLength is not zero, and List contains
> > more than
> > +  PcdMaximumLinkedListLength nodes, then ASSERT().
> > +
> > +  @param  List  A pointer to a node in a linked list.
> > +  @param  Node  A pointer to the node to locate.
> > +
> > +  @retval TRUE   Node is in List.
> > +  @retval FALSE  Node isn't in List, or List is invalid.
> > +
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +IsNodeInList (
> > +  IN      CONST LIST_ENTRY      *List,
> > +  IN      CONST LIST_ENTRY      *Node
> > +  )
> > +{
> > +  UINTN             Count;
> > +  CONST LIST_ENTRY  *Ptr;
> > +
> > +  //
> > +  // Test the validity of List and Node  //  ASSERT (List != NULL);
> > + ASSERT (List->ForwardLink != NULL);  ASSERT (List->BackLink !=
> > + NULL);  ASSERT (Node != NULL);
> > +
> > +  //
> > +  // ASSERT List not too long
> > +  //
> > +  ASSERT (InternalBaseLibIsNodeInList (ListHead, Entry, FALSE));
> > +
> > +  Count = 0;
> > +  Ptr   = List;
> > +
> > +  //
> > +  // Check to see if Node is a member of List.
> > +  // Exit early if the number of nodes in List >=
> > PcdMaximumLinkedListLength
> > +  //
> > +  do {
> > +    Ptr = Ptr->ForwardLink;
> > +    if (PcdGet32 (PcdMaximumLinkedListLength) > 0) {
> > +      Count++;
> > +
> > +      //
> > +      // Return if the linked list is too long
> > +      //
> > +      if (Count == PcdGet32 (PcdMaximumLinkedListLength)) {
> > +        return (BOOLEAN)(Ptr == Node);
> > +      }
> > +    }
> > +
> > +    if (Ptr == Node) {
> > +      return TRUE;
> > +    }
> > +  } while (Ptr != List);
> > +
> > +  return FALSE;
> > +}
> > +
> > +/**
> >    Initializes the head node of a doubly-linked list, and returns the
> > pointer to
> >    the head node of the doubly-linked list.
> >
> > diff --git a/MdePkg/Include/Library/BaseLib.h
> > b/MdePkg/Include/Library/BaseLib.h
> > index 791849b80406..4f3f4fd51f3f 100644
> > --- a/MdePkg/Include/Library/BaseLib.h
> > +++ b/MdePkg/Include/Library/BaseLib.h
> > @@ -2869,6 +2869,31 @@ PathCleanUpDirectories(
> >
> >
> >  /**
> > +  Checks whether Node is part of a doubly-linked list.
> > +
> > +  If List is NULL, then ASSERT().
> > +  If List->ForwardLink is NULL, then ASSERT().
> > +  If List->BackLink is NULL, then ASSERT().
> > +  If Node is NULL, then ASSERT();
> > +  If PcdMaximumLinkedListLength is not zero, and List contains
> > more than
> > +  PcdMaximumLinkedListLength nodes, then ASSERT().
> > +
> > +  @param  List  A pointer to a node in a linked list.
> > +  @param  Node  A pointer to the node to locate.
> > +
> > +  @retval TRUE   Node is in List.
> > +  @retval FALSE  Node isn't in List, or List is invalid.
> > +
> > +**/
> > +BOOLEAN
> > +EFIAPI
> > +IsNodeInList (
> > +  IN      CONST LIST_ENTRY      *List,
> > +  IN      CONST LIST_ENTRY      *Node
> > +  );
> > +
> > +
> > +/**
> >    Initializes the head node of a doubly linked list, and returns the
> > pointer to
> >    the head node of the doubly linked list.
> >
> > diff --git a/MdePkg/Library/BaseLib/BaseLibInternals.h
> > b/MdePkg/Library/BaseLib/BaseLibInternals.h
> > index ea387ce37d27..9dca97a0dcc9 100644
> > --- a/MdePkg/Library/BaseLib/BaseLibInternals.h
> > +++ b/MdePkg/Library/BaseLib/BaseLibInternals.h
> > @@ -340,34 +340,6 @@ InternalSwitchStack (
> >
> >
> >  /**
> > -  Worker function that locates the Node in the List.
> > -
> > -  By searching the List, finds the location of the Node in List.
> > At the same time,
> > -  verifies the validity of this list.
> > -
> > -  If List is NULL, then ASSERT().
> > -  If List->ForwardLink is NULL, then ASSERT().
> > -  If List->backLink is NULL, then ASSERT().
> > -  If Node is NULL, then ASSERT();
> > -  If PcdMaximumLinkedListLength is not zero, and prior to insertion
> > the number
> > -  of nodes in ListHead, including the ListHead node, is greater than
> > or
> > -  equal to PcdMaximumLinkedListLength, then ASSERT().
> > -
> > -  @param  List  A pointer to a node in a linked list.
> > -  @param  Node  A pointer to one nod.
> > -
> > -  @retval TRUE   Node is in List.
> > -  @retval FALSE  Node isn't in List, or List is invalid.
> > -
> > -**/
> > -BOOLEAN
> > -EFIAPI
> > -IsNodeInList (
> > -  IN      CONST LIST_ENTRY      *List,
> > -  IN      CONST LIST_ENTRY      *Node
> > -  );
> > -
> > -/**
> >    Worker function that returns a bit field from Operand.
> >
> >    Returns the bitfield specified by the StartBit and the EndBit from
> > Operand.
> > --
> > 2.12.2.windows.2

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to