-
Notifications
You must be signed in to change notification settings - Fork 121
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Snapsafe-type uniqueness breaking event detection (#1640)
- Loading branch information
Showing
16 changed files
with
434 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 OR ISC | ||
|
||
#include <openssl/crypto.h> | ||
|
||
#include "snapsafe_detect.h" | ||
|
||
#if defined(OPENSSL_LINUX) | ||
#include <fcntl.h> | ||
#include <stdlib.h> | ||
#include <sys/mman.h> | ||
#include <unistd.h> | ||
#include "../delocate.h" | ||
|
||
// Snapsafety state | ||
#define SNAPSAFETY_STATE_FAILED_INITIALISE 0x00 | ||
#define SNAPSAFETY_STATE_SUCCESS_INITIALISE 0x01 | ||
#define SNAPSAFETY_STATE_NOT_SUPPORTED 0x02 | ||
|
||
DEFINE_STATIC_ONCE(aws_snapsafe_init) | ||
DEFINE_BSS_GET(volatile uint32_t *, sgc_addr) | ||
DEFINE_BSS_GET(int, snapsafety_state) | ||
|
||
// aws_snapsafe_check_kernel_support returns 1 if the special sysgenid device | ||
// file exists and 0 otherwise. | ||
static int aws_snapsafe_check_kernel_support(void) { | ||
// This file-exist method is generally brittle. But for our purpose, this | ||
// should be more than fine. | ||
if (access(CRYPTO_get_sysgenid_path(), F_OK) != 0) { | ||
return 0; | ||
} | ||
return 1; | ||
} | ||
|
||
static void do_aws_snapsafe_init(void) { | ||
*snapsafety_state_bss_get() = SNAPSAFETY_STATE_NOT_SUPPORTED; | ||
*sgc_addr_bss_get() = NULL; | ||
|
||
if (aws_snapsafe_check_kernel_support() != 1) { | ||
return; | ||
} | ||
*snapsafety_state_bss_get() = SNAPSAFETY_STATE_FAILED_INITIALISE; | ||
|
||
int fd_sgc = open(CRYPTO_get_sysgenid_path(), O_RDONLY); | ||
if (fd_sgc == -1) { | ||
return; | ||
} | ||
|
||
void *addr = mmap(NULL, sizeof(uint32_t), PROT_READ, MAP_SHARED, fd_sgc, 0); | ||
|
||
// Can close file descriptor now per | ||
// https://man7.org/linux/man-pages/man2/mmap.2.html: "After the mmap() call | ||
// has returned, the file descriptor, fd, can be closed immediately without | ||
// invalidating the mapping.". We have initialised snapsafety without errors | ||
// and this function is only executed once. Therefore, try to close file | ||
// descriptor but don't error if it fails. */ | ||
close(fd_sgc); | ||
|
||
if (addr == MAP_FAILED) { | ||
return; | ||
} | ||
|
||
// sgc_addr will now point at the mapped memory and any 4-byte read from | ||
// this pointer will correspond to the sgn managed by the VMM. | ||
*sgc_addr_bss_get() = addr; | ||
*snapsafety_state_bss_get() = SNAPSAFETY_STATE_SUCCESS_INITIALISE; | ||
} | ||
|
||
static uint32_t aws_snapsafe_read_sgn(void) { | ||
if (*snapsafety_state_bss_get() == SNAPSAFETY_STATE_SUCCESS_INITIALISE) { | ||
return **sgc_addr_bss_get(); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int CRYPTO_get_snapsafe_generation(uint32_t *snapsafe_generation_number) { | ||
CRYPTO_once(aws_snapsafe_init_bss_get(), do_aws_snapsafe_init); | ||
|
||
int state = *snapsafety_state_bss_get(); | ||
switch (state) { | ||
case SNAPSAFETY_STATE_NOT_SUPPORTED: | ||
*snapsafe_generation_number = 0; | ||
return 1; | ||
case SNAPSAFETY_STATE_SUCCESS_INITIALISE: | ||
*snapsafe_generation_number = aws_snapsafe_read_sgn(); | ||
return 1; | ||
case SNAPSAFETY_STATE_FAILED_INITIALISE: | ||
*snapsafe_generation_number = 0; | ||
return 0; | ||
default: | ||
// No other state should be possible. | ||
abort(); | ||
} | ||
} | ||
|
||
int CRYPTO_get_snapsafe_active(void) { | ||
CRYPTO_once(aws_snapsafe_init_bss_get(), do_aws_snapsafe_init); | ||
|
||
if (*snapsafety_state_bss_get() == SNAPSAFETY_STATE_SUCCESS_INITIALISE) { | ||
return 1; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
int CRYPTO_get_snapsafe_supported(void) { | ||
CRYPTO_once(aws_snapsafe_init_bss_get(), do_aws_snapsafe_init); | ||
|
||
if (*snapsafety_state_bss_get() == SNAPSAFETY_STATE_NOT_SUPPORTED) { | ||
return 0; | ||
} | ||
|
||
return 1; | ||
} | ||
|
||
#else // !defined(OPENSSL_LINUX) | ||
|
||
int CRYPTO_get_snapsafe_generation(uint32_t *snapsafe_generation_number) { | ||
*snapsafe_generation_number = 0; | ||
return 1; | ||
} | ||
|
||
int CRYPTO_get_snapsafe_active(void) { return 0; } | ||
|
||
int CRYPTO_get_snapsafe_supported(void) { return 0; } | ||
|
||
#endif // defined(OPENSSL_LINUX) | ||
|
||
const char* CRYPTO_get_sysgenid_path(void) { | ||
return AWSLC_SYSGENID_PATH; | ||
} | ||
|
||
#if defined(OPENSSL_LINUX) && defined(AWSLC_SNAPSAFE_TESTING) | ||
int HAZMAT_init_sysgenid_file(void) { | ||
int fd_sgn = open(CRYPTO_get_sysgenid_path(), O_CREAT | O_RDWR, S_IRWXU | S_IRGRP | S_IROTH); | ||
if (fd_sgn == -1) { | ||
return 0; | ||
} | ||
if (0 != lseek(fd_sgn, 0, SEEK_SET)) { | ||
close(fd_sgn); | ||
return 0; | ||
} | ||
uint32_t value = 0; | ||
if(0 >= write(fd_sgn, &value, sizeof(uint32_t))) { | ||
close(fd_sgn); | ||
return 0; | ||
} | ||
|
||
if (0 != fsync(fd_sgn)) { | ||
return 0; | ||
} | ||
|
||
close(fd_sgn); | ||
|
||
return 1; | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. | ||
// SPDX-License-Identifier: Apache-2.0 OR ISC | ||
|
||
#ifndef HEADER_SNAPSAFE_DETECT | ||
#define HEADER_SNAPSAFE_DETECT | ||
|
||
#include <openssl/base.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#if !defined(AWSLC_SYSGENID_PATH) | ||
#define AWSLC_SYSGENID_PATH "/dev/sysgenid" | ||
#endif | ||
|
||
// Snapsafe-type uniqueness breaking event (ube detection). | ||
// | ||
// CRYPTO_get_snapsafe_generation provides the snapsafe generation number for | ||
// the current process. The snapsafe generation number is a non-zero, | ||
// strictly-monotonic counter with the property that, if queried in an address | ||
// space and then again in a subsequently resumed snapshot/VM, the resumed | ||
// address space will observe a greater value. | ||
// | ||
// We use SysGenID to detect resumed snapshot/VM events. See | ||
// https://lkml.org/lkml/2021/3/8/677 for details about how SysGenID works. | ||
// We make light use of the SysGenId capabilities and only use the following | ||
// supported functions on the device: |open| and |mmap|. | ||
// | ||
// |CRYPTO_get_snapsafe_generation| returns 0 only when the filesystem | ||
// presents SysGenID interface (default is `/dev/sysgenid`) but we are | ||
// is unable to initialize its use. Otherwise, it returns 1. | ||
OPENSSL_EXPORT int CRYPTO_get_snapsafe_generation( | ||
uint32_t *snapsafe_generation_number); | ||
|
||
// CRYPTO_get_snapsafe_active returns 1 if the file system presents the SysGenID | ||
// interface and the libraruy has successfully initialized its use. Otherwise, | ||
// it returns 0. | ||
OPENSSL_EXPORT int CRYPTO_get_snapsafe_active(void); | ||
|
||
// CRYPTO_get_snapsafe_supported returns 1 if the file system presents the | ||
// SysGenID interface. Otherwise, it returns 0. | ||
OPENSSL_EXPORT int CRYPTO_get_snapsafe_supported(void); | ||
|
||
// CRYPTO_get_sysgenid_path returns the path used for the SysGenId interface. | ||
OPENSSL_EXPORT const char *CRYPTO_get_sysgenid_path(void); | ||
|
||
#if defined(OPENSSL_LINUX) && defined(AWSLC_SNAPSAFE_TESTING) | ||
// HAZMAT_init_sysgenid_file should only be used for testing. It creates and | ||
// initializes the sysgenid path indicated by AWSLC_SYSGENID_PATH. | ||
// On success, it returns 1. Otherwise, returns 0. | ||
OPENSSL_EXPORT int HAZMAT_init_sysgenid_file(void); | ||
#endif | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif /* HEADER_SNAPSAFE_DETECT */ |
Oops, something went wrong.