Skip to content

Commit

Permalink
[PXEXT] Add PXENV_FILE_EXEC call to PXE extensions API.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Michael Brown committed Mar 4, 2008
1 parent b08a6f5 commit b62f232
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/arch/i386/interface/pxe/pxe_call.c
Expand Up @@ -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 * );
};

/**
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/include/pxe.h
Expand Up @@ -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;
Expand Down
22 changes: 22 additions & 0 deletions src/include/pxe_api.h
Expand Up @@ -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
Expand Down
40 changes: 39 additions & 1 deletion src/interface/pxe/pxe_file.c
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

0 comments on commit b62f232

Please sign in to comment.