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

security: Add compiler static analysis support #64595

Merged
merged 1 commit into from Jan 25, 2024

Conversation

ceolin
Copy link
Member

@ceolin ceolin commented Oct 30, 2023

Add a build option to enable GCC builtin static analysis.

To enable it an application has to set
CONFIG_COMPILER_STATIC_ANALYSIS=y

When this option is enabled GCC performs a static analysis and can point problems like:

sample.c

+	int *j; +
+	if (j != NULL) {
+		printf("j != NULL\n");

output:

${ZEPHYR_BASE}/samples/userspace/hello_world_user/src/main.c:30:12: warning: use of uninitialized value 'j' [CWE-457]
[-Wanalyzer-use-of-uninitialized-value]
   30 |         if (j != NULL) {
      |            ^
  'main': events 1-2
    |
    |   25 |         int *j;
    |      |              ^
    |      |              |
    |      |              (1) region created on stack here
    |......
    |   30 |         if (j != NULL) {
    |      |            ~
    |      |            |
    |      |            (2) use of uninitialized value 'j' here

Kconfig.zephyr Outdated Show resolved Hide resolved
Kconfig.zephyr Outdated
@@ -442,6 +442,14 @@ config COMPILER_COLOR_DIAGNOSTICS
help
Compiler diagnostic messages are colorized.

config COMPILER_STATIC_ANALYSIS
bool "Compiler static analysis"
depends on "${ZEPHYR_TOOLCHAIN_VARIANT}" = "zephyr"
Copy link
Member

Choose a reason for hiding this comment

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

Why does this depend on Zephyr SDK?

Copy link
Member Author

Choose a reason for hiding this comment

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

That is GCC specific, while the host toolchain probably will work, that was the closest I got to check that it is using GCC. Is there a better way ?

Copy link
Member

Choose a reason for hiding this comment

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

zephyr is not the only ZEPHYR_TOOLCHAIN_VARIANT that is GCC-based (i.e. there is also the generic cross-compile, and crosstool-ng-built xtools; though, the latter should/will be removed soon).

The most ideal solution would be to introduce something like TOOLCHAIN_SUPPORTS_COMPILER_STATIC_ANALYSIS set by each toolchain variant, and depend on it (similar to how TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE works).

But, given that we still have not established a consistent interface for toolchain capability detection (@tejlmand please feel free to correct me if some progress has been made on this front while I was away), I would just leave this an open option with a description saying this option currently only works with GCC (and also potentially a build system warning when an unsupported toolchain is used with this option).

p.s. To elaborate, the rationale for leaving this an open option, as opposed to specifying the dependencies on all upstream GCC-based toolchain variants, is to not tie down the hands of the downstream out-of-tree toolchain users.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I agree.
We should not tie this to Zephyr or gcc toolchains.

Although GCC has a specific -fanalyze then other toolchains may supports some form of static analysis during compilation.

That's why we have the compiler properties, which can be left empty if the compiler doesn't have a dedicated flag.

Suggested change
depends on "${ZEPHYR_TOOLCHAIN_VARIANT}" = "zephyr"

Kconfig.zephyr Outdated Show resolved Hide resolved
cmake/compiler/gcc/compiler_flags.cmake Outdated Show resolved Hide resolved
Kconfig.zephyr Outdated Show resolved Hide resolved
Copy link
Collaborator

@tejlmand tejlmand left a comment

Choose a reason for hiding this comment

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

Thanks for proposing this.

It like to open a discussion if a Kconfig is the best approach in this case.

It's nice to use Kconfig when a flag can be used directly on compiler invocation, but exactly for the SCA case, then Zephyr also supports ZEPHYR_SCA_VARIANT.

This means user now have two places / ways where they can read about SCA and how to use such tools.

The alternative would be to simply create a ZEPHYR_SCA_VARIANT=gcc, where all it does is applying the -fanalyze flag to the compiler.

That would mean there is only one place where users should read about SCA tools.

I would like to hear other opinions on this matter.
Personally I see high value in only having handling of similar feature done in a common way, but in this specific case, Kconfig is also a sane choice.

If going for the Kconfig approach, then I have a couple of specific change requests.

Kconfig.zephyr Outdated
@@ -442,6 +442,14 @@ config COMPILER_COLOR_DIAGNOSTICS
help
Compiler diagnostic messages are colorized.

config COMPILER_STATIC_ANALYSIS
bool "Compiler static analysis"
depends on "${ZEPHYR_TOOLCHAIN_VARIANT}" = "zephyr"
Copy link
Collaborator

Choose a reason for hiding this comment

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

I agree.
We should not tie this to Zephyr or gcc toolchains.

Although GCC has a specific -fanalyze then other toolchains may supports some form of static analysis during compilation.

That's why we have the compiler properties, which can be left empty if the compiler doesn't have a dedicated flag.

Suggested change
depends on "${ZEPHYR_TOOLCHAIN_VARIANT}" = "zephyr"

Kconfig.zephyr Outdated Show resolved Hide resolved
@tejlmand
Copy link
Collaborator

@ceolin did you push the wrong commit ?

It's only doc changes now describing the process and no implementation anymore (of -fanalyze).

@ceolin
Copy link
Member Author

ceolin commented Dec 13, 2023

@ceolin did you push the wrong commit ?

It's only doc changes now describing the process and no implementation anymore (of -fanalyze).

lol !!! my bad. I push a different commit indeed.

@tejlmand
Copy link
Collaborator

tejlmand commented Jan 3, 2024

lol !!! my bad. I push a different commit indeed.

what is status on this PR.
Are you going to push another commit containing implementation ?

@ceolin
Copy link
Member Author

ceolin commented Jan 15, 2024

@tejlmand @stephanosio I just changed it to use Zephyr's SCA infra. It got much simpler.

Please take a look again :)

@ceolin ceolin requested a review from tejlmand January 15, 2024 06:50
doc/develop/sca/gcc.rst Outdated Show resolved Hide resolved
doc/develop/sca/gcc.rst Outdated Show resolved Hide resolved
Enable GCC builtin static analysis in Zephyr's static code analysis
(SCA) infra.

When this option is enabled GCC performs a static analysis and
can point problems like:

sample.c

+	int *j;
+
+	if (j != NULL) {
+		printf("j != NULL\n");

output:

${ZEPHYR_BASE}/samples/userspace/hello_world_user/src/main.c:30:12:
warning: use of uninitialized value 'j' [CWE-457]
[-Wanalyzer-use-of-uninitialized-value]

   30 |         if (j != NULL) {
      |            ^
  'main': events 1-2
    |
    |   25 |         int *j;
    |      |              ^
    |      |              |
    |      |              (1) region created on stack here
    |......
    |   30 |         if (j != NULL) {
    |      |            ~
    |      |            |
    |      |            (2) use of uninitialized value 'j' here

Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
@ceolin
Copy link
Member Author

ceolin commented Jan 18, 2024

@tejlmand @stephanosio ping :)

Copy link
Collaborator

@tejlmand tejlmand left a comment

Choose a reason for hiding this comment

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

Nice and clean ❤️

@kartben
Copy link
Collaborator

kartben commented Jan 19, 2024

Nice indeed, thank you! Related naive question: would it make sense to provide several SCA variants to the same build command, or are the variants always going to be mutually exclusive and possibly messing up with one another?

Copy link
Collaborator

@jfischer-no jfischer-no left a comment

Choose a reason for hiding this comment

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

Thanks for that. Perhaps it would be useful to have another option to set the flag for Zephyr tree only, i.e. to exclude vendor HALs from the analysis.

@tejlmand
Copy link
Collaborator

Related naive question: would it make sense to provide several SCA variants to the same build command, or are the variants always going to be mutually exclusive and possibly messing up with one another?

in most cases I assume they will be mutual exclusive, but I guess there can be cases where you technically could combine, for example the gcc with sparse.
But good luck in trying to parse the output in such cases. I assume running both tools independently would make it easier to understand the error messages provided.

@tejlmand tejlmand dismissed stephanosio’s stale review January 25, 2024 10:52

Stale, and there are no longer Kconfig changes in PR

@carlescufi carlescufi merged commit 3fc5d97 into zephyrproject-rtos:main Jan 25, 2024
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants