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

[PAL] Allow to validate entrypoint ELF file separately #1820

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

dimakuv
Copy link
Contributor

@dimakuv dimakuv commented Mar 15, 2024

Description of the changes

Previously, the entrypoint ELF file (loader.entrypoint in manifest) contents were validated during file read and file mmap, just like with all other files. In particular, Linux-SGX PAL expects the entrypoint to be marked as sgx.trusted_files and validates its SHA256 hash during file read/mmap.

However, future commits will move handling of sgx.trusted_files to the LibOS layer. Thus, file read/mmap at the PAL layer will lose validation guarantees. This commit introduces a separate loader.entrypoint_sha256 manifest option and a corresponding logic to validate the (only required) entrypoint file. A new assumption is made now, that the only file to be loaded by PAL (and not by LibOS) is this entrypoint file; this assumption can be made because the entrypoint has no dependencies.

Extracted from #1812.

Related to #1716 (ideally both should be merged one after another).

How to test this PR?

CI is enough.


This change is Reviewable

Previously, the entrypoint ELF file (`loader.entrypoint` in manifest)
contents were validated during file read and file mmap, just like with
all other files. In particular, Linux-SGX PAL expects the entrypoint to
be marked as `sgx.trusted_files` and validates its SHA256 hash during
file read/mmap.

However, future commits will move handling of `sgx.trusted_files` to the
LibOS layer. Thus, file read/mmap at the PAL layer will lose validation
guarantees. This commit introduces a separate `loader.entrypoint_sha256`
manifest option and a corresponding logic to validate the (only
required) entrypoint file. A new assumption is made now, that the only
file to be loaded by PAL (and not by LibOS) is this entrypoint file;
this assumption can be made because the entrypoint has no dependencies.

Signed-off-by: Dmitrii Kuvaiskii <dmitrii.kuvaiskii@intel.com>
Copy link
Contributor Author

@dimakuv dimakuv left a comment

Choose a reason for hiding this comment

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

Reviewable status: 0 of 6 files reviewed, all discussions resolved, not enough approvals from maintainers (2 more required), not enough approvals from different teams (1 more required, approved so far: Intel)


-- commits line 16 at r1:
Please note that this assumption is already enforced by our PAL code:

gramine/pal/src/pal_rtld.c

Lines 261 to 269 in e3d3aa3

case DT_NEEDED:
if (needed_offset_found) {
log_error("Loaded binary has more than one dependency (must be only one "
"dependency -- the PAL binary)");
return -PAL_ERROR_DENIED;
}
needed_offset = dynamic_section_entry->d_un.d_val;
needed_offset_found = true;
break;

Copy link
Contributor Author

@dimakuv dimakuv left a comment

Choose a reason for hiding this comment

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

Reviewable status: 0 of 6 files reviewed, 2 unresolved discussions, not enough approvals from maintainers (2 more required), not enough approvals from different teams (1 more required, approved so far: Intel) (waiting on @dimakuv)


pal/src/host/linux-sgx/pal_misc.c line 22 at r1 (raw file):

#include "pal_linux_error.h"
#include "seqlock.h"
#include "sgx_arch.h"

TODO: Get rid of sgx_arch.h and sgx_file_hash_t


pal/src/host/linux-sgx/pal_misc.c line 834 at r1 (raw file):

    }

    if (!entrypoint_sha256_str || strlen(entrypoint_sha256_str) != sizeof(sgx_file_hash_t) * 2) {

TODO: The first clause was already checked above, remove

Signed-off-by: Dmitrii Kuvaiskii <dmitrii.kuvaiskii@intel.com>
Copy link
Contributor Author

@dimakuv dimakuv left a comment

Choose a reason for hiding this comment

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

Reviewable status: 0 of 6 files reviewed, all discussions resolved, not enough approvals from maintainers (2 more required), not enough approvals from different teams (1 more required, approved so far: Intel), "fixup! " found in commit messages' one-liners


pal/src/host/linux-sgx/pal_misc.c line 22 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

TODO: Get rid of sgx_arch.h and sgx_file_hash_t

Done


pal/src/host/linux-sgx/pal_misc.c line 834 at r1 (raw file):

Previously, dimakuv (Dmitrii Kuvaiskii) wrote…

TODO: The first clause was already checked above, remove

Done

Copy link
Member

@mkow mkow left a comment

Choose a reason for hiding this comment

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

Reviewed 5 of 6 files at r1, 1 of 1 files at r2, all commit messages.
Reviewable status: all files reviewed, 6 unresolved discussions, not enough approvals from maintainers (1 more required), not enough approvals from different teams (1 more required, approved so far: Intel), "fixup! " found in commit messages' one-liners (waiting on @dimakuv)


-- commits line 2 at r2:
that's not optional, which "allow" implies

Suggestion:

[PAL] Validate entrypoint ELF file separately

pal/src/pal_rtld.c line 659 at r2 (raw file):

    ret = _PalStreamAttributesQueryByHandle(handle, &attr);
    if (ret < 0) {
        log_error("Getting size of ELF file failed");

Suggestion:

log_error("Getting size of loader entrypoint binary failed");

pal/src/pal_rtld.c line 665 at r2 (raw file):

    buf = malloc(attr.pending_size);
    if (!buf) {
        log_error("Allocating buffer to hold ELF file of size %lu failed", attr.pending_size);

ditto - missing context which ELF file
actually, same for a few other places below


pal/src/pal_rtld.c line 672 at r2 (raw file):

    size_t remaining = attr.pending_size;
    while (remaining > 0) {
        int64_t read = _PalStreamRead(handle, buf_offset, remaining, buf + buf_offset);

Everything here is wrong ;) ret vs read


pal/src/host/linux-sgx/pal_misc.c line 832 at r2 (raw file):

        log_error("Cannot find 'loader.entrypoint_sha256' in manifest");
        ret = -PAL_ERROR_INVAL;
        goto out;

Suggestion:

        return -PAL_ERROR_INVAL;

python/graminelibos/manifest.py line 304 at r2 (raw file):

        if not 'entrypoint_sha256' in loader:
            entrypoint_tf = TrustedFile.from_realpath(uri2path(loader['entrypoint'])).ensure_hash()
            loader.setdefault('entrypoint_sha256', entrypoint_tf.sha256);

Suggestion:

loader['entrypoint_sha256'] = entrypoint_tf.sha256

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants