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

SGX's std::env::args function is not thread-safe #64304

Closed
KamilaBorowska opened this issue Sep 9, 2019 · 5 comments · Fixed by #69068
Closed

SGX's std::env::args function is not thread-safe #64304

KamilaBorowska opened this issue Sep 9, 2019 · 5 comments · Fixed by #69068
Assignees
Labels
C-bug Category: This is a bug. I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@KamilaBorowska
Copy link
Contributor

KamilaBorowska commented Sep 9, 2019

The args method is defined as follows.

pub fn args() -> Args {
    let args = unsafe { (ARGS.load(Ordering::Relaxed) as *const ArgsStore).as_ref() };
    if let Some(args) = args {
        Args(args.iter())
    } else {
        Args([].iter())
    }
}

Clean-up function is defined as follows;

pub unsafe fn cleanup() {
    let args = ARGS.swap(0, Ordering::Relaxed);
    if args != 0 {
        drop(Box::<ArgsStore>::from_raw(args as _))
    }
}

It is possible for another thread to use std::env::args() while the main thread quits, and access already freed memory - assuming the following sequence of events.

// Secondary thread
let args = unsafe { (ARGS.load(Ordering::Relaxed) as *const ArgsStore).as_ref() };
// Main thread
{
    let args = ARGS.swap(0, Ordering::Relaxed);
    if args != 0 {
        drop(Box::<ArgsStore>::from_raw(args as _))
    }
}
// Secondary thread
if let Some(args) = args {
    Args(args.iter())
}

This issue has been assigned to @Goirad via this comment.

@Mark-Simulacrum Mark-Simulacrum added I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Sep 10, 2019
@jonas-schievink jonas-schievink added the C-bug Category: This is a bug. label Sep 10, 2019
@jonas-schievink
Copy link
Contributor

cc @jethrogb

(do we want an O-fortanix-sgx label?)

@jethrogb
Copy link
Contributor

jethrogb commented Dec 10, 2019

I suppose we could just turn cleanup into a NOP. How do other platforms handle this?

@Goirad
Copy link
Contributor

Goirad commented Feb 5, 2020

@rustbot claim

@rustbot rustbot self-assigned this Feb 5, 2020
@Goirad
Copy link
Contributor

Goirad commented Feb 7, 2020

Looking at other implementations, the only times when this is not a NOP is for hermit vxcode and unix on non-apple variants. In all these cases the code is:

pub unsafe fn cleanup() {
    let _guard = LOCK.lock();
    ARGC = 0;
    ARGV = ptr::null();
}

I am inclined to just change it to a NOP. What was the motivation for the existing logic?

@jethrogb
Copy link
Contributor

What was the motivation for the existing logic?

Implement the required function cleanup without knowing exactly what needs to happen.

Having done some git archeology, it looks to me like the cleanup function exists solely for certain platforms where the arguments may be stored on the stack of the main thread. If the main thread exits, that stack may no longer be available so other threads may not reference it.

I think turning it into a nop for SGX is probably fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants