From 426351562d55a06e490fad6a87cd7d0106280ab6 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Wed, 30 Dec 1998 06:50:40 +0000 Subject: 1998-12-27 Roland McGrath 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. --- libdiskfs/file-exec.c | 51 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 13 deletions(-) (limited to 'libdiskfs/file-exec.c') 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; } -- cgit v1.2.3