summaryrefslogtreecommitdiff
path: root/libdiskfs/file-exec.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1998-12-30 06:50:40 +0000
committerRoland McGrath <roland@gnu.org>1998-12-30 06:50:40 +0000
commit426351562d55a06e490fad6a87cd7d0106280ab6 (patch)
tree68b935f19834e5fd0b2addcb7e00bfa3a4f9e4dc /libdiskfs/file-exec.c
parent05361f6e96c9b7abaca44e16cf38e9f8bc0475e2 (diff)
1998-12-27 Roland McGrath <roland@baalperazim.frob.com>
Use a struct hurd_port for the cached exec server port, so it is properly reference-counted and locked. * boot-start.c (diskfs_exec): Variable removed. (diskfs_start_bootstrap): Make it a local here. Install that port in _diskfs_exec_portcell. (diskfs_S_fsys_init): Use _diskfs_exec_portcell instead of diskfs_exec. * init-init.c (_diskfs_exec_portcell): New variable. (diskfs_init_diskfs): Initialize it. * priv.h: Declare it. * diskfs.h (diskfs_exec, diskfs_exec_ctl): Remove decls. * file-exec.c (diskfs_S_file_exec): Use _diskfs_exec_portcell instead of diskfs_exec.
Diffstat (limited to 'libdiskfs/file-exec.c')
-rw-r--r--libdiskfs/file-exec.c51
1 files changed, 38 insertions, 13 deletions
diff --git a/libdiskfs/file-exec.c b/libdiskfs/file-exec.c
index 2933a7d4..521f3528 100644
--- a/libdiskfs/file-exec.c
+++ b/libdiskfs/file-exec.c
@@ -54,16 +54,31 @@ diskfs_S_file_exec (struct protid *cred,
int suid, sgid;
struct protid *newpi;
error_t err = 0;
+ mach_port_t execserver;
int cached_exec;
+ struct hurd_userlink ulink;
+#define RETURN(code) do { err = (code); goto out; } while (0)
if (!cred)
return EOPNOTSUPP;
- cached_exec = (diskfs_exec != MACH_PORT_NULL);
- if (diskfs_exec == MACH_PORT_NULL)
- diskfs_exec = file_name_lookup (_SERVERS_EXEC, 0, 0); /* XXX unlocked */
- if (diskfs_exec == MACH_PORT_NULL)
- return EOPNOTSUPP;
+ /* Get a light reference to the cached exec server port. */
+ execserver = _hurd_port_get (&_diskfs_exec_portcell, &ulink);
+ cached_exec = (execserver != MACH_PORT_NULL);
+ if (execserver == MACH_PORT_NULL)
+ {
+ /* No cached port. Look up the canonical naming point. */
+ execserver = file_name_lookup (_SERVERS_EXEC, 0, 0);
+ if (execserver == MACH_PORT_NULL)
+ return EOPNOTSUPP; /* No exec server, no exec. */
+ else
+ {
+ /* Install the newly-gotten exec server port for other
+ threads to use, then get a light reference for this call. */
+ _hurd_port_set (&_diskfs_exec_portcell, execserver);
+ execserver = _hurd_port_get (&_diskfs_exec_portcell, &ulink);
+ }
+ }
np = cred->po->np;
@@ -74,17 +89,17 @@ diskfs_S_file_exec (struct protid *cred,
mutex_unlock (&np->lock);
if (_diskfs_noexec)
- return EACCES;
+ RETURN (EACCES);
if ((cred->po->openstat & O_EXEC) == 0)
- return EBADF;
+ RETURN (EBADF);
if (!((mode & (S_IXUSR|S_IXGRP|S_IXOTH))
|| ((mode & S_IUSEUNK) && (mode & (S_IEXEC << S_IUNKSHIFT)))))
- return EACCES;
+ RETURN (EACCES);
if ((mode & S_IFMT) == S_IFDIR)
- return EACCES;
+ RETURN (EACCES);
suid = mode & S_ISUID;
sgid = mode & S_ISGID;
@@ -124,7 +139,7 @@ diskfs_S_file_exec (struct protid *cred,
{
do
{
- err = exec_exec (diskfs_exec,
+ err = exec_exec (execserver,
ports_get_right (newpi),
MACH_MSG_TYPE_MAKE_SEND,
task, flags, argv, argvlen, envp, envplen,
@@ -140,10 +155,17 @@ diskfs_S_file_exec (struct protid *cred,
/* We were using a previously looked-up exec server port.
Try looking up a new one before giving an error. */
cached_exec = 0;
- mach_port_deallocate (mach_task_self (), diskfs_exec);
- diskfs_exec = file_name_lookup (_SERVERS_EXEC, 0, 0);
- if (diskfs_exec == MACH_PORT_NULL)
+ _hurd_port_free (&_diskfs_exec_portcell, &ulink, execserver);
+
+ execserver = file_name_lookup (_SERVERS_EXEC, 0, 0);
+ if (execserver == MACH_PORT_NULL)
err = EOPNOTSUPP;
+ else
+ {
+ _hurd_port_set (&_diskfs_exec_portcell, execserver);
+ execserver = _hurd_port_get (&_diskfs_exec_portcell,
+ &ulink);
+ }
}
else
err = EOPNOTSUPP;
@@ -163,5 +185,8 @@ diskfs_S_file_exec (struct protid *cred,
mach_port_deallocate (mach_task_self (), portarray[i]);
}
+ out:
+ _hurd_port_free (&_diskfs_exec_portcell, &ulink, execserver);
+
return err;
}