iPXE
Defines | Functions | Variables
image.c File Reference

Executable images. More...

#include <stddef.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <libgen.h>
#include <syslog.h>
#include <ipxe/list.h>
#include <ipxe/umalloc.h>
#include <ipxe/uri.h>
#include <ipxe/image.h>

Go to the source code of this file.

Defines

#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" )

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static void free_image (struct refcnt *refcnt)
 Free executable image.
struct imagealloc_image (struct uri *uri)
 Allocate executable image.
int image_set_uri (struct image *image, struct uri *uri)
 Set image URI.
int image_set_name (struct image *image, const char *name)
 Set image name.
int image_set_cmdline (struct image *image, const char *cmdline)
 Set image command line.
static int image_probe (struct image *image)
 Determine image type.
int register_image (struct image *image)
 Register executable image.
void unregister_image (struct image *image)
 Unregister executable image.
struct imagefind_image (const char *name)
 Find image by name.
int image_exec (struct image *image)
 Execute image.
int image_replace (struct image *replacement)
 Set replacement image.
int image_select (struct image *image)
 Select image for execution.
struct imageimage_find_selected (void)
 Find selected image.
int image_set_trust (int require_trusted, int permanent)
 Change image trust requirement.

Variables

struct list_head images = LIST_HEAD_INIT ( images )
 List of registered images.
struct imagecurrent_image
 Currently-executing image.
static int require_trusted_images = 0
 Current image trust requirement.
static int require_trusted_images_permanent = 0
 Prevent changes to image trust requirement.

Detailed Description

Executable images.

Definition in file image.c.


Define Documentation

Definition at line 46 of file image.c.

Referenced by image_exec().

#define EINFO_EACCES_UNTRUSTED   __einfo_uniqify ( EINFO_EACCES, 0x01, "Untrusted image" )

Definition at line 48 of file image.c.

Definition at line 50 of file image.c.

Referenced by image_set_trust().

#define EINFO_EACCES_PERMANENT   __einfo_uniqify ( EINFO_EACCES, 0x02, "Trust requirement is permanent" )

Definition at line 52 of file image.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static void free_image ( struct refcnt refcnt) [static]

Free executable image.

Parameters:
refcntReference counter

Definition at line 72 of file image.c.

References image::cmdline, container_of, image::data, DBGC, free, image_put(), image::name, image::replacement, ufree(), image::uri, and uri_put().

Referenced by alloc_image().

                                                 {
        struct image *image = container_of ( refcnt, struct image, refcnt );

        DBGC ( image, "IMAGE %s freed\n", image->name );
        free ( image->name );
        free ( image->cmdline );
        uri_put ( image->uri );
        ufree ( image->data );
        image_put ( image->replacement );
        free ( image );
}
struct image* alloc_image ( struct uri uri) [read]

Allocate executable image.

Parameters:
uriURI, or NULL
Return values:
imageExecutable image

Definition at line 90 of file image.c.

References free_image(), image_put(), image_set_uri(), NULL, rc, ref_init, image::refcnt, and zalloc().

Referenced by imgdownload(), and initrd_init().

                                               {
        struct image *image;
        int rc;

        /* Allocate image */
        image = zalloc ( sizeof ( *image ) );
        if ( ! image )
                goto err_alloc;

        /* Initialise image */
        ref_init ( &image->refcnt, free_image );
        if ( uri && ( ( rc = image_set_uri ( image, uri ) ) != 0 ) )
                goto err_set_uri;

        return image;

 err_set_uri:
        image_put ( image );
 err_alloc:
        return NULL;
}
int image_set_uri ( struct image image,
struct uri uri 
)

Set image URI.

Parameters:
imageImage
uriNew image URI
Return values:
rcReturn status code

Definition at line 119 of file image.c.

References basename(), image_set_name(), image::name, name, uri::path, rc, image::uri, uri_get(), and uri_put().

Referenced by alloc_image(), and downloader_vredirect().

                                                           {
        const char *name;
        int rc;

        /* Set name, if image does not already have one */
        if ( uri->path && ( ! ( image->name && image->name[0] ) ) ) {
                name = basename ( ( char * ) uri->path );
                if ( ( rc = image_set_name ( image, name ) ) != 0 )
                        return rc;
        }

        /* Update image URI */
        uri_put ( image->uri );
        image->uri = uri_get ( uri );

        return 0;
}
int image_set_name ( struct image image,
const char *  name 
)

Set image name.

Parameters:
imageImage
nameNew image name
Return values:
rcReturn status code

Definition at line 144 of file image.c.

References ENOMEM, free, image::name, and strdup().

Referenced by image_set_uri(), imgsingle_exec(), initrd_init(), and register_image().

                                                             {
        char *name_copy;

        /* Duplicate name */
        name_copy = strdup ( name );
        if ( ! name_copy )
                return -ENOMEM;

        /* Replace existing name */
        free ( image->name );
        image->name = name_copy;

        return 0;
}
int image_set_cmdline ( struct image image,
const char *  cmdline 
)

Set image command line.

Parameters:
imageImage
cmdlineNew image command line, or NULL
Return values:
rcReturn status code

Definition at line 166 of file image.c.

References image::cmdline, ENOMEM, free, NULL, and strdup().

Referenced by image_clear_cmdline(), and imgsingle_exec().

                                                                   {

        free ( image->cmdline );
        image->cmdline = NULL;
        if ( cmdline ) {
                image->cmdline = strdup ( cmdline );
                if ( ! image->cmdline )
                        return -ENOMEM;
        }
        return 0;
}
static int image_probe ( struct image image) [static]

Determine image type.

Parameters:
imageExecutable image
Return values:
rcReturn status code

Definition at line 184 of file image.c.

References DBGC, ENOTSUP, for_each_table_entry, IMAGE_TYPES, image::name, image_type::name, image_type::probe, rc, strerror(), image::type, and type.

Referenced by register_image().

                                               {
        struct image_type *type;
        int rc;

        /* Try each type in turn */
        for_each_table_entry ( type, IMAGE_TYPES ) {
                if ( ( rc = type->probe ( image ) ) == 0 ) {
                        image->type = type;
                        DBGC ( image, "IMAGE %s is %s\n",
                               image->name, type->name );
                        return 0;
                }
                DBGC ( image, "IMAGE %s is not %s: %s\n", image->name,
                       type->name, strerror ( rc ) );
        }

        DBGC ( image, "IMAGE %s format not recognised\n", image->name );
        return -ENOTSUP;
}
int register_image ( struct image image)

Register executable image.

Parameters:
imageExecutable image
Return values:
rcReturn status code

Definition at line 210 of file image.c.

References image::data, DBGC, image::flags, image_find_selected(), image_get(), image_probe(), IMAGE_REGISTERED, IMAGE_SELECTED, image_set_name(), image::len, image::list, list_add_tail, image::name, name, rc, snprintf(), image::type, and user_to_phys().

Referenced by asn1_okx(), cmdline_init(), embedded_init(), imgdownload(), initrd_init(), pixbuf_okx(), script_exec(), and test_init().

                                           {
        static unsigned int imgindex = 0;
        char name[8]; /* "imgXXXX" */
        int rc;

        /* Create image name if it doesn't already have one */
        if ( ! image->name ) {
                snprintf ( name, sizeof ( name ), "img%d", imgindex++ );
                if ( ( rc = image_set_name ( image, name ) ) != 0 )
                        return rc;
        }

        /* Avoid ending up with multiple "selected" images on
         * re-registration
         */
        if ( image_find_selected() )
                image->flags &= ~IMAGE_SELECTED;

        /* Add to image list */
        image_get ( image );
        image->flags |= IMAGE_REGISTERED;
        list_add_tail ( &image->list, &images );
        DBGC ( image, "IMAGE %s at [%lx,%lx) registered\n",
               image->name, user_to_phys ( image->data, 0 ),
               user_to_phys ( image->data, image->len ) );

        /* Try to detect image type, if applicable.  Ignore failures,
         * since we expect to handle some unrecognised images
         * (e.g. kernel initrds, multiboot modules, random files
         * provided via our EFI virtual filesystem, etc).
         */
        if ( ! image->type )
                image_probe ( image );

        return 0;
}
void unregister_image ( struct image image)

Unregister executable image.

Parameters:
imageExecutable image

Definition at line 252 of file image.c.

References DBGC, image::flags, image_put(), IMAGE_REGISTERED, image::list, list_del, and image::name.

Referenced by asn1_okx(), bzimage_exec(), cert_exec(), com32_exec_loop(), comboot_exec_loop(), console_exec(), image_exec(), imgfree_exec(), imgverify_exec(), pixbuf_okx(), and script_exec().

                                              {

        /* Do nothing unless image is registered */
        if ( ! ( image->flags & IMAGE_REGISTERED ) )
                return;

        DBGC ( image, "IMAGE %s unregistered\n", image->name );
        list_del ( &image->list );
        image->flags &= ~IMAGE_REGISTERED;
        image_put ( image );
}
struct image* find_image ( const char *  name) [read]

Find image by name.

Parameters:
nameImage name
Return values:
imageExecutable image, or NULL

Definition at line 270 of file image.c.

References image::list, list_for_each_entry, image::name, NULL, and strcmp().

Referenced by imgacquire(), and imgmulti_exec().

                                               {
        struct image *image;

        list_for_each_entry ( image, &images, list ) {
                if ( strcmp ( image->name, name ) == 0 )
                        return image;
        }

        return NULL;
}
int image_exec ( struct image image)

Execute image.

Parameters:
imageExecutable image
Return values:
rcReturn status code

The image must already be registered. Note that executing an image may cause it to unregister itself. The caller must therefore assume that the image pointer becomes invalid.

Definition at line 291 of file image.c.

References assert, churi(), current_image, cwuri, DBGC, EACCES_UNTRUSTED, ENOEXEC, image_type::exec, image::flags, IMAGE_AUTO_UNREGISTER, image_exec(), image_get(), image_put(), IMAGE_REGISTERED, IMAGE_TRUSTED, LOG_ERR, LOG_NOTICE, image::name, NULL, rc, image::replacement, require_trusted_images, strerror(), syslog, image::type, unregister_image(), image::uri, uri_get(), and uri_put().

Referenced by image_exec(), imgexec(), ipxe(), and uriboot().

                                       {
        struct image *saved_current_image;
        struct image *replacement = NULL;
        struct uri *old_cwuri;
        int rc;

        /* Sanity check */
        assert ( image->flags & IMAGE_REGISTERED );

        /* Switch current working directory to be that of the image itself */
        old_cwuri = uri_get ( cwuri );
        churi ( image->uri );

        /* Preserve record of any currently-running image */
        saved_current_image = current_image;

        /* Take out a temporary reference to the image.  This allows
         * the image to unregister itself if necessary, without
         * automatically freeing itself.
         */
        current_image = image_get ( image );

        /* Check that this image can be executed */
        if ( ! ( image->type && image->type->exec ) ) {
                rc = -ENOEXEC;
                goto err;
        }

        /* 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 );
                rc = -EACCES_UNTRUSTED;
                goto err;
        }

        /* Record boot attempt */
        syslog ( LOG_NOTICE, "Executing \"%s\"\n", image->name );

        /* Try executing the image */
        if ( ( rc = image->type->exec ( image ) ) != 0 ) {
                DBGC ( image, "IMAGE %s could not execute: %s\n",
                       image->name, strerror ( rc ) );
                /* Do not return yet; we still have clean-up to do */
        }

        /* Record result of boot attempt */
        if ( rc == 0 ) {
                syslog ( LOG_NOTICE, "Execution of \"%s\" completed\n",
                         image->name );
        } else {
                syslog ( LOG_ERR, "Execution of \"%s\" failed: %s\n",
                         image->name, strerror ( rc ) );
        }

        /* Pick up replacement image before we drop the original
         * image's temporary reference.  The replacement image must
         * already be registered, so we don't need to hold a temporary
         * reference (which would complicate the tail-recursion).
         */
        replacement = image->replacement;
        if ( replacement )
                assert ( replacement->flags & IMAGE_REGISTERED );

 err:
        /* Unregister image if applicable */
        if ( image->flags & IMAGE_AUTO_UNREGISTER )
                unregister_image ( image );

        /* Debug message for tail-recursion.  Placed here because the
         * image_put() may end up freeing the image.
         */
        if ( replacement ) {
                DBGC ( image, "IMAGE %s replacing self with IMAGE %s\n",
                       image->name, replacement->name );
        }

        /* Drop temporary reference to the original image */
        image_put ( image );

        /* Restore previous currently-running image */
        current_image = saved_current_image;

        /* Reset current working directory */
        churi ( old_cwuri );
        uri_put ( old_cwuri );

        /* Tail-recurse into replacement image, if one exists */
        if ( replacement )
                return image_exec ( replacement );

        return rc;
}
int image_replace ( struct image replacement)

Set replacement image.

Parameters:
replacementReplacement image
Return values:
rcReturn status code

The replacement image must already be registered, and must remain registered until the currently-executing image returns.

Definition at line 393 of file image.c.

References assert, current_image, DBGC, ENOEXEC, ENOTTY, image_type::exec, image::flags, image_get(), image_put(), IMAGE_REGISTERED, image::name, rc, image::replacement, strerror(), and image::type.

Referenced by comboot_fetch_kernel(), and imgexec().

                                                {
        struct image *image = current_image;
        int rc;

        /* Sanity check */
        assert ( replacement->flags & IMAGE_REGISTERED );

        /* Fail unless there is a currently-executing image */
        if ( ! image ) {
                rc = -ENOTTY;
                DBGC ( replacement, "IMAGE %s cannot replace non-existent "
                       "image: %s\n", replacement->name, strerror ( rc ) );
                return rc;
        }

        /* Check that the replacement image can be executed */
        if ( ! ( replacement->type && replacement->type->exec ) )
                return -ENOEXEC;

        /* Clear any existing replacement */
        image_put ( image->replacement );

        /* Set replacement */
        image->replacement = image_get ( replacement );
        DBGC ( image, "IMAGE %s will replace self with IMAGE %s\n",
               image->name, replacement->name );

        return 0;
}
int image_select ( struct image image)

Select image for execution.

Parameters:
imageExecutable image
Return values:
rcReturn status code

Definition at line 429 of file image.c.

References ENOEXEC, image_type::exec, image::flags, for_each_image, IMAGE_SELECTED, and image::type.

Referenced by embedded_init(), and imgselect().

                                         {
        struct image *tmp;

        /* Unselect all other images */
        for_each_image ( tmp )
                tmp->flags &= ~IMAGE_SELECTED;

        /* Check that this image can be executed */
        if ( ! ( image->type && image->type->exec ) )
                return -ENOEXEC;

        /* Mark image as selected */
        image->flags |= IMAGE_SELECTED;

        return 0;
}
struct image* image_find_selected ( void  ) [read]

Find selected image.

Return values:
imageExecutable image, or NULL

Definition at line 451 of file image.c.

References image::flags, for_each_image, IMAGE_SELECTED, and NULL.

Referenced by imgsingle_exec(), and register_image().

                                            {
        struct image *image;

        for_each_image ( image ) {
                if ( image->flags & IMAGE_SELECTED )
                        return image;
        }
        return NULL;
}
int image_set_trust ( int  require_trusted,
int  permanent 
)

Change image trust requirement.

Parameters:
require_trustedRequire trusted images
permanentMake trust requirement permanent
Return values:
rcReturn status code

Definition at line 468 of file image.c.

References EACCES_PERMANENT, require_trusted_images, and require_trusted_images_permanent.

Referenced by imgtrust_exec().

                                                           {

        /* 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;
}

Variable Documentation

List of registered images.

Definition at line 56 of file image.c.

Referenced by efi_file_find(), first_image(), have_images(), initrd_dump(), initrd_reshuffle(), initrd_squash_high(), and initrd_swap().

Currently-executing image.

Definition at line 59 of file image.c.

Referenced by goto_exec(), image_exec(), and image_replace().

int require_trusted_images = 0 [static]

Current image trust requirement.

Definition at line 62 of file image.c.

Referenced by image_exec(), and image_set_trust().

Prevent changes to image trust requirement.

Definition at line 65 of file image.c.

Referenced by image_set_trust().