-
Notifications
You must be signed in to change notification settings - Fork 7
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
Static Analysis Fixes #44
Static Analysis Fixes #44
Conversation
Signed-off-by: Eric Richter <[email protected]>
Pointed out by cppcheck. out_buffer, a pointer to a pointer, is dereferenced and assigned to without first checking validity. Then, the base, top-level pointer value is checked for NULL, after it has already been dereferenced. This commit fixes the two problems by first checking that the out_buffer parameter actually points somewhere, then correcting the NULL check to confirm that the call to malloc actually succeeds. Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
…e type Signed-off-by: Eric Richter <[email protected]>
rc is a relatively useless variable in this function unless there actually is an error. Therefore, initialize it to SUCCESS, and return it at the end rather than only referencing it in the while loop. Signed-off-by: Eric Richter <[email protected]>
…same #ifdef Without this, those two variables trigger an static analysis warning when not compiling with the defined flag. Also include those as a requirement under the flag so to temporarily clear the warning. That flag should still be deleted eventually. Signed-off-by: Eric Richter <[email protected]>
cppcheck flags variables that can be reduced in scope, meaning they are declared in say the top-level of a function, but only used in the scope of a loop. This in itself isn't an issue, as I personally prefer seeing all the variables used in the function as a whole up at the top, however it does highlight a larger issue with the function as a whole -- FAR too much indentation and probably repeat logic. This function should *really* be broken down into helper functions so that it need not be one massive while loop. For now, reduce the variables to the scopes that they are used in. Signed-off-by: Eric Richter <[email protected]>
This function needlessly uses near-identical logic for PK and KEK, only changing what variables are referenced. Therefore, factor out the common logic, to dramatically reduce code size and indentation levels. Signed-off-by: Eric Richter <[email protected]>
get_pk_and_kek_from_path_var previously contained one giant `if` block with all of the logic. Invert the logic and return early, so that the rest of the body can have the indentation reduced. Also return an error code instead of SUCCESS if that condition is not met, since apparently it just happily returns on through without doing anything. Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Fix check of esl_data_size against -1, which will never happen. Since this appears to be checking that there is enough space in the esl buffer for the timestamp header + data, instead just check that the size is at least the length of a timestamp. If the size is less than a timestamp, it's probably garbage data. Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
…C to that scope Signed-off-by: Eric Richter <[email protected]>
I'm going to be honest, I have no idea where that code came from, or why it was there in the first place. It appears the host equivalent to this function also has code after the break, but cppcheck isn't flagging that for some reason. Adding a default: to the switch breaks a test. Removing the initial break breaks a test. None of this make sense, so just remove the offending code, and improve the test cases later -- maybe we'll find out why this is so miserable later. Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
For some reason the for loop uses an assigment as its condition. I'm going to ignore that and address the portability issue of casting a pointer to void then doing arithmetic on a non-known size for `void *`. Just increment the pointer if you are only going to add the size of the value anyway. Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
… is trying to be loaded Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
…_single_esl esl_size is declared and only used twice: once to make a redundant check, and then again at the end of the function to be assigned to a pass-by-reference parameter. Remove the variable, redundant check, and use the source value directly at the end. Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Same change as before, see the following commit for more details: a0a778e guest/validate: remove needless esl_size variable alias from validate_single_esl Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
Signed-off-by: Eric Richter <[email protected]>
… zero Signed-off-by: Eric Richter <[email protected]>
Reported by scan-build. ESL is not checked for NULL throughout the function, and is blatantly memcpy'd from at the end from an also unchecked size value. This is however, actually valid, the case of ESL_size = 0, as the memcpy will then not actually read from the buffer. Even better, this is exactly how generating a reset auth file works -- it passes in a NULL buffer with ESL_size set to 0. Therefore, this commit adds a check for that specific error case where ESL is NULL, but ESL_size is nonzero. Also this skips the memcpy at the end in the case of ESL being NULL, just to ensure that any static analyzers are happy about not blatantly memcpy'ing from NULL, even if ESL_size = 0 would prevent it. Signed-off-by: Eric Richter <[email protected]>
Reported by scan-build. auth_data is assumed to not be NULL. Add a check to ensure it is not, so that we don't blatantly continue to pass it around and read from garbage memory. Signed-off-by: Eric Richter <[email protected]>
Reported by scan-build. If getCurrentVars returns an error case, we exit the function early without cleaning up currentVars. Free the memory in the error clause. Signed-off-by: Eric Richter <[email protected]>
…_var Reported by scan-build. Currently, this attempts to free auth_data as returned by get_auth_data() if rc is non-success. get_auth_data() only sets *auth_data if returning successfully. Therefore, auth_data will never be assigned to an allocated buffer in this particular conditional block. Remove the free, as it is not necessary. Functions that return allocated memory should really be marked better. Signed-off-by: Eric Richter <[email protected]>
…UNC enabled Signed-off-by: Eric Richter <[email protected]>
…s for better inline documentation Signed-off-by: Eric Richter <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ran out of time today but managed to review ~10 commits. Will add more later, thanks!
backends/guest/common/validate.c
Outdated
@@ -260,7 +260,7 @@ int validate_esl(const uint8_t *esl_data, size_t esl_data_len) | |||
if (!count) | |||
return ESL_FAIL; | |||
|
|||
return SUCCESS; | |||
return rc; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This actually changes behavior of this function.
Assume that there are more than one ESL's in the chain: Previously, if the first one parsed successfully and the second failed to parse, we would return success. This commit ensures that all ESLs are valid AND that all bytes are accounted for.
This functions behavior should mirror whatever our backends are accepting as a "valid" ESL list (ikik atm machine-ism lol)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Changed to reducing the scope of rc
instead of persisting it through the whole function. There's no test case that failed for this, but there really should be if this change of behavior is supposed to be important.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a weird function though -- why do we handled what seems to be the first one different from the second. Why is a function called validate_esl
validating a list, and should it not be breaking and erroring if we're validating a list of esls and one fails? I don't know what the right answer is here, but this is slated for rework.
@@ -124,14 +124,17 @@ int print_variables(const uint8_t *buffer, size_t buffer_size, const uint8_t *va | |||
{ | |||
int rc; | |||
ssize_t esl_data_size = buffer_size, cert_size; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agreed, we should split this into smaller functions.
But if you are going to reduce scope of variables then you might as well go all the way:
data_size
is useless and can be removed and replaced withcert_size
cert_size
,esd
can be declared in the second loopsignature_type
,sig_list
can go in first loop- I don't think
offset
is being used properly in this function at all, in the first loop we use it for offset to the next ESL header, in the second, loop we use it as an offset to the ESL data. I doubt this works if there are ever two appended ESL structures (which I believe is possible with dbx, unless something changed)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this was mostly to silence cppcheck warnings, most of the rest of the scope reductions will probably be removed with a function rewrite. Skipping for now.
|
||
free(auth_data); | ||
|
||
if (rc != SUCCESS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a note on this function as a whole, this is not due to the work in this PR, but it looks like this (poorly-named) function performs updates on all PK and KEK updates first then it processes all other variables in verify_update_variable
. This differs from host boot processing flow (which handles updates in chronological order). We talked offline and there was speculation as to whether guest boot could even process more than update at once (since it handles updates in realtime). We need to make sure that this is clarified and this function reflects what the backend actually does. If it can only accept one update at a time then we need to have secvarctl reflect that.
} | ||
|
||
rc = update_variable((uint8_t *)args->update_variable[i], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could have sworn this function was implemented in libstb-sevar but it appears it is defined in this file. I see libstb-secvar implements pseries_update_variable
. At some point we should look to use that function instead. The more libstb-secvar functions that we can use in secvarctl, the more useful secvarctl will be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's... multiple functions like this that more or less do the same thing. There's also a wrapper function in libstb-secvar with 15+ arguments that packs the struct args. I'll look into this with the next overhaul PR that hopefully removes a lot of these redundant wrappers.
free(esl_data_path); | ||
if (args->variable_path == NULL) { | ||
prlog(PR_ERR, "Path is not set, possibly a bug?"); | ||
return -1; // Throwaway error, this function likely needs a rewrite |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was going to complain about generic -1
value but I see where you are coming from. The only use of the function is:
if (args->variable_path != NULL)
rc = get_pk_and_kek_from_path_var(.........
So I agree with what you have here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm planning an eventual overhaul of internal secvarctl error codes -- there should at least be a generic unknown error and more memory error types. Will likely end up using standard errno where possible, but that needs a whole treewide rework.
This looks really good thanks for doing all of this. I left some minor nits, maybe only need to verify the I have more cppcheck errors showing up when I run Thanks again! |
Signed-off-by: Eric Richter <[email protected]>
To fix a scope reduction warning from cppcheck, a previous commit persisted the use of rc throughout the whole function. However, this introduces an unintended side effect of being pickier about Change the function to reduce the scope of rc instead to avoid the unintended side-effect. Signed-off-by: Eric Richter <[email protected]>
This PR adds a new
make cppcheck
build target to run thecppcheck
static analysis tool on the source files. The rest of this PR is a fix for every single complaint it had, including a few found fromscan-build
.Some highlights:
%d
with unsigned integers (%u
). Commit messages started getting lazier with these.unsigned < 0
comparisons. May warrant a larger audit of all size checks and size arithmetic, I fear there may be possible cases of unsigned wrapping.NOTE: A subsequent PR will re-enable Actions, and will run both of these tools.