summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1995-10-18 07:12:50 +0000
committerRoland McGrath <roland@gnu.org>1995-10-18 07:12:50 +0000
commitd038e00bebd1595c948f7f50b9fa76e5568ee582 (patch)
tree26f296f22b1f86c0191f96c28ecba7ea71c06fb0
parent3586b70f8807213f21db6f6c7bb42bab5ee32585 (diff)
(struct execdata): Moved to priv.h.
(std_*, finish): Make global. (do_exec): Only reset CWDIR when null, even if secure. Actually call check_hashbang and return success if it does. Use new hurd_file_name_lookup protocol with private callbacks to open interpreter file on behalf of client. Remove `bootout' label; use `stdout' or `out' as appropriate instead. At `out' label always deref BOOT, which cleans it up iff necessary. (S_exec_exec): #if 0 out $EXECSERVERS processing for time being.
-rw-r--r--exec/exec.c212
1 files changed, 97 insertions, 115 deletions
diff --git a/exec/exec.c b/exec/exec.c
index 35c130df..c8c04249 100644
--- a/exec/exec.c
+++ b/exec/exec.c
@@ -32,73 +32,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "priv.h"
#include <hurd.h>
#include <hurd/exec.h>
-#include <hurd/fsys.h>
#include <hurd/shared.h>
-#include <hurd/ports.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <rwlock.h>
-
-
-/* Data shared between check, check_section,
- load, load_section, and finish. */
-struct execdata
- {
- /* Passed out to caller. */
- error_t error;
-
- /* Set by check. */
- vm_address_t entry;
- FILE stream;
- file_t file;
-
-#ifdef BFD
- bfd *bfd;
-#endif
- union /* Interpreter section giving name of file. */
- {
- asection *section;
- const Elf32_Phdr *phdr;
- } interp;
- memory_object_t filemap, cntlmap;
- struct shared_io *cntl;
- char *file_data; /* File data if already copied in core. */
- off_t file_size;
- size_t optimal_block; /* Optimal size for io_read from file. */
-
- /* Set by caller of load. */
- task_t task;
-
- union
- {
- /* Vector indexed by section index,
- information passed from check_section to load_section.
- Set by caller of check_section and load. */
- vm_offset_t *bfd_locations;
- struct
- {
- /* Program header table read from the executable.
- After `check' this is a pointer into the mapping window.
- By `load' it is local alloca'd storage. */
- Elf32_Phdr *phdr;
- Elf32_Word phnum; /* Number of program header table elements. */
- int anywhere; /* Nonzero if image can go anywhere. */
- vm_address_t loadbase; /* Actual mapping location. */
- } elf;
- } info;
- };
-
mach_port_t procserver; /* Our proc port. */
/* Standard exec data for secure execs. */
-static mach_port_t *std_ports;
-static int *std_ints;
-static size_t std_nports, std_nints;
-static struct rwlock std_lock = RWLOCK_INITIALIZER;
+mach_port_t *std_ports;
+int *std_ints;
+size_t std_nports, std_nints;
+struct rwlock std_lock = RWLOCK_INITIALIZER;
#ifdef BFD
@@ -845,7 +789,7 @@ finish_mapping (struct execdata *e)
}
/* Clean up after reading the file (need not be completed). */
-static void
+void
finish (struct execdata *e, int dealloc_file)
{
finish_mapping (e);
@@ -1112,7 +1056,12 @@ do_exec (file_t file,
if (e->error == ENOEXEC)
{
/* See if it is a compressed image. */
+ static struct mutex lock = MUTEX_INITIALIZER;
+ /* The gzip code is really cheesy, not even close to thread-safe.
+ So we serialize all uses of it. */
+ mutex_lock (&lock);
check_gzip (e);
+ mutex_unlock (&lock);
if (e->error == 0)
/* The file was uncompressed into memory, and now E describes the
uncompressed image rather than the actual file. Check it again
@@ -1120,20 +1069,6 @@ do_exec (file_t file,
check (e);
}
#endif
-
-#if 0
- if (e->error == ENOEXEC)
- /* Check for a #! executable file. */
- check_hashbang (e, replyport,
- file, oldtask, flags,
- argv, argvlen, argv_copy,
- envp, envplen, envp_copy,
- dtable, dtablesize, dtable_copy,
- portarray, nports, portarray_copy,
- intarray, nints, intarray_copy,
- deallocnames, ndeallocnames,
- destroynames, ndestroynames);
-#endif
}
@@ -1154,22 +1089,41 @@ do_exec (file_t file,
/* Prime E for executing FILE and check its validity. */
prepare_and_check (file, &e);
- if (! e.error)
+
+ if (e.error == ENOEXEC)
{
+ /* Check for a #! executable file. */
+ check_hashbang (&e,
+ file, oldtask, flags,
+ argv, argvlen, argv_copy,
+ envp, envplen, envp_copy,
+ dtable, dtablesize, dtable_copy,
+ portarray, nports, portarray_copy,
+ intarray, nints, intarray_copy,
+ deallocnames, ndeallocnames,
+ destroynames, ndestroynames);
+ if (! e.error)
+ /* The #! exec succeeded; nothing more to do. */
+ return 0;
+ }
+
+ if (e.error)
+ /* The file is not a valid executable. */
+ goto out;
+
#ifdef BFD
- if (e.bfd)
- {
- e.info.bfd_locations = alloca (e.bfd->section_count *
- sizeof (vm_offset_t));
- bfd_map_over_sections (e.bfd, check_section, &e);
- }
- else
+ if (e.bfd)
+ {
+ e.info.bfd_locations = alloca (e.bfd->section_count *
+ sizeof (vm_offset_t));
+ bfd_map_over_sections (e.bfd, check_section, &e);
+ }
+ else
#endif
- {
- const Elf32_Phdr *phdr = e.info.elf.phdr;
- e.info.elf.phdr = alloca (e.info.elf.phnum * sizeof (Elf32_Phdr));
- check_elf_phdr (&e, phdr, &phdr_addr, &phdr_size);
- }
+ {
+ const Elf32_Phdr *phdr = e.info.elf.phdr;
+ e.info.elf.phdr = alloca (e.info.elf.phnum * sizeof (Elf32_Phdr));
+ check_elf_phdr (&e, phdr, &phdr_addr, &phdr_size);
}
interp.file = MACH_PORT_NULL;
@@ -1202,7 +1156,8 @@ do_exec (file_t file,
If CONSUME is nonzero, a reference on NEW is consumed;
it is invalid to give nonzero values to both REAUTH and CONSUME. */
#define use(idx, new, reauth, consume) \
- do { use1 (idx, new, reauth, consume); if (e.error) goto bootout; } while (0)
+ do { use1 (idx, new, reauth, consume); \
+ if (e.error) goto stdout; } while (0)
void use1 (unsigned int idx, mach_port_t new,
int reauth, int consume)
{
@@ -1258,22 +1213,18 @@ do_exec (file_t file,
e.error = servercopy ((void **) &argv, argvlen, argv_copy);
if (e.error)
- {
- bootout:
- ports_port_deref (boot);
- goto stdout;
- }
+ goto stdout;
boot->argv = argv;
boot->argvlen = argvlen;
e.error = servercopy ((void **) &envp, envplen, envp_copy);
if (e.error)
- goto bootout;
+ goto stdout;
boot->envp = envp;
boot->envplen = envplen;
e.error = servercopy ((void **) &dtable, dtablesize * sizeof (mach_port_t),
dtable_copy);
if (e.error)
- goto bootout;
+ goto stdout;
boot->dtable = dtable;
boot->dtablesize = dtablesize;
@@ -1297,7 +1248,7 @@ do_exec (file_t file,
e.error = servercopy ((void **) &intarray, nints * sizeof (int),
intarray_copy);
if (e.error)
- goto bootout;
+ goto stdout;
boot->intarray = intarray;
boot->nints = nints;
}
@@ -1346,7 +1297,7 @@ do_exec (file_t file,
mach_port_t new;
e.error = proc_task2proc (procserver, newtask, &new);
if (e.error)
- goto bootout;
+ goto stdout;
use (INIT_PORT_PROC, new, 0, 1);
@@ -1361,14 +1312,14 @@ do_exec (file_t file,
e.error = proc_task2proc (boot->portarray[INIT_PORT_PROC],
newtask, &new);
if (e.error)
- goto bootout;
+ goto stdout;
use (INIT_PORT_PROC, new, 0, 1);
}
if (secure || (defaults
&& boot->portarray[INIT_PORT_CRDIR] == MACH_PORT_NULL))
use (INIT_PORT_CRDIR, std_ports[INIT_PORT_CRDIR], 1, 0);
- if (secure || (defaults
- && boot->portarray[INIT_PORT_CWDIR] == MACH_PORT_NULL))
+ if ((secure || defaults)
+ && boot->portarray[INIT_PORT_CWDIR] == MACH_PORT_NULL)
use (INIT_PORT_CWDIR, std_ports[INIT_PORT_CWDIR], 1, 0);
}
rwlock_reader_unlock (&std_lock);
@@ -1415,11 +1366,28 @@ do_exec (file_t file,
if (! name)
e.interp.section = NULL;
else
- /* Open the named file using the appropriate directory ports for
- the user. */
- e.error = hurd_file_name_lookup (boot->portarray[INIT_PORT_CRDIR],
- boot->portarray[INIT_PORT_CWDIR],
- name, O_READ, 0, &interp.file);
+ {
+ /* Open the named file using the appropriate directory ports for
+ the user. */
+ error_t user_port (int which, error_t (*operate) (mach_port_t))
+ {
+ return (*operate) (boot->nports > which ?
+ boot->portarray[which] :
+ MACH_PORT_NULL);
+ }
+ file_t user_fd (int fd)
+ {
+ if (fd < 0 || fd >= boot->dtablesize ||
+ boot->dtable[fd] == MACH_PORT_NULL)
+ {
+ errno = EBADF;
+ return MACH_PORT_NULL;
+ }
+ return boot->dtable[fd];
+ }
+ e.error = hurd_file_name_lookup (&user_port, &user_fd,
+ name, O_READ, 0, &interp.file);
+ }
}
if (interp.file != MACH_PORT_NULL)
@@ -1448,7 +1416,7 @@ do_exec (file_t file,
}
if (e.error)
- goto bootout;
+ goto out;
/* We are now committed to the exec. It "should not fail".
@@ -1463,7 +1431,7 @@ do_exec (file_t file,
e.error = task_threads (oldtask, &threads, &nthreads);
if (e.error)
- goto bootout;
+ goto out;
for (i = 0; i < nthreads; ++i)
{
thread_terminate (threads[i]);
@@ -1497,7 +1465,7 @@ do_exec (file_t file,
if (interp.error)
{
e.error = interp.error;
- goto bootout;
+ goto out;
}
finish (&interp, 1);
}
@@ -1506,7 +1474,7 @@ do_exec (file_t file,
/* Load the file into the task. */
load (newtask, &e);
if (e.error)
- goto bootout;
+ goto out;
/* XXX loading of interp belongs here */
@@ -1516,7 +1484,7 @@ do_exec (file_t file,
/* Create the initial thread. */
e.error = thread_create (newtask, &thread);
if (e.error)
- goto bootout;
+ goto out;
/* Start up the initial thread at the entry point. */
boot->stack_base = 0, boot->stack_size = 0; /* Don't care about values. */
@@ -1525,7 +1493,7 @@ do_exec (file_t file,
e.entry),
&boot->stack_base, &boot->stack_size);
if (e.error)
- goto bootout;
+ goto out;
if (oldtask != newtask && oldtask != MACH_PORT_NULL)
{
@@ -1561,9 +1529,6 @@ do_exec (file_t file,
MACH_MSG_TYPE_MAKE_SEND);
e.error = task_set_bootstrap_port (newtask, btport);
mach_port_deallocate (mach_task_self (), btport);
- /* Release the original reference. Now there is only one
- reference, which will be released on no-senders notification. */
- ports_port_deref (boot);
}
out:
@@ -1571,6 +1536,21 @@ do_exec (file_t file,
finish (&interp, 1);
finish (&e, !e.error);
+ if (boot)
+ {
+ /* Release the original reference. Now there is only one
+ reference, which will be released on no-senders notification.
+ If we are bailing out due to error before setting the task's
+ bootstrap port, this will be the last reference and BOOT
+ will get cleaned up here. */
+ if (e.error)
+ /* Kill the pointers to the argument information so the cleanup
+ of BOOT doesn't deallocate it. It will be deallocated my MiG
+ when we return the error. */
+ bzero (&boot->pi + 1, (char *) &boot[1] - (char *) (&boot->pi + 1));
+ ports_port_deref (boot);
+ }
+
if (thread != MACH_PORT_NULL)
{
thread_resume (thread);
@@ -1646,6 +1626,7 @@ S_exec_exec (struct trivfs_protid *protid,
if (! protid)
return EOPNOTSUPP;
+#if 0
if (!(flags & EXEC_SECURE))
{
const char envar[] = "\0EXECSERVERS=";
@@ -1711,6 +1692,7 @@ S_exec_exec (struct trivfs_protid *protid,
return ENOEXEC;
}
}
+#endif
/* There were no user-specified exec servers,
or none of them could be found. */