]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[PXEXT] Add PXENV_FILE_EXEC call to PXE extensions API.
authorMichael Brown <mcb30@etherboot.org>
Tue, 4 Mar 2008 18:16:30 +0000 (18:16 +0000)
committerMichael Brown <mcb30@etherboot.org>
Tue, 4 Mar 2008 18:16:30 +0000 (18:16 +0000)
This allows pxelinux to execute arbitrary gPXE commands.  This is
remarkably unsafe (not least because some of the commands will assume
full ownership of memory and do nasty things like edit the e820 map
underneath the calling pxelinux), but it does allow access to the
"sanboot" command.

src/arch/i386/interface/pxe/pxe_call.c
src/include/pxe.h
src/include/pxe_api.h
src/interface/pxe/pxe_file.c

index 8f1dd0a22f2629c66a8abf9aec4b34186357588d..b9c21ce556da6d29ca09c19603951c125f6a1aff 100644 (file)
@@ -96,6 +96,7 @@ union pxenv_call {
        PXENV_EXIT_t ( * file_select ) ( struct s_PXENV_FILE_SELECT * );
        PXENV_EXIT_t ( * file_read ) ( struct s_PXENV_FILE_READ * );
        PXENV_EXIT_t ( * get_file_size ) ( struct s_PXENV_GET_FILE_SIZE * );
+       PXENV_EXIT_t ( * file_exec ) ( struct s_PXENV_FILE_EXEC * );
 };
 
 /**
@@ -294,6 +295,10 @@ __cdecl void pxe_api_call ( struct i386_all_regs *ix86 ) {
                pxenv_call.get_file_size = pxenv_get_file_size;
                param_len = sizeof ( pxenv_any.get_file_size );
                break;
+       case PXENV_FILE_EXEC:
+               pxenv_call.file_exec = pxenv_file_exec;
+               param_len = sizeof ( pxenv_any.file_exec );
+               break;
        default:
                DBG ( "PXENV_UNKNOWN_%hx", opcode );
                pxenv_call.unknown = pxenv_unknown;
index f17d8f770747643793e8b8db03467f04d04e1dab..8b3ca14c4c7ab384401e0a01ddf3311d0101f3cd 100644 (file)
@@ -63,6 +63,7 @@ union u_PXENV_ANY {
        struct s_PXENV_FILE_SELECT              file_select;
        struct s_PXENV_FILE_READ                file_read;
        struct s_PXENV_GET_FILE_SIZE            get_file_size;
+       struct s_PXENV_FILE_EXEC                file_exec;
 };
 
 typedef union u_PXENV_ANY PXENV_ANY_t;
index 8dc1607a8fd5d29e0ad73d7153074a6f031d1a9c..53708ed4f587de012c99123e98e3761f05ea3b91 100644 (file)
@@ -1684,6 +1684,28 @@ extern PXENV_EXIT_t pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE
 
 /** @} */ /* pxenv_get_file_size */
 
+/** @defgroup pxenv_file_exec PXENV_FILE_EXEC
+ *
+ * FILE EXEC
+ *
+ * @{
+ */
+
+/** PXE API function code for pxenv_file_exec() */
+#define PXENV_FILE_EXEC                        0x00e5
+
+/** Parameter block for pxenv_file_exec() */
+struct s_PXENV_FILE_EXEC {
+       PXENV_STATUS_t Status;          /**< PXE status code */
+       SEGOFF16_t Command;             /**< Command to execute */
+} PACKED;
+
+typedef struct s_PXENV_FILE_EXEC PXENV_FILE_EXEC_t;
+
+extern PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec );
+
+/** @} */ /* pxenv_file_exec */
+
 /** @} */ /* pxe_file_api */
 
 /** @defgroup pxe_loader_api PXE Loader API
index 01dac8f7d62795546501c3c87dc363df33008196..718f5e38ead8224017d6c32b2b5a34aea8a4dc64 100644 (file)
@@ -31,7 +31,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-FEATURE ( FEATURE_MISC, "PXEXT", DHCP_EB_FEATURE_PXE_EXT, 1 );
+FEATURE ( FEATURE_MISC, "PXEXT", DHCP_EB_FEATURE_PXE_EXT, 2 );
 
 /**
  * FILE OPEN
@@ -189,3 +189,41 @@ PXENV_EXIT_t pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE
        get_file_size->Status = PXENV_STATUS_SUCCESS;
        return PXENV_EXIT_SUCCESS;
 }
+
+/**
+ * FILE EXEC
+ *
+ * @v file_exec                                Pointer to a struct s_PXENV_FILE_EXEC
+ * @v s_PXENV_FILE_EXEC::Command       Command to execute
+ * @ret #PXENV_EXIT_SUCCESS            Command was executed successfully
+ * @ret #PXENV_EXIT_FAILURE            Command was not executed successfully
+ * @ret s_PXENV_FILE_EXEC::Status      PXE status code
+ *
+ */
+PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ) {
+       userptr_t command;
+       size_t command_len;
+       int rc;
+
+       DBG ( "PXENV_FILE_EXEC" );
+
+       /* Copy name from external program, and exec it */
+       command = real_to_user ( file_exec->Command.segment,
+                                file_exec->Command.offset );
+       command_len = strlen_user ( command, 0 );
+       {
+               char command_string[ command_len + 1 ];
+
+               copy_from_user ( command_string, command, 0,
+                                sizeof ( command_string ) );
+               DBG ( " %s", command_string );
+
+               if ( ( rc = system ( command_string ) ) != 0 ) {
+                       file_exec->Status = PXENV_STATUS ( rc );
+                       return PXENV_EXIT_FAILURE;
+               }
+       }
+
+       file_exec->Status = PXENV_STATUS_SUCCESS;
+       return PXENV_EXIT_SUCCESS;
+}