Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add validation function for Microsoft signing(supersede #531) #567

Closed
wants to merge 2 commits into from

Conversation

dennis-tseng99
Copy link
Contributor

To align line 45 of post-process-pe.c with upstream, the initial value of set_nx_compat variable in PR#531 is also updated to true. To understand why some validation functions were added onto post-process-pe.c, please refer the following link for more previous comments:

Signed-off-by: Dennis Tseng [email protected]

@aronowski
Copy link
Contributor

I have a few suggestions.

Instead of the help message

fprintf(out, "       -m    Microsoft validation\n");

let's use something that sheds some more light on the matter. Something like

fprintf(out, "       -m    Test for Microsoft's signing requirements\n");

With static bool set_ms_validation = true; the process is already set up to be ran. Why have -m to set it to true again if it's already set and have no -M that sets it to false?


The code block for checking sections characteristics looks improvable. Maybe something like this would be cleaner

for (i = 0, Section = ctx->FirstSection; i < ctx->NumberOfSections; i++, Section++) {
  if ((Section->Characteristics & EFI_IMAGE_SCN_MEM_WRITE) &&
      (Section->Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE)) {
    debug(INFO, "%14s: %s\n","Section-Wr-Exe", "FAIL");
  } else {
    debug(INFO, "%14s: %s\n","Section-Wr-Exe", "PASS");
  }
}

(This is a suggestion I made up on-the-fly, this is not guaranteed to compile or work properly in runtime)


While people that are in the environment of shim development, reviewing shim reviews and whatnot may know about Microsoft requirements, these may change in the future. I'd add comments that clarify what happens, why the function was added and what the requirements are as of today, as well as a link to Microsoft's official posts.


If you want, I can add my way of doing these things. Maybe another comment in this pull request with a diff to your current tree. Or as a .patch file. Or a pull request to your fork. Or something else you prefer.

But for that much code in exchange give me a token of appreciation and co-author me with

Co-authored-by: Kamil Aronowski <[email protected]>

in a new commit. ;)

@dennis-tseng99
Copy link
Contributor Author

@aronowski Thanks for your comments. Actually, I'd like to be a co-author with you. It is my pleasure. I'll put your co-author name on this PR in the later version.

>for (i = 0, Section = ctx->FirstSection; i < ctx->NumberOfSections; i++, Section++) {
  if ((Section->Characteristics & EFI_IMAGE_SCN_MEM_WRITE) &&
      (Section->Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE)) {
    debug(INFO, "%14s: %s\n","Section-Wr-Exe", "FAIL");
  } else {
    debug(INFO, "%14s: %s\n","Section-Wr-Exe", "PASS");
  }
}

Sorry to let you know I will still suggest we can keep "break test-loop even only one section is FAIL", rather than testing through all sections. Actually, I referred a Python tool codes provided by Microsoft to implement our codes when I sent PR#531 last year. Here is the Python codes named image_validation.py:

def execute(self, pe, config_data):
       .....
       for section in pe.sections:
            if (has_characteristic(section.Characteristics, 
SECTION_CHARACTERISTICS["IMAGE_SCN_MEM_EXECUTE"])
               and has_characteristic(section.Characteristics, SECTION_CHARACTERISTICS["IMAGE_SCN_MEM_WRITE"])):
                logging.error(f'[{Result.FAIL}]: Section [{section.Name.decode().strip()}] \
                              should not be both Write and Execute')
                return Result.FAIL
        return Result.PASS

I'd add comments that clarify what happens, why the function was added and what the requirements are as of today, as well as a link to Microsoft's official posts.

I like your idea. But before doing that, please also refer my Conversation 1 in #531 If you think that is not clear enough, please just put your comments on it.

@aronowski
Copy link
Contributor

You're right about that function. I guess I forgot a return; once and shouldn't code after 8 hours of intellectual work from now on. ;)

Anyway, I implemented the tweaks discussed and fixed some formatting issues. You can use my patch for inspiration - apply it on top of your commit 1b4f664:

From 8bbd6dd52ddc8f46f0128be40ff4a554fac85354 Mon Sep 17 00:00:00 2001
From: Kamil Aronowski <[email protected]>
Date: Tue, 9 May 2023 10:30:59 +0200
Subject: [PATCH] Some tweaks as discussed in PR 567

Signed-off-by: Kamil Aronowski <[email protected]>
---
 post-process-pe.c | 34 +++++++++++++++++++++++++---------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/post-process-pe.c b/post-process-pe.c
index 7083d3e..f39b623 100644
--- a/post-process-pe.c
+++ b/post-process-pe.c
@@ -367,6 +367,22 @@ set_dll_characteristics(PE_COFF_LOADER_IMAGE_CONTEXT *ctx)
 static void
 ms_validation(PE_COFF_LOADER_IMAGE_CONTEXT *ctx)
 {
+	/*
+	 * Since November 30th, 2022 Microsoft requires that shim satisifes
+	 * certain memory mitigations for it to be signed. Reference:
+	 * https://techcommunity.microsoft.com/t5/hardware-dev-center/new-uefi-ca-memory-mitigation-requirements-for-signing/ba-p/3608714
+	 * Currently they are implemented here with the codenames:
+	 * 4K-Alignment: Section Alignment of the submitted PE file must be
+	 * aligned with page size.  This must be 4kb, or a larger power of 2 (ex
+	 * 64kb)
+	 * Section-Wr-Exe: Section Flags must not combine IMAGE_SCN_MEM_WRITE and
+	 * IMAGE_SCN_MEM_EXECUTE for any given section.
+	 * NX-Compat-Flag: DLL Characteristics must include
+	 * IMAGE_DLLCHARACTERISTICS_NX_COMPAT
+	 *
+	 * Keep an eye out for new incoming requirements and implement them
+	 * here once they have been made public.
+	 */
 	EFI_IMAGE_SECTION_HEADER *Section;
 	int i;
 
@@ -379,14 +395,11 @@ ms_validation(PE_COFF_LOADER_IMAGE_CONTEXT *ctx)
 		PAGE_SIZE == ctx->PEHdr->Pe32Plus.OptionalHeader.SectionAlignment ?
 		"PASS":"FAIL");
 
-	Section = ctx->FirstSection;
-	//printf("NumberOfSections=%d\n",ctx->NumberOfSections);
 	for (i=0, Section = ctx->FirstSection; i < ctx->NumberOfSections; i++, Section++) {
-		//printf("name=%s, Charact=0x%04x\n",Section->Name,Section->Characteristics);
 		if ((Section->Characteristics & EFI_IMAGE_SCN_MEM_WRITE) &&
-		    (Section->Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE)) {
-		    debug(INFO, "%14s: %s\n","Section-Wr-Exe", "FAIL");
-	    	    return;
+			(Section->Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE)) {
+			(debug(INFO, "%14s: %s\n","Section-Wr-Exe", "FAIL");
+			return;
 		}
 	}
 	debug(INFO, "%14s: %s\n","Section-Wr-Exe", "PASS");
@@ -541,7 +554,10 @@ int main(int argc, char **argv)
 		{.name = "enable-nx-compat",
 		 .val = 'n',
 		},
-		{.name = "ms-validation",
+		{.name = "disable-ms-validation",
+		 .val = 'M',
+		},
+		{.name = "enable-ms-validation",
 		 .val = 'm',
 		},
 		{.name = "quiet",
@@ -567,11 +583,11 @@ int main(int argc, char **argv)
 			set_nx_compat = true;
 			break;
 		case 'M':
-		        set_ms_validation = false;	
+			set_ms_validation = false;
 			break;
 		case 'm':
 			set_ms_validation = true;
-			break;	
+			break;
 		case 'q':
 			verbosity = MAX(verbosity - 1, MIN_VERBOSITY);
 			break;
-- 
2.40.0

and once that's done, recompile shim and check if everything works as intended. Thanks a lot!

@dennis-tseng99 dennis-tseng99 force-pushed the post-process-pe branch 2 times, most recently from 26ab927 to 5f3103f Compare May 9, 2023 14:48
Copy link
Contributor

@vathpela vathpela left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please squash this down to one commit, and run clang-format on the added code.

post-process-pe.c Outdated Show resolved Hide resolved
post-process-pe.c Outdated Show resolved Hide resolved
EFI_IMAGE_SECTION_HEADER *Section;
int i;

debug(INFO, "%14s: %s\n","NX-Compat-Flag",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's with all this "%14s: stuff? Why not just "NX-Compat-Flag: %s\n"? Same with all the cases below it.

Co-authored-by: Peter Jones <[email protected]>
Co-authored-by: Kamil Aronowski <[email protected]>
Signed-off-by: Dennis Tseng <[email protected]>
@vathpela
Copy link
Contributor

I've got a version of this I've made some changes to over here: #705 (because I can't push an update here.)

@vathpela vathpela closed this Nov 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants