iPXE
image.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 #include <stddef.h>
00027 #include <string.h>
00028 #include <stdlib.h>
00029 #include <stdio.h>
00030 #include <errno.h>
00031 #include <assert.h>
00032 #include <libgen.h>
00033 #include <syslog.h>
00034 #include <ipxe/list.h>
00035 #include <ipxe/umalloc.h>
00036 #include <ipxe/uri.h>
00037 #include <ipxe/image.h>
00038 
00039 /** @file
00040  *
00041  * Executable images
00042  *
00043  */
00044 
00045 /* Disambiguate the various error causes */
00046 #define EACCES_UNTRUSTED \
00047         __einfo_error ( EINFO_EACCES_UNTRUSTED )
00048 #define EINFO_EACCES_UNTRUSTED \
00049         __einfo_uniqify ( EINFO_EACCES, 0x01, "Untrusted image" )
00050 #define EACCES_PERMANENT \
00051         __einfo_error ( EINFO_EACCES_PERMANENT )
00052 #define EINFO_EACCES_PERMANENT \
00053         __einfo_uniqify ( EINFO_EACCES, 0x02, "Trust requirement is permanent" )
00054 
00055 /** List of registered images */
00056 struct list_head images = LIST_HEAD_INIT ( images );
00057 
00058 /** Currently-executing image */
00059 struct image *current_image;
00060 
00061 /** Current image trust requirement */
00062 static int require_trusted_images = 0;
00063 
00064 /** Prevent changes to image trust requirement */
00065 static int require_trusted_images_permanent = 0;
00066 
00067 /**
00068  * Free executable image
00069  *
00070  * @v refcnt            Reference counter
00071  */
00072 static void free_image ( struct refcnt *refcnt ) {
00073         struct image *image = container_of ( refcnt, struct image, refcnt );
00074 
00075         DBGC ( image, "IMAGE %s freed\n", image->name );
00076         free ( image->name );
00077         free ( image->cmdline );
00078         uri_put ( image->uri );
00079         ufree ( image->data );
00080         image_put ( image->replacement );
00081         free ( image );
00082 }
00083 
00084 /**
00085  * Allocate executable image
00086  *
00087  * @v uri               URI, or NULL
00088  * @ret image           Executable image
00089  */
00090 struct image * alloc_image ( struct uri *uri ) {
00091         struct image *image;
00092         int rc;
00093 
00094         /* Allocate image */
00095         image = zalloc ( sizeof ( *image ) );
00096         if ( ! image )
00097                 goto err_alloc;
00098 
00099         /* Initialise image */
00100         ref_init ( &image->refcnt, free_image );
00101         if ( uri && ( ( rc = image_set_uri ( image, uri ) ) != 0 ) )
00102                 goto err_set_uri;
00103 
00104         return image;
00105 
00106  err_set_uri:
00107         image_put ( image );
00108  err_alloc:
00109         return NULL;
00110 }
00111 
00112 /**
00113  * Set image URI
00114  *
00115  * @v image             Image
00116  * @v uri               New image URI
00117  * @ret rc              Return status code
00118  */
00119 int image_set_uri ( struct image *image, struct uri *uri ) {
00120         const char *name;
00121         int rc;
00122 
00123         /* Set name, if image does not already have one */
00124         if ( uri->path && ( ! ( image->name && image->name[0] ) ) ) {
00125                 name = basename ( ( char * ) uri->path );
00126                 if ( ( rc = image_set_name ( image, name ) ) != 0 )
00127                         return rc;
00128         }
00129 
00130         /* Update image URI */
00131         uri_put ( image->uri );
00132         image->uri = uri_get ( uri );
00133 
00134         return 0;
00135 }
00136 
00137 /**
00138  * Set image name
00139  *
00140  * @v image             Image
00141  * @v name              New image name
00142  * @ret rc              Return status code
00143  */
00144 int image_set_name ( struct image *image, const char *name ) {
00145         char *name_copy;
00146 
00147         /* Duplicate name */
00148         name_copy = strdup ( name );
00149         if ( ! name_copy )
00150                 return -ENOMEM;
00151 
00152         /* Replace existing name */
00153         free ( image->name );
00154         image->name = name_copy;
00155 
00156         return 0;
00157 }
00158 
00159 /**
00160  * Set image command line
00161  *
00162  * @v image             Image
00163  * @v cmdline           New image command line, or NULL
00164  * @ret rc              Return status code
00165  */
00166 int image_set_cmdline ( struct image *image, const char *cmdline ) {
00167 
00168         free ( image->cmdline );
00169         image->cmdline = NULL;
00170         if ( cmdline ) {
00171                 image->cmdline = strdup ( cmdline );
00172                 if ( ! image->cmdline )
00173                         return -ENOMEM;
00174         }
00175         return 0;
00176 }
00177 
00178 /**
00179  * Determine image type
00180  *
00181  * @v image             Executable image
00182  * @ret rc              Return status code
00183  */
00184 static int image_probe ( struct image *image ) {
00185         struct image_type *type;
00186         int rc;
00187 
00188         /* Try each type in turn */
00189         for_each_table_entry ( type, IMAGE_TYPES ) {
00190                 if ( ( rc = type->probe ( image ) ) == 0 ) {
00191                         image->type = type;
00192                         DBGC ( image, "IMAGE %s is %s\n",
00193                                image->name, type->name );
00194                         return 0;
00195                 }
00196                 DBGC ( image, "IMAGE %s is not %s: %s\n", image->name,
00197                        type->name, strerror ( rc ) );
00198         }
00199 
00200         DBGC ( image, "IMAGE %s format not recognised\n", image->name );
00201         return -ENOTSUP;
00202 }
00203 
00204 /**
00205  * Register executable image
00206  *
00207  * @v image             Executable image
00208  * @ret rc              Return status code
00209  */
00210 int register_image ( struct image *image ) {
00211         static unsigned int imgindex = 0;
00212         char name[8]; /* "imgXXXX" */
00213         int rc;
00214 
00215         /* Create image name if it doesn't already have one */
00216         if ( ! image->name ) {
00217                 snprintf ( name, sizeof ( name ), "img%d", imgindex++ );
00218                 if ( ( rc = image_set_name ( image, name ) ) != 0 )
00219                         return rc;
00220         }
00221 
00222         /* Avoid ending up with multiple "selected" images on
00223          * re-registration
00224          */
00225         if ( image_find_selected() )
00226                 image->flags &= ~IMAGE_SELECTED;
00227 
00228         /* Add to image list */
00229         image_get ( image );
00230         image->flags |= IMAGE_REGISTERED;
00231         list_add_tail ( &image->list, &images );
00232         DBGC ( image, "IMAGE %s at [%lx,%lx) registered\n",
00233                image->name, user_to_phys ( image->data, 0 ),
00234                user_to_phys ( image->data, image->len ) );
00235 
00236         /* Try to detect image type, if applicable.  Ignore failures,
00237          * since we expect to handle some unrecognised images
00238          * (e.g. kernel initrds, multiboot modules, random files
00239          * provided via our EFI virtual filesystem, etc).
00240          */
00241         if ( ! image->type )
00242                 image_probe ( image );
00243 
00244         return 0;
00245 }
00246 
00247 /**
00248  * Unregister executable image
00249  *
00250  * @v image             Executable image
00251  */
00252 void unregister_image ( struct image *image ) {
00253 
00254         /* Do nothing unless image is registered */
00255         if ( ! ( image->flags & IMAGE_REGISTERED ) )
00256                 return;
00257 
00258         DBGC ( image, "IMAGE %s unregistered\n", image->name );
00259         list_del ( &image->list );
00260         image->flags &= ~IMAGE_REGISTERED;
00261         image_put ( image );
00262 }
00263 
00264 /**
00265  * Find image by name
00266  *
00267  * @v name              Image name
00268  * @ret image           Executable image, or NULL
00269  */
00270 struct image * find_image ( const char *name ) {
00271         struct image *image;
00272 
00273         list_for_each_entry ( image, &images, list ) {
00274                 if ( strcmp ( image->name, name ) == 0 )
00275                         return image;
00276         }
00277 
00278         return NULL;
00279 }
00280 
00281 /**
00282  * Execute image
00283  *
00284  * @v image             Executable image
00285  * @ret rc              Return status code
00286  *
00287  * The image must already be registered.  Note that executing an image
00288  * may cause it to unregister itself.  The caller must therefore
00289  * assume that the image pointer becomes invalid.
00290  */
00291 int image_exec ( struct image *image ) {
00292         struct image *saved_current_image;
00293         struct image *replacement = NULL;
00294         struct uri *old_cwuri;
00295         int rc;
00296 
00297         /* Sanity check */
00298         assert ( image->flags & IMAGE_REGISTERED );
00299 
00300         /* Switch current working directory to be that of the image itself */
00301         old_cwuri = uri_get ( cwuri );
00302         churi ( image->uri );
00303 
00304         /* Preserve record of any currently-running image */
00305         saved_current_image = current_image;
00306 
00307         /* Take out a temporary reference to the image.  This allows
00308          * the image to unregister itself if necessary, without
00309          * automatically freeing itself.
00310          */
00311         current_image = image_get ( image );
00312 
00313         /* Check that this image can be executed */
00314         if ( ! ( image->type && image->type->exec ) ) {
00315                 rc = -ENOEXEC;
00316                 goto err;
00317         }
00318 
00319         /* Check that image is trusted (if applicable) */
00320         if ( require_trusted_images && ! ( image->flags & IMAGE_TRUSTED ) ) {
00321                 DBGC ( image, "IMAGE %s is not trusted\n", image->name );
00322                 rc = -EACCES_UNTRUSTED;
00323                 goto err;
00324         }
00325 
00326         /* Record boot attempt */
00327         syslog ( LOG_NOTICE, "Executing \"%s\"\n", image->name );
00328 
00329         /* Try executing the image */
00330         if ( ( rc = image->type->exec ( image ) ) != 0 ) {
00331                 DBGC ( image, "IMAGE %s could not execute: %s\n",
00332                        image->name, strerror ( rc ) );
00333                 /* Do not return yet; we still have clean-up to do */
00334         }
00335 
00336         /* Record result of boot attempt */
00337         if ( rc == 0 ) {
00338                 syslog ( LOG_NOTICE, "Execution of \"%s\" completed\n",
00339                          image->name );
00340         } else {
00341                 syslog ( LOG_ERR, "Execution of \"%s\" failed: %s\n",
00342                          image->name, strerror ( rc ) );
00343         }
00344 
00345         /* Pick up replacement image before we drop the original
00346          * image's temporary reference.  The replacement image must
00347          * already be registered, so we don't need to hold a temporary
00348          * reference (which would complicate the tail-recursion).
00349          */
00350         replacement = image->replacement;
00351         if ( replacement )
00352                 assert ( replacement->flags & IMAGE_REGISTERED );
00353 
00354  err:
00355         /* Unregister image if applicable */
00356         if ( image->flags & IMAGE_AUTO_UNREGISTER )
00357                 unregister_image ( image );
00358 
00359         /* Debug message for tail-recursion.  Placed here because the
00360          * image_put() may end up freeing the image.
00361          */
00362         if ( replacement ) {
00363                 DBGC ( image, "IMAGE %s replacing self with IMAGE %s\n",
00364                        image->name, replacement->name );
00365         }
00366 
00367         /* Drop temporary reference to the original image */
00368         image_put ( image );
00369 
00370         /* Restore previous currently-running image */
00371         current_image = saved_current_image;
00372 
00373         /* Reset current working directory */
00374         churi ( old_cwuri );
00375         uri_put ( old_cwuri );
00376 
00377         /* Tail-recurse into replacement image, if one exists */
00378         if ( replacement )
00379                 return image_exec ( replacement );
00380 
00381         return rc;
00382 }
00383 
00384 /**
00385  * Set replacement image
00386  *
00387  * @v replacement       Replacement image
00388  * @ret rc              Return status code
00389  *
00390  * The replacement image must already be registered, and must remain
00391  * registered until the currently-executing image returns.
00392  */
00393 int image_replace ( struct image *replacement ) {
00394         struct image *image = current_image;
00395         int rc;
00396 
00397         /* Sanity check */
00398         assert ( replacement->flags & IMAGE_REGISTERED );
00399 
00400         /* Fail unless there is a currently-executing image */
00401         if ( ! image ) {
00402                 rc = -ENOTTY;
00403                 DBGC ( replacement, "IMAGE %s cannot replace non-existent "
00404                        "image: %s\n", replacement->name, strerror ( rc ) );
00405                 return rc;
00406         }
00407 
00408         /* Check that the replacement image can be executed */
00409         if ( ! ( replacement->type && replacement->type->exec ) )
00410                 return -ENOEXEC;
00411 
00412         /* Clear any existing replacement */
00413         image_put ( image->replacement );
00414 
00415         /* Set replacement */
00416         image->replacement = image_get ( replacement );
00417         DBGC ( image, "IMAGE %s will replace self with IMAGE %s\n",
00418                image->name, replacement->name );
00419 
00420         return 0;
00421 }
00422 
00423 /**
00424  * Select image for execution
00425  *
00426  * @v image             Executable image
00427  * @ret rc              Return status code
00428  */
00429 int image_select ( struct image *image ) {
00430         struct image *tmp;
00431 
00432         /* Unselect all other images */
00433         for_each_image ( tmp )
00434                 tmp->flags &= ~IMAGE_SELECTED;
00435 
00436         /* Check that this image can be executed */
00437         if ( ! ( image->type && image->type->exec ) )
00438                 return -ENOEXEC;
00439 
00440         /* Mark image as selected */
00441         image->flags |= IMAGE_SELECTED;
00442 
00443         return 0;
00444 }
00445 
00446 /**
00447  * Find selected image
00448  *
00449  * @ret image           Executable image, or NULL
00450  */
00451 struct image * image_find_selected ( void ) {
00452         struct image *image;
00453 
00454         for_each_image ( image ) {
00455                 if ( image->flags & IMAGE_SELECTED )
00456                         return image;
00457         }
00458         return NULL;
00459 }
00460 
00461 /**
00462  * Change image trust requirement
00463  *
00464  * @v require_trusted   Require trusted images
00465  * @v permanent         Make trust requirement permanent
00466  * @ret rc              Return status code
00467  */
00468 int image_set_trust ( int require_trusted, int permanent ) {
00469 
00470         /* Update trust requirement, if permitted to do so */
00471         if ( ! require_trusted_images_permanent ) {
00472                 require_trusted_images = require_trusted;
00473                 require_trusted_images_permanent = permanent;
00474         }
00475 
00476         /* Fail if we attempted to change the trust requirement but
00477          * were not permitted to do so.
00478          */
00479         if ( require_trusted_images != require_trusted )
00480                 return -EACCES_PERMANENT;
00481 
00482         return 0;
00483 }