diff --git a/src/core/image.c b/src/core/image.c index b1eba4ad4..ae09a0727 100644 --- a/src/core/image.c +++ b/src/core/image.c @@ -36,12 +36,28 @@ FILE_LICENCE ( GPL2_OR_LATER ); * */ +/* Disambiguate the various error causes */ +#define EACCES_UNTRUSTED \ + __einfo_error ( EINFO_EACCES_UNTRUSTED ) +#define EINFO_EACCES_UNTRUSTED \ + __einfo_uniqify ( EINFO_EACCES, 0x01, "Untrusted image" ) +#define EACCES_PERMANENT \ + __einfo_error ( EINFO_EACCES_PERMANENT ) +#define EINFO_EACCES_PERMANENT \ + __einfo_uniqify ( EINFO_EACCES, 0x02, "Trust requirement is permanent" ) + /** List of registered images */ struct list_head images = LIST_HEAD_INIT ( images ); /** Currently-executing image */ struct image *current_image; +/** Current image trust requirement */ +static int require_trusted_images = 0; + +/** Prevent changes to image trust requirement */ +static int require_trusted_images_permanent = 0; + /** * Free executable image * @@ -228,6 +244,12 @@ int image_exec ( struct image *image ) { if ( ( rc = image_select ( image ) ) != 0 ) return rc; + /* Check that image is trusted (if applicable) */ + if ( require_trusted_images && ! ( image->flags & IMAGE_TRUSTED ) ) { + DBGC ( image, "IMAGE %s is not trusted\n", image->name ); + return -EACCES_UNTRUSTED; + } + /* Switch current working directory to be that of the image itself */ old_cwuri = uri_get ( cwuri ); churi ( image->uri ); @@ -355,3 +377,27 @@ struct image * image_find_selected ( void ) { } return NULL; } + +/** + * Change image trust requirement + * + * @v require_trusted Require trusted images + * @v permanent Make trust requirement permanent + * @ret rc Return status code + */ +int image_set_trust ( int require_trusted, int permanent ) { + + /* Update trust requirement, if permitted to do so */ + if ( ! require_trusted_images_permanent ) { + require_trusted_images = require_trusted; + require_trusted_images_permanent = permanent; + } + + /* Fail if we attempted to change the trust requirement but + * were not permitted to do so. + */ + if ( require_trusted_images != require_trusted ) + return -EACCES_PERMANENT; + + return 0; +} diff --git a/src/include/ipxe/image.h b/src/include/ipxe/image.h index dbcd6d642..500b216ed 100644 --- a/src/include/ipxe/image.h +++ b/src/include/ipxe/image.h @@ -64,6 +64,9 @@ struct image { /** Image is selected for execution */ #define IMAGE_SELECTED 0x0002 +/** Image is trusted */ +#define IMAGE_TRUSTED 0x0004 + /** An executable image type */ struct image_type { /** Name of this image type */ @@ -148,6 +151,7 @@ extern int image_exec ( struct image *image ); extern int image_replace ( struct image *replacement ); extern int image_select ( struct image *image ); extern struct image * image_find_selected ( void ); +extern int image_set_trust ( int require_trusted, int permanent ); /** * Increment reference count on an image @@ -181,4 +185,22 @@ static inline int image_set_name ( struct image *image, const char *name ) { return 0; } +/** + * Set image as trusted + * + * @v image Image + */ +static inline void image_trust ( struct image *image ) { + image->flags |= IMAGE_TRUSTED; +} + +/** + * Set image as untrusted + * + * @v image Image + */ +static inline void image_untrust ( struct image *image ) { + image->flags &= ~IMAGE_TRUSTED; +} + #endif /* _IPXE_IMAGE_H */ diff --git a/src/usr/imgmgmt.c b/src/usr/imgmgmt.c index e323dd0c5..59011415b 100644 --- a/src/usr/imgmgmt.c +++ b/src/usr/imgmgmt.c @@ -140,6 +140,8 @@ void imgstat ( struct image *image ) { printf ( "%s : %zd bytes", image->name, image->len ); if ( image->type ) printf ( " [%s]", image->type->name ); + if ( image->flags & IMAGE_TRUSTED ) + printf ( " [TRUSTED]" ); if ( image->flags & IMAGE_SELECTED ) printf ( " [SELECTED]" ); if ( image->cmdline )