linuxmodule: fix md5_append wrt non-virt data #90
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
sg_init_one uses sg_init_buf, which only works with kmalloc'd data. In particular, this excludes anything vmalloc'd as well as anything in the rodata section of the module. The code that was failing for me was essentially
and the work-around was to invoke String::mutable_data() prior to the md5_append, which kmalloc's and makes String::data() safe for sg_init_buf.
The better solution is to call virt_addr_valid, only using sg_init_one if true; otherwise, we must use vmalloc_to_page on individual pages, which will walk the page-table and should do the Right Thing.
Since vmalloc'd data might not be continuous, we must iterate over the individual pages that make up the allocation. Because this is expensive to begin with, we call update for each page using a single scatterlist rather than allocating an sg_table and calling update once. This also simplifies the code.
I tested this by adding
inside the loop and watching it "do the Right Thing" to a large vmalloc allocation, verifying that the hash was correct using md5sum.