-
Notifications
You must be signed in to change notification settings - Fork 33
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
Generator Gadgets #42
base: arm-port
Are you sure you want to change the base?
Conversation
…ompletely optional and are specified by the user in a JSON file. Each gadget specifies a number of instruction specifications (in the same syntax as the isa_spec's base.json file). During program generation, the generator may choose a random gadget. If this happens, all instructions in the gadget's list will be generated and placed. It's a customizeable way for the user to give the generator chunks of assembly code that might get included in the test
…0) for finer-grained control
…lacing gadgets. Gadget placement is mindful of the number of memory accesses already placed into the program. If placing a specific gadget will exceed the config field's value, the gadget will not be placed
…ithin gadgets. Control-flow is already decided based on the basic blocks and successors generated in earlier steps. We don't want control-flow in gadgets, as this will mess with the test DAG
…f 1) the average number of gadgets placed into each basic block, and 2) the maximum number of gadgets placed into each basic block. Also implemented individual probabilities for each gadget, which allows for the gadgets in a gadget file to be weighed differently
Hi @OleksiiOleksenko - have you had the chance to look at this? I had another idea that could be added to this PR; what do you think of this? Currently I've implemented this gadget system to forbid any control-flow instructions. The motivation here was to prevent the disruption of your test case's DAG; if control-flow instructions were allowed in gadgets, the user could force more basic blocks to be added to the test case that aren't a part of the official DAG. However, what do you think about allowing small, self-contained, loops to be present? A "loop gadget" might look like this:
Something like this might allow for forced misprediction to occur, without creating infinite loops or doing anything unreasonable. If this isn't worth implementing as a gadget, perhaps implementing loops would be best as a separate feature of the program generator. (I might actually prefer the latter.) What do you think? |
… allows any arbitrary assembly to be placed as an operand to an instruction. I'm using this as a way to specify arm64 barrel-shifting operations, but it could be used for *any* string literal
I'm also implementing a way to "alias" operands in a gadget, to allow for the same unique operand to be used in two different places in the same gadget. I'll push this up as soon as it's done, but for now, I'll mark the PR as a draft. More details to come on this particular part of the PR. |
…es use unique registers and allow for more control over the random-ness of gadget instruction operands
This PR implements the concept of gadgets into Revizor's program generator. Here, a gadget refers to a small list of assembly instructions placed in a specific order for a specific reason. I've made this PR description somewhat lengthy to make sure I document my thought process in implementing this feature.
Benefits of Gadgets
Considering Spectre v1, the below gadget (in pseudocode), which features two memory load instructions, would be useful for causing an extra line in the CPU cache to be allocated during speculative execution.
Or consider another gadget, potentially useful for increasing the CPU's speculative execution window by creating a chain of data-dependent instructions:
Because Revizor's program generator randomly places assembly instructions, specific assembly sequences like these won't easily be generated. Gadgets make this possible.
Gadget File
At runtime, the user can specify the path to a gadget file through a config field (
gadget_file
). This file is formatted in JSON and uses the same syntax for specifying assembly instructions as Revizor's ISA specification parser. Within this file, the user can place interesting assembly gadgets he/she wants to see in Revizor's generated programs. Each gadget has a name and an optional weight (used to tune how often gadgets appear in generated programs). Here's an example of what one gadget might look like:If the generator chooses to place this particular gadget into a program, two randomized
SUB
instructions will be placed (consecutively) within a basic block.(I've created an example gadget file at
src/arm64/tests/example_gadgets.json
).Gadget Selection
As the program generator fills basic blocks with instructions, it may choose to instead select a random gadget from the gadget file and place it into the program. This pseudocode describes the basic idea of how it decides:
The randomness of gadget placement is configurable using a few new config fields:
CONF.avg_gadgets_per_bb
dictates, roughly, how many gadgets are selected and placed into each basic block of the test case.CONF.max_gadgets_per_bb
forces a maximum number of gadgets that can be placed into each basic block.Gadget placement will also not occur if:
CONF.program_size
)CONF.avg_mem_accesses
)Operand Aliasing
I've also given gadgets the ability to specify unique operand aliases, to control how instruction operands (such as registers) are used within the same gadget. Defining an operand alias (let's say it's named
REG_A
) as a GPR operand allows us to specifyREG_A
in the operands of the gadget's instructions. When the gadgets is placed into the code, all instances ofREG_A
will be replaced by the same randomly-chosen register.See this gadget as an example:
The
operand_aliases
allow this gadget to use random registers to fill inREG_A
,REG_B
, andREG_C
, but keep their values consistent across all uses in each of the two load instructions.Other Additions
Literal Operand
To support extra operands that may not fit under the existing types, I've implemented a
LiteralOperand
, which allows for any arbitrary literal string to be used as an operand for an assembly instruction. Take thisEOR
instruction specification as an example:The final operand is a
"LITERAL"
, and contains the value"ROR #9"
. This type of operand will be placed in the assembly code as-is. In this example, it allows theEOR
instruction to have a right-rotate barrel-shift operand: