diff --git a/Makefile.am b/Makefile.am index abfdc6e9b7ab87617813f44b56f1f11693db7b2c..fb21633184c991c09d5d84f6f23020492577bdec 100644 --- a/Makefile.am +++ b/Makefile.am @@ -20,8 +20,7 @@ if VIRTUAL_PNOR_ENABLED include vpnor/Makefile.am.include else mboxd_SOURCES += flash.c \ - lpc_reset.c \ - protocol_negotiate_version.c + lpc_reset.c endif mboxctl_SOURCES = mboxctl.c diff --git a/flash.c b/flash.c index e6058f0ec3c05937ff04817165e2d547c1c3135e..6bd5c8449992d0dda7512d595017b01cb26daa68 100644 --- a/flash.c +++ b/flash.c @@ -105,6 +105,13 @@ void flash_dev_free(struct mbox_context *context) /* Flash Functions */ +int flash_validate(struct mbox_context *context, uint32_t offset, + uint32_t size, bool ro) +{ + /* Default behaviour is all accesses are valid */ + return 0; +} + /* * flash_is_erased() - Check if an offset into flash is erased * @context: The mbox context pointer diff --git a/flash.h b/flash.h index 44f5155497a52695a9e505e5ac64a636c049cebe..27605635059c757b339aaf115bf899193bfc0c9c 100644 --- a/flash.h +++ b/flash.h @@ -4,6 +4,7 @@ #ifndef FLASH_H #define FLASH_H +#include #include #define FLASH_DIRTY 0x00 @@ -16,6 +17,8 @@ struct mbox_context; int flash_dev_init(struct mbox_context *context); void flash_dev_free(struct mbox_context *context); +int flash_validate(struct mbox_context *context, uint32_t offset, + uint32_t size, bool ro); int64_t flash_copy(struct mbox_context *context, uint32_t offset, void *mem, uint32_t size); int flash_set_bytemap(struct mbox_context *context, uint32_t offset, diff --git a/protocol.c b/protocol.c index 2a04d897a0f113ed8deee2b44e38a10ae82f1ec4..76bc6ea45496d28ea3324ab42d46022fcaa2b9b1 100644 --- a/protocol.c +++ b/protocol.c @@ -7,8 +7,9 @@ #include "common.h" #include "flash.h" -#include "mboxd.h" #include "lpc.h" +#include "mboxd.h" +#include "protocol.h" #include "windows.h" #define BLOCK_SIZE_SHIFT_V1 12 /* 4K */ @@ -76,15 +77,18 @@ int protocol_events_clear(struct mbox_context *context, uint8_t bmc_event) return context->transport->clear_events(context, bmc_event, mask); } -int protocol_v1_reset(struct mbox_context *context) +static int protocol_v1_reset(struct mbox_context *context) { /* Host requested it -> No BMC Event */ windows_reset_all(context); return lpc_reset(context); } -int protocol_v1_get_info(struct mbox_context *context, - struct protocol_get_info *io) +static int protocol_negotiate_version(struct mbox_context *context, + uint8_t requested); + +static int protocol_v1_get_info(struct mbox_context *context, + struct protocol_get_info *io) { uint8_t old_version = context->version; int rc; @@ -120,7 +124,7 @@ int protocol_v1_get_info(struct mbox_context *context, return lpc_map_memory(context); } -int protocol_v1_get_flash_info(struct mbox_context *context, +static int protocol_v1_get_flash_info(struct mbox_context *context, struct protocol_get_flash_info *io) { io->resp.v1.flash_size = context->flash_size; @@ -149,11 +153,18 @@ static inline uint16_t get_lpc_addr_shifted(struct mbox_context *context) return lpc_addr >> context->block_size_shift; } -int protocol_v1_create_window(struct mbox_context *context, - struct protocol_create_window *io) +static int protocol_v1_create_window(struct mbox_context *context, + struct protocol_create_window *io) { - int rc; uint32_t offset = io->req.offset << context->block_size_shift; + uint32_t size = io->req.size << context->block_size_shift; + int rc; + + rc = flash_validate(context, offset, size, io->req.ro); + if (rc < 0) { + /* Backend does not allow window to be created. */ + return rc; + } /* Close the current window if there is one */ if (context->current) { @@ -202,8 +213,8 @@ int protocol_v1_create_window(struct mbox_context *context, return 0; } -int protocol_v1_mark_dirty(struct mbox_context *context, - struct protocol_mark_dirty *io) +static int protocol_v1_mark_dirty(struct mbox_context *context, + struct protocol_mark_dirty *io) { uint32_t offset = io->req.v1.offset; uint32_t size = io->req.v1.size; @@ -305,7 +316,8 @@ static int generic_flush(struct mbox_context *context) WINDOW_CLEAN); } -int protocol_v1_flush(struct mbox_context *context, struct protocol_flush *io) +static int protocol_v1_flush(struct mbox_context *context, + struct protocol_flush *io) { int rc; @@ -331,7 +343,8 @@ int protocol_v1_flush(struct mbox_context *context, struct protocol_flush *io) return generic_flush(context); } -int protocol_v1_close(struct mbox_context *context, struct protocol_close *io) +static int protocol_v1_close(struct mbox_context *context, + struct protocol_close *io) { int rc; @@ -355,7 +368,8 @@ int protocol_v1_close(struct mbox_context *context, struct protocol_close *io) return 0; } -int protocol_v1_ack(struct mbox_context *context, struct protocol_ack *io) +static int protocol_v1_ack(struct mbox_context *context, + struct protocol_ack *io) { return protocol_events_clear(context, (io->req.flags & BMC_EVENT_ACK_MASK)); @@ -380,8 +394,8 @@ static uint16_t get_suggested_timeout(struct mbox_context *context) return ret; } -int protocol_v2_get_info(struct mbox_context *context, - struct protocol_get_info *io) +static int protocol_v2_get_info(struct mbox_context *context, + struct protocol_get_info *io) { uint8_t old_version = context->version; int rc; @@ -415,8 +429,8 @@ int protocol_v2_get_info(struct mbox_context *context, return lpc_map_memory(context); } -int protocol_v2_get_flash_info(struct mbox_context *context, - struct protocol_get_flash_info *io) +static int protocol_v2_get_flash_info(struct mbox_context *context, + struct protocol_get_flash_info *io) { io->resp.v2.flash_size = context->flash_size >> context->block_size_shift; @@ -426,8 +440,8 @@ int protocol_v2_get_flash_info(struct mbox_context *context, return 0; } -int protocol_v2_create_window(struct mbox_context *context, - struct protocol_create_window *io) +static int protocol_v2_create_window(struct mbox_context *context, + struct protocol_create_window *io) { int rc; @@ -442,8 +456,8 @@ int protocol_v2_create_window(struct mbox_context *context, return 0; } -int protocol_v2_mark_dirty(struct mbox_context *context, - struct protocol_mark_dirty *io) +static int protocol_v2_mark_dirty(struct mbox_context *context, + struct protocol_mark_dirty *io) { if (!(context->current && context->current_is_write)) { MSG_ERR("Tried to call mark dirty without open write window\n"); @@ -458,8 +472,8 @@ int protocol_v2_mark_dirty(struct mbox_context *context, io->req.v2.size, WINDOW_DIRTY); } -int protocol_v2_erase(struct mbox_context *context, - struct protocol_erase *io) +static int protocol_v2_erase(struct mbox_context *context, + struct protocol_erase *io) { size_t start, len; int rc; @@ -487,7 +501,8 @@ int protocol_v2_erase(struct mbox_context *context, return 0; } -int protocol_v2_flush(struct mbox_context *context, struct protocol_flush *io) +static int protocol_v2_flush(struct mbox_context *context, + struct protocol_flush *io) { if (!(context->current && context->current_is_write)) { MSG_ERR("Tried to call flush without open write window\n"); @@ -497,7 +512,8 @@ int protocol_v2_flush(struct mbox_context *context, struct protocol_flush *io) return generic_flush(context); } -int protocol_v2_close(struct mbox_context *context, struct protocol_close *io) +static int protocol_v2_close(struct mbox_context *context, + struct protocol_close *io) { int rc; @@ -521,6 +537,51 @@ int protocol_v2_close(struct mbox_context *context, struct protocol_close *io) return 0; } +static const struct protocol_ops protocol_ops_v1 = { + .reset = protocol_v1_reset, + .get_info = protocol_v1_get_info, + .get_flash_info = protocol_v1_get_flash_info, + .create_window = protocol_v1_create_window, + .mark_dirty = protocol_v1_mark_dirty, + .erase = NULL, + .flush = protocol_v1_flush, + .close = protocol_v1_close, + .ack = protocol_v1_ack, +}; + +static const struct protocol_ops protocol_ops_v2 = { + .reset = protocol_v1_reset, + .get_info = protocol_v2_get_info, + .get_flash_info = protocol_v2_get_flash_info, + .create_window = protocol_v2_create_window, + .mark_dirty = protocol_v2_mark_dirty, + .erase = protocol_v2_erase, + .flush = protocol_v2_flush, + .close = protocol_v2_close, + .ack = protocol_v1_ack, +}; + +static const struct protocol_ops *protocol_ops_map[] = { + [0] = NULL, + [1] = &protocol_ops_v1, + [2] = &protocol_ops_v2, +}; + +static int protocol_negotiate_version(struct mbox_context *context, + uint8_t requested) +{ + /* Check we support the version requested */ + if (requested < API_MIN_VERSION) + return -EINVAL; + + context->version = (requested > API_MAX_VERSION) ? + API_MAX_VERSION : requested; + + context->protocol = protocol_ops_map[context->version]; + + return context->version; +} + int protocol_init(struct mbox_context *context) { protocol_negotiate_version(context, API_MAX_VERSION); diff --git a/protocol.h b/protocol.h index 5a678c6e312ecd5ae9051ec55fc33ce97fcb2ab3..f571fe1fcf97f062d92d00f17f2afa3ff76f951e 100644 --- a/protocol.h +++ b/protocol.h @@ -119,8 +119,6 @@ struct protocol_ops { int protocol_init(struct mbox_context *context); void protocol_free(struct mbox_context *context); -int protocol_negotiate_version(struct mbox_context *context, uint8_t requested); - /* Sneaky reset: Don't tell the host */ int __protocol_reset(struct mbox_context *context); @@ -132,32 +130,4 @@ int protocol_events_put(struct mbox_context *context, int protocol_events_set(struct mbox_context *context, uint8_t bmc_event); int protocol_events_clear(struct mbox_context *context, uint8_t bmc_event); -/* Protocol v1 */ -int protocol_v1_reset(struct mbox_context *context); -int protocol_v1_get_info(struct mbox_context *context, - struct protocol_get_info *io); -int protocol_v1_get_flash_info(struct mbox_context *context, - struct protocol_get_flash_info *io); -int protocol_v1_create_window(struct mbox_context *context, - struct protocol_create_window *io); -int protocol_v1_mark_dirty(struct mbox_context *context, - struct protocol_mark_dirty *io); -int protocol_v1_flush(struct mbox_context *context, struct protocol_flush *io); -int protocol_v1_close(struct mbox_context *context, struct protocol_close *io); -int protocol_v1_ack(struct mbox_context *context, struct protocol_ack *io); - -/* Protocol v2 */ -int protocol_v2_get_info(struct mbox_context *context, - struct protocol_get_info *io); -int protocol_v2_get_flash_info(struct mbox_context *context, - struct protocol_get_flash_info *io); -int protocol_v2_create_window(struct mbox_context *context, - struct protocol_create_window *io); -int protocol_v2_mark_dirty(struct mbox_context *context, - struct protocol_mark_dirty *io); -int protocol_v2_erase(struct mbox_context *context, - struct protocol_erase *io); -int protocol_v2_flush(struct mbox_context *context, struct protocol_flush *io); -int protocol_v2_close(struct mbox_context *context, struct protocol_close *io); - #endif /* PROTOCOL_H */ diff --git a/protocol_negotiate_version.c b/protocol_negotiate_version.c deleted file mode 100644 index 16b8e64ee6e6f2faf6da8ee23999f6f528003a29..0000000000000000000000000000000000000000 --- a/protocol_negotiate_version.c +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright (C) 2018 IBM Corp. -#include "config.h" - -#include - -#include "mboxd.h" -#include "protocol.h" - -static const struct protocol_ops protocol_ops_v1 = { - .reset = protocol_v1_reset, - .get_info = protocol_v1_get_info, - .get_flash_info = protocol_v1_get_flash_info, - .create_window = protocol_v1_create_window, - .mark_dirty = protocol_v1_mark_dirty, - .erase = NULL, - .flush = protocol_v1_flush, - .close = protocol_v1_close, - .ack = protocol_v1_ack, -}; - -static const struct protocol_ops protocol_ops_v2 = { - .reset = protocol_v1_reset, - .get_info = protocol_v2_get_info, - .get_flash_info = protocol_v2_get_flash_info, - .create_window = protocol_v2_create_window, - .mark_dirty = protocol_v2_mark_dirty, - .erase = protocol_v2_erase, - .flush = protocol_v2_flush, - .close = protocol_v2_close, - .ack = protocol_v1_ack, -}; - -static const struct protocol_ops *protocol_ops_map[] = { - [0] = NULL, - [1] = &protocol_ops_v1, - [2] = &protocol_ops_v2, -}; - -int protocol_negotiate_version(struct mbox_context *context, - uint8_t requested) -{ - /* Check we support the version requested */ - if (requested < API_MIN_VERSION) - return -EINVAL; - - context->version = (requested > API_MAX_VERSION) ? - API_MAX_VERSION : requested; - - context->protocol = protocol_ops_map[context->version]; - - return context->version; -} diff --git a/test/Makefile.am.include b/test/Makefile.am.include index de1bfce2be585e0a6e1d58ef1fc76624b64c736a..195e4517f7f909560f395521ec2a90e61702086e 100644 --- a/test/Makefile.am.include +++ b/test/Makefile.am.include @@ -26,8 +26,7 @@ TEST_MBOX_SRCS = \ lpc_reset.c \ common.c \ flash.c \ - protocol.c \ - protocol_negotiate_version.c + protocol.c TEST_MOCK_SRCS = %reldir%/tmpf.c %reldir%/mbox.c %reldir%/system.c diff --git a/vpnor/Makefile.am.include b/vpnor/Makefile.am.include index 75bd92e83d3575171a9c7717edaecee88a1c2436..36e3c5073033dc7b34ee6c7693f20f11d072ddff 100644 --- a/vpnor/Makefile.am.include +++ b/vpnor/Makefile.am.include @@ -2,9 +2,7 @@ mboxd_SOURCES += %reldir%/pnor_partition_table.cpp \ %reldir%/mboxd_pnor_partition_table.cpp \ %reldir%/flash.cpp \ %reldir%/pnor_partition.cpp \ - %reldir%/lpc_reset.cpp \ - %reldir%/protocol.cpp \ - %reldir%/protocol_negotiate_version.cpp + %reldir%/lpc_reset.cpp mboxd_LDFLAGS += -lstdc++fs \ $(SDBUSPLUS_LIBS) \ diff --git a/vpnor/flash.cpp b/vpnor/flash.cpp index cd2a37f2c5adc8b995bf93e91b743933afbc8051..847e6a52c8280f8a6149c94cf4d280403011eb72 100644 --- a/vpnor/flash.cpp +++ b/vpnor/flash.cpp @@ -237,3 +237,39 @@ int flash_write(struct mbox_context* context, uint32_t offset, void* buf, } return 0; } + +static bool vpnor_partition_is_readonly(const pnor_partition& part) +{ + return part.data.user.data[1] & PARTITION_READONLY; +} + +int flash_validate(struct mbox_context* context, uint32_t offset, + uint32_t size __attribute__((unused)), bool ro) +{ + /* All reads are allowed */ + if (ro) + { + return 0; + } + + /* Only allow write windows on regions mapped by the ToC as writeable */ + try + { + const pnor_partition& part = context->vpnor->table->partition(offset); + if (vpnor_partition_is_readonly(part)) + { + return -EPERM; + } + } + catch (const openpower::virtual_pnor::UnmappedOffset& e) + { + /* + * Writes to unmapped areas are not meaningful, so deny the request. + * This removes the ability for a compromised host to abuse unused + * space if any data was to be persisted (which it isn't). + */ + return -EACCES; + } + + return 0; +} diff --git a/vpnor/protocol.cpp b/vpnor/protocol.cpp deleted file mode 100644 index c3f4fca51b627d8be5d13bb92ef3c35b5c1ffa47..0000000000000000000000000000000000000000 --- a/vpnor/protocol.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright (C) 2018 IBM Corp. -#include "config.h" - -extern "C" { -#include "mboxd.h" -#include "protocol.h" -#include "vpnor/protocol.h" -} - -#include "vpnor/pnor_partition_table.hpp" - -/* XXX: Maybe this should be a method on a class? */ -static bool vpnor_partition_is_readonly(const pnor_partition& part) -{ - return part.data.user.data[1] & PARTITION_READONLY; -} - -typedef int (*create_window_fn)(struct mbox_context* context, - struct protocol_create_window* io); - -static int generic_vpnor_create_window(struct mbox_context* context, - struct protocol_create_window* io, - create_window_fn create_window) -{ - if (io->req.ro) - { - return create_window(context, io); - } - - /* Only allow write windows on regions mapped by the ToC as writeable */ - size_t offset = io->req.offset; - offset <<= context->block_size_shift; - try - { - const pnor_partition& part = context->vpnor->table->partition(offset); - if (vpnor_partition_is_readonly(part)) - { - return -EPERM; - } - } - catch (const openpower::virtual_pnor::UnmappedOffset& e) - { - /* - * Writes to unmapped areas are not meaningful, so deny the request. - * This removes the ability for a compromised host to abuse unused - * space if any data was to be persisted (which it isn't). - */ - return -EACCES; - } - - return create_window(context, io); -} - -int protocol_v1_vpnor_create_window(struct mbox_context* context, - struct protocol_create_window* io) -{ - return generic_vpnor_create_window(context, io, protocol_v1_create_window); -} - -int protocol_v2_vpnor_create_window(struct mbox_context* context, - struct protocol_create_window* io) -{ - return generic_vpnor_create_window(context, io, protocol_v2_create_window); -} diff --git a/vpnor/protocol_negotiate_version.cpp b/vpnor/protocol_negotiate_version.cpp deleted file mode 100644 index 12593ea82ba2994ee2a9c20fa1778d57eba4899d..0000000000000000000000000000000000000000 --- a/vpnor/protocol_negotiate_version.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright (C) 2018 IBM Corp. -#include "config.h" - -#include - -extern "C" { -#include "mboxd.h" -#include "protocol.h" -#include "vpnor/protocol.h" -} - -/* We need to hijack create_window for vpnor */ - -static const struct protocol_ops protocol_ops_v1 = { - .reset = protocol_v1_reset, - .get_info = protocol_v1_get_info, - .get_flash_info = protocol_v1_get_flash_info, - .create_window = protocol_v1_vpnor_create_window, - .mark_dirty = protocol_v1_mark_dirty, - .erase = NULL, - .flush = protocol_v1_flush, - .close = protocol_v1_close, - .ack = protocol_v1_ack, -}; - -static const struct protocol_ops protocol_ops_v2 = { - .reset = protocol_v1_reset, - .get_info = protocol_v2_get_info, - .get_flash_info = protocol_v2_get_flash_info, - .create_window = protocol_v2_vpnor_create_window, - .mark_dirty = protocol_v2_mark_dirty, - .erase = protocol_v2_erase, - .flush = protocol_v2_flush, - .close = protocol_v2_close, - .ack = protocol_v1_ack, -}; - -static const struct protocol_ops* protocol_ops_map[] = { - [0] = NULL, - [1] = &protocol_ops_v1, - [2] = &protocol_ops_v2, -}; - -int protocol_negotiate_version(struct mbox_context* context, uint8_t requested) -{ - /* Check we support the version requested */ - if (requested < API_MIN_VERSION) - return -EINVAL; - - uint8_t version = - (requested > API_MAX_VERSION) ? API_MAX_VERSION : requested; - context->version = static_cast(version); - - context->protocol = protocol_ops_map[context->version]; - - return context->version; -} diff --git a/vpnor/test/Makefile.am.include b/vpnor/test/Makefile.am.include index f3f4fc2897e9e48674deed30a507c541fa939952..5ff4dcc0e27ebe51a1c87a2cea04412b6392d87a 100644 --- a/vpnor/test/Makefile.am.include +++ b/vpnor/test/Makefile.am.include @@ -14,8 +14,6 @@ TEST_MBOX_VPNOR_INTEG_SRCS = \ vpnor/flash.cpp \ vpnor/pnor_partition.cpp \ vpnor/pnor_partition_table.cpp \ - vpnor/protocol.cpp \ - vpnor/protocol_negotiate_version.cpp \ %reldir%/tmpd.cpp VPNOR_LDADD = -lstdc++fs \