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

ubpf_vm: Add mem_len via R2 into uBPF VM #58

Merged
merged 2 commits into from
May 25, 2021

Conversation

sbates130272
Copy link

It is useful for programs to be able to operate based on the length of
the input data passed in to it. Pass in this length via the R2
register.

Fixes #57.

@sbates130272
Copy link
Author

I see that #22 also required a chance to the JIT code. However my testing suggests this change is not needed? Also, how do I add a testcase for this change?

@coveralls
Copy link

coveralls commented Mar 12, 2021

Coverage Status

Coverage increased (+0.005%) to 96.054% when pulling 5b22e3a on sbates130272:mem_length into 0014f29 on iovisor:master.

@jpsamaroo
Copy link

The tests currently pass without it, but if you add a new test to the tests/ folder that relies on the mem_len being in R2, you'll find that that new test should fail reliably, because the JIT hasn't been updated to pass mem_len in R2. I'd just cherry-pick b7caed9 so you get the necessary change, and @ygrek gets credit.

@jpsamaroo
Copy link

And for adding a test, just look in tests/ for something simple that uses memory, make a copy of it in that folder with a new name, and make it return 0 if the mem_len matches what's expected, or 1 if it does not.

@sbates130272
Copy link
Author

@jpsamaroo I did what you suggest. I cherry-picked @ygrek and added a test. Note that this test is really simple. However while it passes for the VM it fails for the x86_64 JIT and I am not sure why. Can you take a look?

@sbates130272
Copy link
Author

Oh @jpsamaroo I think we have a problem here. After reviewing the JIT code some more it looks like RSI is used to return a divide by zero error handle. So we might have to review that.

https://github.com/iovisor/ubpf/blob/master/vm/ubpf_jit_x86_64.c#L446

@jpsamaroo
Copy link

I don't see any evidence that the div-by-zero handler is the issue. The div-by-zero handler only gets hit if you have a div (otherwise we just do the regular epilogue), which you don't have in your test. Maybe try throwing that test under gdb and see why this is happening?

@lsgunth
Copy link

lsgunth commented Mar 18, 2021

The issue is with the register mapping. When we only shift by one (ie -r 1) then map_register[1] is RSI and thus RSI gets overwritten by RDI before RSI is copied to map_register[2].

This could be fixed with some complicated logic. But my recommendation would be to just drop the transfer and add a "-- no register offset" to any test which relies on the second argument. (Like is done for call instructions). The register offset test is of limited use here anyway and register offsets are only useful for the test code.

@sbates130272
Copy link
Author

@lsgunth thanks! @jpsamaroo I updated the mem-length.data test to disable the register offset testing. It should now pass. Can you take a look and LMK if this looks good to merge?

/* Move rsi into register 2 */
if (map_register(2) != RSI) {
emit_mov(state, RSI, map_register(2));
}
Copy link

Choose a reason for hiding this comment

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

Given that we can't rely on the length register when applying a register offset, I think these lines should just be removed.... Keeping them here just confusingly makes it seem like that would work.

Copy link
Author

Choose a reason for hiding this comment

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

@jpsamaroo can you comment on this. It looks like @lsgunth is correct here.

Choose a reason for hiding this comment

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

I just realized that we'll already be passing the memory length in RSI anyway thanks to calling conventions, so there's no need for this 😄

Copy link
Author

Choose a reason for hiding this comment

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

Thanks @jpsamaroo. I will drop these lines and resubmit.

ygrek and others added 2 commits May 2, 2021 19:16
It is useful for programs to be able to operate based on the length
ofthe input data passed in to it. Pass in this length via the R2
register.

[cherry-pick of b7caed9 with some modifications to commit message]

Fixes iovisor#57.
Add a simple test to ensure the mem_len variable is being passed into
the VM and/or JIT as expected. Note that due to how the register
offset testing works we need to disable it for this new test.
Copy link

@jpsamaroo jpsamaroo left a comment

Choose a reason for hiding this comment

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

LGTM!

@jpsamaroo
Copy link

@pchaigno I think this looks good to merge.

@Dantali0n
Copy link

Thanks for this patch :)
Out of curiosity do you think it is possible to extract these register values and move them into variables using inline assembly in C. Or would the basic initialization when compiling C programs with Clang already overwrite these?

Copy link

@niclashedam niclashedam left a comment

Choose a reason for hiding this comment

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

LGTM. This is going to be a highly needed change in my fork, so let's get it merged.

@rlane rlane merged commit 221bbe0 into iovisor:master May 25, 2021
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.

Pass the mem_len argument into the uBPF VM so it can be used by programs.
8 participants