lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20230907153036.GBZPnsnNreLCyGpJFn@fat_crate.local>
Date:   Thu, 7 Sep 2023 17:30:36 +0200
From:   Borislav Petkov <bp@...en8.de>
To:     Peter Zijlstra <peterz@...radead.org>
Cc:     x86@...nel.org, linux-kernel@...r.kernel.org, David.Kaplan@....com,
        Andrew.Cooper3@...rix.com, jpoimboe@...nel.org,
        gregkh@...uxfoundation.org, nik.borisov@...e.com
Subject: Re: [PATCH v2 10/11] x86/alternatives: Simplify ALTERNATIVE_n()

On Thu, Sep 07, 2023 at 05:06:32PM +0200, Borislav Petkov wrote:
> >       # ALT: oldnstr
> > 661:
> >       # ALT: oldnstr 
> > 661:
> 
> I'll keep on playing with this.

Ok, below's what I've been thinking. It looks ok but I'll keep staring
at it for a while to make sure I'm not missing an angle.

We simply pass a number to the ALTERNATIVE macro, starting from 0. 0 is
the innermost invocation, 1 is the outer and so on. And then the labels
are unique and the sizes are correct. And we hardcode 0 to mean the
innermost macro invocation and use that for sizing of orig instr.

But I might be missing something so lemme poke at it more. Below is
a userspace program which makes this a lot easier to experiment with:

---
#include <stdio.h>

#define __stringify_1(x...)	#x
#define __stringify(x...)	__stringify_1(x)

#define alt_slen		"662b-6610b"
#define alt_total_slen		"663b-661b"
#define alt_rlen		"665f-664f"

#define OLDINSTR(oldinstr, n)						\
	"# ALT: oldnstr\n"						\
	"661" #n ":\n\t" oldinstr "\n662:\n"					\
	"# ALT: padding\n"						\
	".skip -(((" alt_rlen ")-(" alt_slen ")) > 0) * "		\
		"((" alt_rlen ")-(" alt_slen ")),0x90\n"		\
	"663:\n"

#define ALTINSTR_ENTRY(ft_flags)					      \
	".pushsection .altinstructions,\"a\"\n"				      \
	" .long 6610b - .\n"				/* label           */ \
	" .long 664f - .\n"				/* new instruction */ \
	" .4byte " __stringify(ft_flags) "\n"		/* feature + flags */ \
	" .byte " alt_total_slen "\n"			/* source len      */ \
	" .byte " alt_rlen "\n"				/* replacement len */ \
	".popsection\n"

#define ALTINSTR_REPLACEMENT(newinstr)			/* replacement */	\
	".pushsection .altinstr_replacement, \"ax\"\n"				\
	"# ALT: replacement \n"							\
	"664:\n\t" newinstr "\n 665:\n"						\
	".popsection\n"

/*
 * Define an alternative between two instructions. If @ft_flags is
 * present, early code in apply_alternatives() replaces @oldinstr with
 * @newinstr. ".skip" directive takes care of proper instruction padding
 * in case @newinstr is longer than @oldinstr.
 *
 * Notably: @oldinstr may be an ALTERNATIVE() itself, also see
 *          apply_alternatives()
 */
#define __ALTERNATIVE(oldinstr, newinstr, ft_flags, n)			\
	OLDINSTR(oldinstr, n)						\
	ALTINSTR_ENTRY(ft_flags)					\
	ALTINSTR_REPLACEMENT(newinstr)

#define ALTERNATIVE(oldinstr, newinstr, ft_flags)			\
	__ALTERNATIVE(oldinstr, newinstr, ft_flags, 0)

#define ALTERNATIVE_2(oldinst, newinst1, flag1, newinst2, flag2)	\
	__ALTERNATIVE(__ALTERNATIVE(oldinst, newinst1, flag1, 0),		\
		    newinst2, flag2, 1)

#define alternative_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2) \
	asm __inline volatile(ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2) ::: "memory")

int main(void)
{
	alternative_2("", "pop %%rax", 1, "call main", 1);
	return 0;
}



-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ