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

Rust: New query for bad 'ctor' initialization #18097

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

geoffw0
Copy link
Contributor

@geoffw0 geoffw0 commented Nov 25, 2024

New (requested) query for bad ctor initialization. See the .qhelp for an explanation of what this is. Note three limitations:

  • results are perhaps more likely to be more about correctness / reliability than security (in my opinion). There is a suitable CWE though.
  • no transitive results through calls (yet), because we don't have call target resolution (yet, as far as I'm aware).
  • limited testing, because we don't yet have any real-world databases that use #[ctor] / #[dtor].

TODO:

  • code review
  • docs review

@geoffw0 geoffw0 added ready-for-doc-review This PR requires and is ready for review from the GitHub docs team. Rust Pull requests that update Rust code labels Nov 25, 2024
Copy link
Contributor

QHelp previews:

rust/ql/src/queries/security/CWE-696/BadCtorInitialization.qhelp

Bad 'ctor' initialization

Calling functions and methods in the Rust std library from a #[ctor] or #[dtor] function is not safe. This is because the std library only guarantees stability and portability between the beginning and end of main, whereas #[ctor] functions are called before main, and #[dtor] functions are called after it.

Recommendation

Do not call any part of the std library from a #[ctor] or #[dtor] function. Instead either:

  • Move the code to a different location, such as inside your program's main function.
  • Rewrite the code using an alternative library.

Example

In the following example, a #[ctor] function uses the println! macro which calls std library functions. This may cause unexpected behaviour at runtime.


#[ctor::ctor]
fn bad_example() {
    println!("Hello, world!"); // BAD: the println! macro calls std library functions
}

The issue can be fixed by replacing println! with something that does not rely on the std library. In the fixed code below we use the libc_println! macro from the libc-print library:


#[ctor::ctor]
fn good_example() {
    libc_print::libc_println!("Hello, world!"); // GOOD: libc-print does not use the std library
}

References

@paldepind
Copy link
Contributor

results are perhaps more likely to be more about correctness / reliability than security (in my opinion). There is a suitable CWE though.

Sounds right to me.

no transitive results through calls (yet), because we don't have call target resolution (yet, as far as I'm aware).

For global data flow we use the resolved paths that the extractor gives. But I don't think we have a suitable API for using that in queries yet. In C we have getTarget on function calls. Is that the thing that we'd want for queries?

Copy link
Contributor

@paldepind paldepind left a comment

Choose a reason for hiding this comment

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

Looks good to me 😄

@geoffw0
Copy link
Contributor Author

geoffw0 commented Nov 27, 2024

In C we have getTarget on function calls. Is that the thing that we'd want for queries?

Yep - or getStaticTarget() in Swift. @andersfugmann pointed out that even a placeholder predicate would allow us to fill the gaps in this query implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation ready-for-doc-review This PR requires and is ready for review from the GitHub docs team. Rust Pull requests that update Rust code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants