diff options
author | Mihai Moldovan <ionic@ionic.de> | 2017-03-22 00:40:55 +0100 |
---|---|---|
committer | Mihai Moldovan <ionic@ionic.de> | 2017-03-22 00:40:55 +0100 |
commit | f5e7d555ad58368cb550b4516b75a1ac3765fda2 (patch) | |
tree | 000ba384ea14d1c4ba4b8023b37ec57f95c88f58 /nx-X11/programs/Xserver/os | |
parent | b7c389b9a0fa366a40ab272a9429a52ecee7365d (diff) | |
parent | 565421ba18a09d20620e01fc877915a8b09a3735 (diff) | |
download | nx-libs-f5e7d555ad58368cb550b4516b75a1ac3765fda2.tar.gz nx-libs-f5e7d555ad58368cb550b4516b75a1ac3765fda2.tar.bz2 nx-libs-f5e7d555ad58368cb550b4516b75a1ac3765fda2.zip |
Merge branch 'sunweaver-pr/various-os-backports' into 3.6.x
Attributes GH PR #376: https://github.com/ArcticaProject/nx-libs/pull/376
Diffstat (limited to 'nx-X11/programs/Xserver/os')
-rw-r--r-- | nx-X11/programs/Xserver/os/Imakefile | 130 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/os/WaitFor.c | 73 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/os/access.c | 202 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/os/client.c | 397 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/os/connection.c | 397 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/os/io.c | 81 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/os/log.c | 127 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/os/osdep.h | 5 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/os/osinit.c | 5 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/os/utils.c | 192 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/os/xdmcp.c | 10 |
11 files changed, 1139 insertions, 480 deletions
diff --git a/nx-X11/programs/Xserver/os/Imakefile b/nx-X11/programs/Xserver/os/Imakefile index 8b260fa32..7932e32cd 100644 --- a/nx-X11/programs/Xserver/os/Imakefile +++ b/nx-X11/programs/Xserver/os/Imakefile @@ -25,25 +25,31 @@ #include <Server.tmpl> +NULL = + /* * If you have any extra files to be put into the library, define them here. */ +ZONEID_DEFINES = -UHAVE_GETZONEID + #if NXLibraries NX_INCLUDES = -I../../../../nxcomp -NX_DEFINES = -DNX_TRANS_SOCKET \ - -DNX_TRANS_AUTH \ - -DNX_TRANS_FOPEN \ - -DNX_TRANS_SLEEP \ - -DNX_TRANS_EXIT \ - -DNX_TRANS_WAKEUP=1000 +NX_DEFINES = -DNX_TRANS_SOCKET \ + -DNX_TRANS_AUTH \ + -DNX_TRANS_FOPEN \ + -DNX_TRANS_SLEEP \ + -DNX_TRANS_EXIT \ + -DNX_TRANS_WAKEUP=1000 \ + -DNXAGENT_SERVER \ + $(NULL) -# -DNX_TRANS_WARN \ -# -DNX_TRANS_INFO \ -# -DNX_TRANS_TEST \ -# -DNX_TRANS_DEBUG \ +# -DNX_TRANS_WARN \ +# -DNX_TRANS_INFO \ +# -DNX_TRANS_TEST \ +# -DNX_TRANS_DEBUG \ #endif @@ -121,16 +127,53 @@ TMEMCMP_OBJS = timingsafe_memcmp.o #endif BOOTSTRAPCFLAGS = - SRCS = WaitFor.c access.c connection.c io.c $(COLOR_SRCS) \ - osinit.c utils.c log.c auth.c mitauth.c secauth.c \ - $(XDMAUTHSRCS) $(RPCSRCS) xdmcp.c OtherSources \ - xstrans.c $(SNPRINTF_SRCS) $(STRLCAT_SRCS) \ - $(REALLOCARRAY_SRCS) xprintf.c $(TMEMCMP_SRCS) - OBJS = WaitFor.o access.o connection.o io.o $(COLOR_OBJS) \ - osinit.o utils.o log.o auth.o mitauth.o secauth.o \ - $(XDMAUTHOBJS) $(RPCOBJS) xdmcp.o OtherObjects \ - xstrans.o $(SNPRINTF_OBJS) $(STRLCAT_OBJS) \ - $(REALLOCARRAY_OBJS) xprintf.o $(TMEMCMP_OBJS) + SRCS = WaitFor.c \ + access.c \ + client.c \ + connection.c \ + io.c \ + $(COLOR_SRCS) \ + osinit.c \ + utils.c \ + log.c \ + auth.c \ + mitauth.c \ + secauth.c \ + $(XDMAUTHSRCS) \ + $(RPCSRCS) \ + xdmcp.c \ + OtherSources \ + xstrans.c \ + $(SNPRINTF_SRCS) \ + $(STRLCAT_SRCS) \ + $(REALLOCARRAY_SRCS) \ + xprintf.c \ + $(TMEMCMP_SRCS) \ + $(NULL) + + OBJS = WaitFor.o \ + access.o \ + client.o \ + connection.o \ + io.o \ + $(COLOR_OBJS) \ + osinit.o \ + utils.o \ + log.o \ + auth.o \ + mitauth.o \ + secauth.o \ + $(XDMAUTHOBJS) \ + $(RPCOBJS) \ + xdmcp.o \ + OtherObjects \ + xstrans.o \ + $(SNPRINTF_OBJS) \ + $(STRLCAT_OBJS) \ + $(REALLOCARRAY_OBJS) \ + xprintf.o \ + $(TMEMCMP_OBJS) \ + $(NULL) #if UseMemLeak MEM_DEFINES = -DMEMBUG @@ -143,18 +186,39 @@ BOOTSTRAPCFLAGS = #endif XTRANS_DEFINES = -DXTRANS_SEND_FDS=0 - DEFINES = $(CONNECTION_FLAGS) $(MEM_DEFINES) \ - $(XDMAUTHDEFS) $(RPCDEFS) $(SIGNAL_DEFINES) $(OS_DEFINES) \ - $(GETPEER_DEFINES) \ - $(RANDOM_DEFINES) $(BUGMSG) $(XTRANS_FAILDEFINES) \ - $(XTRANS_DEFINES) $(NX_DEFINES) - INCLUDES = -I. -I../include -I$(XINCLUDESRC) -I$(EXTINCSRC) \ - -I$(SERVERSRC)/Xext -I$(SERVERSRC)/render \ - -I$(TOP)/lib/Xau $(NX_INCLUDES) \ - `pkg-config --cflags-only-I pixman-1` - DEPEND_DEFINES = $(XDMCP_DEFINES) $(EXT_DEFINES) \ - $(TRANS_INCLUDES) $(CONNECTION_FLAGS) $(GETPEER_DEFINES) \ - DependDefines + DEFINES = $(CONNECTION_FLAGS) \ + $(MEM_DEFINES) \ + $(XDMAUTHDEFS) \ + $(RPCDEFS) \ + $(SIGNAL_DEFINES) \ + $(OS_DEFINES) \ + $(GETPEER_DEFINES) \ + $(RANDOM_DEFINES) \ + $(BUGMSG) \ + $(XTRANS_FAILDEFINES) \ + $(XTRANS_DEFINES) \ + $(NX_DEFINES) \ + $(NULL) + + INCLUDES = -I. \ + -I../include \ + -I$(XINCLUDESRC) \ + -I$(EXTINCSRC) \ + -I$(SERVERSRC)/Xext \ + -I$(SERVERSRC)/render \ + -I$(TOP)/lib/Xau \ + $(NX_INCLUDES) \ + `pkg-config --cflags-only-I pixman-1` \ + $(NULL) + + DEPEND_DEFINES = $(XDMCP_DEFINES) \ + $(EXT_DEFINES) \ + $(TRANS_INCLUDES) \ + $(CONNECTION_FLAGS) \ + $(GETPEER_DEFINES) \ + DependDefines \ + $(NULL) + LINTLIBS = ../dix/llib-ldix.ln #ifdef NEED_ALLOCA_FROM_LIBPW @@ -176,7 +240,7 @@ alloca.o: $(PWLIB) ar x $(PWLIB) alloca.o #endif /* NEED_ALLOCA_FROM_LIBPW */ -SpecialCObjectRule(access,$(ICONFIGFILES),$(XDMCP_DEFINES) $(SOCK_DEFINES) $(IFADDRS_DEFINES)) +SpecialCObjectRule(access,$(ICONFIGFILES),$(XDMCP_DEFINES) $(SOCK_DEFINES) $(IFADDRS_DEFINES) $(ZONEID_DEFINES)) SpecialCObjectRule(auth,$(ICONFIGFILES),$(XDMCP_DEFINES)) SpecialCObjectRule(xdmauth,$(ICONFIGFILES),$(XDMCP_DEFINES)) SpecialCObjectRule(xdmcp,$(ICONFIGFILES),$(SOCK_DEFINES) $(XDMCP_DEFINES)) diff --git a/nx-X11/programs/Xserver/os/WaitFor.c b/nx-X11/programs/Xserver/os/WaitFor.c index 3ac2e1c7e..76e5da5f2 100644 --- a/nx-X11/programs/Xserver/os/WaitFor.c +++ b/nx-X11/programs/Xserver/os/WaitFor.c @@ -213,18 +213,10 @@ WaitForSomething(int *pClientsReady) ProcessWorkQueue(); if (XFD_ANYSET (&ClientsWithInput)) { - if (!SmartScheduleDisable) - { - someReady = TRUE; - waittime.tv_sec = 0; - waittime.tv_usec = 0; - wt = &waittime; - } - else - { - XFD_COPYSET (&ClientsWithInput, &clientsReadable); - break; - } + someReady = TRUE; + waittime.tv_sec = 0; + waittime.tv_usec = 0; + wt = &waittime; } if (someReady) { @@ -247,7 +239,8 @@ WaitForSomething(int *pClientsReady) } XFD_COPYSET(&AllSockets, &LastSelectMask); } - SmartScheduleIdle = TRUE; + SmartScheduleStopTimer (); + BlockHandler((void *)&wt, (void *)&LastSelectMask); if (NewOutputPending) FlushAllOutput(); @@ -387,13 +380,8 @@ WaitForSomething(int *pClientsReady) i = XTestProcessInputAction (i, &waittime); } #endif /* XTESTEXT1 */ - if (i >= 0) - { - SmartScheduleIdle = FALSE; - SmartScheduleIdleCount = 0; - if (SmartScheduleTimerStopped) - (void) SmartScheduleStartTimer (); - } + SmartScheduleStartTimer (); + if (i <= 0) /* An error or timeout occurred */ { #if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_DEBUG) @@ -507,10 +495,6 @@ WaitForSomething(int *pClientsReady) } XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients); - XFD_ANDSET(&tmp_set, &LastSelectMask, &WellKnownConnections); - if (XFD_ANYSET(&tmp_set)) - QueueWorkProc(EstablishNewConnections, NULL, - (void *)&LastSelectMask); XFD_ANDSET(&tmp_set, &LastSelectMask, &NotifyReadFds); if (XFD_ANYSET(&tmp_set) || someNotifyWriteReady) @@ -544,17 +528,14 @@ WaitForSomething(int *pClientsReady) #ifndef WIN32 for (i=0; i<howmany(XFD_SETSIZE, NFDBITS); i++) { - int highest_priority = 0; - while (clientsReadable.fds_bits[i]) { - int client_priority, client_index; + int client_index; curclient = ffs (clientsReadable.fds_bits[i]) - 1; client_index = /* raphael: modified */ ConnectionTranslation[curclient + (i * (sizeof(fd_mask) * 8))]; #else - int highest_priority = 0; fd_set savedClientsReadable; XFD_COPYSET(&clientsReadable, &savedClientsReadable); for (i = 0; i < XFD_SETCOUNT(&savedClientsReadable); i++) @@ -564,40 +545,10 @@ WaitForSomething(int *pClientsReady) curclient = XFD_FD(&savedClientsReadable, i); client_index = GetConnectionTranslation(curclient); #endif -#ifdef XSYNC - /* We implement "strict" priorities. - * Only the highest priority client is returned to - * dix. If multiple clients at the same priority are - * ready, they are all returned. This means that an - * aggressive client could take over the server. - * This was not considered a big problem because - * aggressive clients can hose the server in so many - * other ways :) - */ - client_priority = clients[client_index]->priority; - if (nready == 0 || client_priority > highest_priority) - { - /* Either we found the first client, or we found - * a client whose priority is greater than all others - * that have been found so far. Either way, we want - * to initialize the list of clients to contain just - * this client. - */ - pClientsReady[0] = client_index; - highest_priority = client_priority; - nready = 1; - } - /* the following if makes sure that multiple same-priority - * clients get batched together - */ - else if (client_priority == highest_priority) -#endif - { - pClientsReady[nready++] = client_index; - } + pClientsReady[nready++] = client_index; #ifndef WIN32 - clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient); - } + clientsReadable.fds_bits[i] &= ~(((fd_mask)1L) << curclient); + } #else FD_CLR(curclient, &clientsReadable); #endif diff --git a/nx-X11/programs/Xserver/os/access.c b/nx-X11/programs/Xserver/os/access.c index d3a18efbe..d8d035ade 100644 --- a/nx-X11/programs/Xserver/os/access.c +++ b/nx-X11/programs/Xserver/os/access.c @@ -204,10 +204,6 @@ static Bool NewHost(int /*family*/, int /*len*/, int /* addingLocalHosts */); -int LocalClientCredAndGroups(ClientPtr client, int *pUid, int *pGid, - int **pSuppGids, int *nSuppGids); - - /* XFree86 bug #156: To keep track of which hosts were explicitly requested in /etc/X<display>.hosts, we've added a requested field to the HOST struct, and a LocalHostRequested variable. These default to FALSE, but are set @@ -496,7 +492,7 @@ DefineSelf (int fd) void DefineSelf (int fd) { -#if !defined(TCPCONN) && !defined(UNIXCONN) && !defined(MNX_TCPCONN) +#if !defined(TCPCONN) && !defined(UNIXCONN) return; #else register int n; @@ -631,7 +627,7 @@ DefineLocalHost: selfhosts = host; } } -#endif /* !TCPCONN && !UNIXCONN && !MNX_TCPCONN */ +#endif /* !TCPCONN && !UNIXCONN */ } #else @@ -893,6 +889,8 @@ DefineSelf (int fd) return; } for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) { + if (!ifr->ifa_addr) + continue; len = sizeof(*(ifr->ifa_addr)); family = ConvertAddr(ifr->ifa_addr, &len, (void **)&addr); if (family == -1 || family == FamilyLocal) @@ -1068,11 +1066,10 @@ ResetHosts (char *display) FILE *fd; char *ptr; int i, hostlen; -#if ((defined(TCPCONN) || defined(MNX_TCPCONN)) && \ - (!defined(IPv6) || !defined(AF_INET6))) +#if (defined(TCPCONN) && (!defined(IPv6) || !defined(AF_INET6))) union { struct sockaddr sa; -#if defined(TCPCONN) || defined(MNX_TCPCONN) +#if defined(TCPCONN) struct sockaddr_in in; #endif /* TCPCONN */ } saddr; @@ -1117,7 +1114,7 @@ ResetHosts (char *display) NewHost(family, "", 0, FALSE); LocalHostRequested = TRUE; /* Fix for XFree86 bug #156 */ } -#if defined(TCPCONN) || defined(MNX_TCPCONN) +#if defined(TCPCONN) else if (!strncmp("inet:", lhostname, 5)) { family = FamilyInternet; @@ -1162,7 +1159,7 @@ ResetHosts (char *display) } else #endif /* SECURE_RPC */ -#if defined(TCPCONN) || defined(MNX_TCPCONN) +#if defined(TCPCONN) { #if defined(IPv6) && defined(AF_INET6) if ( (family == FamilyInternet) || (family == FamilyInternet6) || @@ -1220,12 +1217,17 @@ ResetHosts (char *display) } /* Is client on the local host */ -Bool LocalClient(ClientPtr client) +Bool +ComputeLocalClient(ClientPtr client) { int alen, family, notused; Xtransaddr *from = NULL; void *addr; register HOST *host; + OsCommPtr oc = (OsCommPtr) client->osPrivate; + + if (!oc->trans_conn) + return FALSE; #ifdef XCSECURITY /* untrusted clients can't change host access */ @@ -1236,65 +1238,79 @@ Bool LocalClient(ClientPtr client) return FALSE; } #endif - if (!_XSERVTransGetPeerAddr (((OsCommPtr)client->osPrivate)->trans_conn, - ¬used, &alen, &from)) + if (!_XSERVTransGetPeerAddr (oc->trans_conn, ¬used, &alen, &from)) { family = ConvertAddr ((struct sockaddr *) from, &alen, (void **)&addr); if (family == -1) { - free ((char *) from); + free(from); return FALSE; } if (family == FamilyLocal) { - free ((char *) from); + free(from); return TRUE; } for (host = selfhosts; host; host = host->next) { - if (addrEqual (family, addr, alen, host)) + if (addrEqual (family, addr, alen, host)) { + free(from); return TRUE; + } } - free ((char *) from); + free(from); } return FALSE; } /* * Return the uid and gid of a connected local client - * or the uid/gid for nobody those ids cannot be determined * * Used by XShm to test access rights to shared memory segments */ int LocalClientCred(ClientPtr client, int *pUid, int *pGid) { - return LocalClientCredAndGroups(client, pUid, pGid, NULL, NULL); + LocalClientCredRec *lcc; + int ret = GetLocalClientCreds(client, &lcc); + + if (ret == 0) { +#ifdef HAVE_GETZONEID /* only local if in the same zone */ + if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) { + FreeLocalClientCreds(lcc); + return -1; + } +#endif + if ((lcc->fieldsSet & LCC_UID_SET) && (pUid != NULL)) + *pUid = lcc->euid; + if ((lcc->fieldsSet & LCC_GID_SET) && (pGid != NULL)) + *pGid = lcc->egid; + FreeLocalClientCreds(lcc); + } + return ret; } /* * Return the uid and all gids of a connected local client - * or the uid/gid for nobody those ids cannot be determined + * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds * - * If the caller passes non-NULL values for pSuppGids & nSuppGids, - * they are responsible for calling XFree(*pSuppGids) to release the - * memory allocated for the supplemental group ids list. - * * Used by localuser & localgroup ServerInterpreted access control forms below + * Used by AuthAudit to log where local connections came from */ int -LocalClientCredAndGroups(ClientPtr client, int *pUid, int *pGid, - int **pSuppGids, int *nSuppGids) +GetLocalClientCreds(ClientPtr client, LocalClientCredRec **lccp) { #if defined(HAS_GETPEEREID) || defined(HAS_GETPEERUCRED) || defined(SO_PEERCRED) int fd; XtransConnInfo ci; + LocalClientCredRec *lcc; #ifdef HAS_GETPEEREID uid_t uid; gid_t gid; #elif defined(HAS_GETPEERUCRED) ucred_t *peercred = NULL; + const gid_t *gids; #elif defined(SO_PEERCRED) struct ucred peercred; socklen_t so_len = sizeof(peercred); @@ -1313,57 +1329,64 @@ LocalClientCredAndGroups(ClientPtr client, int *pUid, int *pGid, } #endif - if (pSuppGids != NULL) - *pSuppGids = NULL; - if (nSuppGids != NULL) - *nSuppGids = 0; + *lccp = calloc(1, sizeof(LocalClientCredRec)); + if (*lccp == NULL) + return -1; + lcc = *lccp; fd = _XSERVTransGetConnectionNumber(ci); #ifdef HAS_GETPEEREID - if (getpeereid(fd, &uid, &gid) == -1) - return -1; - if (pUid != NULL) - *pUid = uid; - if (pGid != NULL) - *pGid = gid; + if (getpeereid(fd, &uid, &gid) == -1) { + FreeLocalClientCreds(lcc); + return -1; + } + lcc->euid = uid; + lcc->egid = gid; + lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET; return 0; #elif defined(HAS_GETPEERUCRED) - if (getpeerucred(fd, &peercred) < 0) - return -1; -#ifdef sun /* Ensure process is in the same zone */ - if (getzoneid() != ucred_getzoneid(peercred)) { - ucred_free(peercred); + if (getpeerucred(fd, &peercred) < 0) { + FreeLocalClientCreds(lcc); return -1; - } -#endif - if (pUid != NULL) - *pUid = ucred_geteuid(peercred); - if (pGid != NULL) - *pGid = ucred_getegid(peercred); - if (pSuppGids != NULL && nSuppGids != NULL) { - const gid_t *gids; - *nSuppGids = ucred_getgroups(peercred, &gids); - if (*nSuppGids > 0) { - *pSuppGids = malloc(sizeof(int) * (*nSuppGids)); - if (*pSuppGids == NULL) { - *nSuppGids = 0; - } else { - int i; - for (i = 0 ; i < *nSuppGids; i++) { - (*pSuppGids)[i] = (int) gids[i]; - } + lcc->euid = ucred_geteuid(peercred); + if (lcc->euid != -1) + lcc->fieldsSet |= LCC_UID_SET; + lcc->egid = ucred_getegid(peercred); + if (lcc->egid != -1) + lcc->fieldsSet |= LCC_GID_SET; + lcc->pid = ucred_getpid(peercred); + if (lcc->pid != -1) + lcc->fieldsSet |= LCC_PID_SET; +#ifdef HAVE_GETZONEID + lcc->zoneid = ucred_getzoneid(peercred); + if (lcc->zoneid != -1) + lcc->fieldsSet |= LCC_ZID_SET; +#endif + lcc->nSuppGids = ucred_getgroups(peercred, &gids); + if (lcc->nSuppGids > 0) { + lcc->pSuppGids = calloc((lcc->nSuppGids), sizeof(int)); + if (lcc->pSuppGids == NULL) { + lcc->nSuppGids = 0; + } else { + int i; + for (i = 0 ; i < lcc->nSuppGids; i++) { + (lcc->pSuppGids)[i] = (int) gids[i]; } } + } else { + lcc->nSuppGids = 0; } ucred_free(peercred); return 0; #elif defined(SO_PEERCRED) - if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) - return -1; - if (pUid != NULL) - *pUid = peercred.uid; - if (pGid != NULL) - *pGid = peercred.gid; + if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) { + FreeLocalClientCreds(lcc); + return -1; + } + lcc->euid = peercred.uid; + lcc->egid = peercred.gid; + lcc->pid = peercred.pid; + lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET | LCC_PID_SET; return 0; #endif #else @@ -1373,12 +1396,23 @@ LocalClientCredAndGroups(ClientPtr client, int *pUid, int *pGid, #endif } +void +FreeLocalClientCreds(LocalClientCredRec *lcc) +{ + if (lcc != NULL) { + if (lcc->nSuppGids > 0) { + free(lcc->pSuppGids); + } + free(lcc); + } +} + static Bool AuthorizedClient(ClientPtr client) { if (!client || defeatAccessControl) return TRUE; - return LocalClient(client); + return client->local ? Success : BadAccess; } /* Add a host to the access control list. This is the external interface @@ -1593,7 +1627,7 @@ CheckAddr ( switch (family) { -#if defined(TCPCONN) || defined(MNX_TCPCONN) +#if defined(TCPCONN) case FamilyInternet: if (length == sizeof (struct in_addr)) len = length; @@ -1686,7 +1720,7 @@ ConvertAddr ( case AF_UNIX: #endif return FamilyLocal; -#if defined(TCPCONN) || defined(MNX_TCPCONN) +#if defined(TCPCONN) case AF_INET: #ifdef WIN32 if (16777343 == *(long*)&((struct sockaddr_in *) saddr)->sin_addr) @@ -2176,38 +2210,48 @@ static Bool siLocalCredAddrMatch(int family, void * addr, int len, const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv) { - int connUid, connGid, *connSuppGids, connNumSuppGids, siAddrId; + int siAddrId; + LocalClientCredRec *lcc; siLocalCredPrivPtr lcPriv = (siLocalCredPrivPtr) typePriv; - if (LocalClientCredAndGroups(client, &connUid, &connGid, - &connSuppGids, &connNumSuppGids) == -1) { + if (GetLocalClientCreds(client, &lcc) == -1) { return FALSE; } +#ifdef HAVE_GETZONEID /* Ensure process is in the same zone */ + if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) { + FreeLocalClientCreds(lcc); + return FALSE; + } +#endif + if (siLocalCredGetId(siAddr, siAddrlen, lcPriv, &siAddrId) == FALSE) { + FreeLocalClientCreds(lcc); return FALSE; } if (lcPriv->credType == LOCAL_USER) { - if (connUid == siAddrId) { + if ((lcc->fieldsSet & LCC_UID_SET) && (lcc->euid == siAddrId)) { + FreeLocalClientCreds(lcc); return TRUE; } } else { - if (connGid == siAddrId) { + if ((lcc->fieldsSet & LCC_GID_SET) && (lcc->egid == siAddrId)) { + FreeLocalClientCreds(lcc); return TRUE; } - if (connSuppGids != NULL) { + if (lcc->pSuppGids != NULL) { int i; - for (i = 0 ; i < connNumSuppGids; i++) { - if (connSuppGids[i] == siAddrId) { - free(connSuppGids); + for (i = 0 ; i < lcc->nSuppGids; i++) { + if (lcc->pSuppGids[i] == siAddrId) { + FreeLocalClientCreds(lcc); return TRUE; } } - free(connSuppGids); } } + FreeLocalClientCreds(lcc); return FALSE; } diff --git a/nx-X11/programs/Xserver/os/client.c b/nx-X11/programs/Xserver/os/client.c new file mode 100644 index 000000000..ef5e3935d --- /dev/null +++ b/nx-X11/programs/Xserver/os/client.c @@ -0,0 +1,397 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). All + * rights reserved. + * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @file + * + * This file contains functionality for identifying clients by various + * means. The primary purpose of identification is to simply aid in + * finding out which clients are using X server and how they are using + * it. For example, it's often necessary to monitor what requests + * clients are executing (to spot bad behaviour) and how they are + * allocating resources in X server (to spot excessive resource + * usage). + * + * This framework automatically allocates information, that can be + * used for client identification, when a client connects to the + * server. The information is freed when the client disconnects. The + * allocated information is just a collection of various IDs, such as + * PID and process name for local clients, that are likely to be + * useful in analyzing X server usage. + * + * Users of the framework can query ID information about clients at + * any time. To avoid repeated polling of IDs the users can also + * subscribe for notifications about the availability of ID + * information. IDs have been allocated before ClientStateCallback is + * called with ClientStateInitial state. Similarly the IDs will be + * released after ClientStateCallback is called with ClientStateGone + * state. + * + * Author: Rami Ylimäki <rami.ylimaki@vincit.fi> + */ + +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#include "client.h" +#include "os.h" +#include "dixstruct.h" + +#ifdef __sun +#include <errno.h> +#include <procfs.h> +#endif + +#ifdef __OpenBSD__ +#include <sys/param.h> +#include <sys/sysctl.h> +#include <sys/types.h> + +#include <kvm.h> +#include <limits.h> +#endif + +/** + * Try to determine a PID for a client from its connection + * information. This should be called only once when new client has + * connected, use GetClientPid to determine the PID at other times. + * + * @param[in] client Connection linked to some process. + * + * @return PID of the client. Error (-1) if PID can't be determined + * for the client. + * + * @see GetClientPid + */ +pid_t +DetermineClientPid(struct _Client * client) +{ + LocalClientCredRec *lcc = NULL; + pid_t pid = -1; + + if (client == NullClient) + return pid; + + if (client == serverClient) + return getpid(); + + if (GetLocalClientCreds(client, &lcc) != -1) { + if (lcc->fieldsSet & LCC_PID_SET) + pid = lcc->pid; + FreeLocalClientCreds(lcc); + } + + return pid; +} + +/** + * Try to determine a command line string for a client based on its + * PID. Note that mapping PID to a command hasn't been implemented for + * some operating systems. This should be called only once when a new + * client has connected, use GetClientCmdName/Args to determine the + * string at other times. + * + * @param[in] pid Process ID of a client. + + * @param[out] cmdname Client process name without arguments. You must + * release this by calling free. On error NULL is + * returned. Pass NULL if you aren't interested in + * this value. + * @param[out] cmdargs Arguments to client process. Useful for + * identifying a client that is executed from a + * launcher program. You must release this by + * calling free. On error NULL is returned. Pass + * NULL if you aren't interested in this value. + * + * @see GetClientCmdName/Args + */ +void +DetermineClientCmd(pid_t pid, const char **cmdname, const char **cmdargs) +{ + char path[PATH_MAX + 1]; + int totsize = 0; + int fd = 0; + + if (cmdname) + *cmdname = NULL; + if (cmdargs) + *cmdargs = NULL; + + if (pid == -1) + return; + +#ifdef __sun /* Solaris */ + /* Solaris does not support /proc/pid/cmdline, but makes information + * similar to what ps shows available in a binary structure in the + * /proc/pid/psinfo file. */ + if (snprintf(path, sizeof(path), "/proc/%d/psinfo", pid) < 0) + return; + fd = open(path, O_RDONLY); + if (fd < 0) { + ErrorF("Failed to open %s: %s\n", path, strerror(errno)); + return; + } + else { + psinfo_t psinfo = { 0 }; + char *sp; + + totsize = read(fd, &psinfo, sizeof(psinfo_t)); + close(fd); + if (totsize <= 0) + return; + + /* pr_psargs is the first PRARGSZ (80) characters of the command + * line string - assume up to the first space is the command name, + * since it's not delimited. While there is also pr_fname, that's + * more limited, giving only the first 16 chars of the basename of + * the file that was exec'ed, thus cutting off many long gnome + * command names, or returning "isapython2.6" for all python scripts. + */ + psinfo.pr_psargs[PRARGSZ - 1] = '\0'; + sp = strchr(psinfo.pr_psargs, ' '); + if (sp) + *sp++ = '\0'; + + if (cmdname) + *cmdname = strdup(psinfo.pr_psargs); + + if (cmdargs && sp) + *cmdargs = strdup(sp); + } +#elif defined(__OpenBSD__) + /* on OpenBSD use kvm_getargv() */ + { + kvm_t *kd; + char errbuf[_POSIX2_LINE_MAX]; + char **argv; + struct kinfo_proc *kp; + size_t len = 0; + int i, n; + + kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, errbuf); + if (kd == NULL) + return; + kp = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc), + &n); + if (n != 1) + return; + argv = kvm_getargv(kd, kp, 0); + *cmdname = strdup(argv[0]); + i = 1; + while (argv[i] != NULL) { + len += strlen(argv[i]) + 1; + i++; + } + *cmdargs = calloc(1, len); + i = 1; + while (argv[i] != NULL) { + strlcat(*cmdargs, argv[i], len); + strlcat(*cmdargs, " ", len); + i++; + } + kvm_close(kd); + } +#else /* Linux using /proc/pid/cmdline */ + + /* Check if /proc/pid/cmdline exists. It's not supported on all + * operating systems. */ + if (snprintf(path, sizeof(path), "/proc/%d/cmdline", pid) < 0) + return; + fd = open(path, O_RDONLY); + if (fd < 0) + return; + + /* Read the contents of /proc/pid/cmdline. It should contain the + * process name and arguments. */ + totsize = read(fd, path, sizeof(path)); + close(fd); + if (totsize <= 0) + return; + path[totsize - 1] = '\0'; + + /* Contruct the process name without arguments. */ + if (cmdname) { + *cmdname = strdup(path); + } + + /* Construct the arguments for client process. */ + if (cmdargs) { + int cmdsize = strlen(path) + 1; + int argsize = totsize - cmdsize; + char *args = NULL; + + if (argsize > 0) + args = malloc(argsize); + if (args) { + int i = 0; + + for (i = 0; i < (argsize - 1); ++i) { + const char c = path[cmdsize + i]; + + args[i] = (c == '\0') ? ' ' : c; + } + args[argsize - 1] = '\0'; + *cmdargs = args; + } + } +#endif +} + +/** + * Called when a new client connects. Allocates client ID information. + * + * @param[in] client Recently connected client. + */ +void +ReserveClientIds(struct _Client *client) +{ +#ifdef CLIENTIDS + if (client == NullClient) + return; + + assert(!client->clientIds); + client->clientIds = calloc(1, sizeof(ClientIdRec)); + if (!client->clientIds) + return; + + client->clientIds->pid = DetermineClientPid(client); + if (client->clientIds->pid != -1) + DetermineClientCmd(client->clientIds->pid, &client->clientIds->cmdname, + &client->clientIds->cmdargs); + + DebugF("client(%lx): Reserved pid(%d).\n", + (unsigned long) client->clientAsMask, client->clientIds->pid); + DebugF("client(%lx): Reserved cmdname(%s) and cmdargs(%s).\n", + (unsigned long) client->clientAsMask, + client->clientIds->cmdname ? client->clientIds->cmdname : "NULL", + client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL"); +#endif /* CLIENTIDS */ +} + +/** + * Called when an existing client disconnects. Frees client ID + * information. + * + * @param[in] client Recently disconnected client. + */ +void +ReleaseClientIds(struct _Client *client) +{ +#ifdef CLIENTIDS + if (client == NullClient) + return; + + if (!client->clientIds) + return; + + DebugF("client(%lx): Released pid(%d).\n", + (unsigned long) client->clientAsMask, client->clientIds->pid); + DebugF("client(%lx): Released cmdline(%s) and cmdargs(%s).\n", + (unsigned long) client->clientAsMask, + client->clientIds->cmdname ? client->clientIds->cmdname : "NULL", + client->clientIds->cmdargs ? client->clientIds->cmdargs : "NULL"); + + free((void *) client->clientIds->cmdname); /* const char * */ + free((void *) client->clientIds->cmdargs); /* const char * */ + free(client->clientIds); + client->clientIds = NULL; +#endif /* CLIENTIDS */ +} + +/** + * Get cached PID of a client. + * + * param[in] client Client whose PID has been already cached. + * + * @return Cached client PID. Error (-1) if called: + * - before ClientStateInitial client state notification + * - after ClientStateGone client state notification + * - for remote clients + * + * @see DetermineClientPid + */ +pid_t +GetClientPid(struct _Client *client) +{ + if (client == NullClient) + return -1; + + if (!client->clientIds) + return -1; + + return client->clientIds->pid; +} + +/** + * Get cached command name string of a client. + * + * param[in] client Client whose command line string has been already + * cached. + * + * @return Cached client command name. Error (NULL) if called: + * - before ClientStateInitial client state notification + * - after ClientStateGone client state notification + * - for remote clients + * - on OS that doesn't support mapping of PID to command line + * + * @see DetermineClientCmd + */ +const char * +GetClientCmdName(struct _Client *client) +{ + if (client == NullClient) + return NULL; + + if (!client->clientIds) + return NULL; + + return client->clientIds->cmdname; +} + +/** + * Get cached command arguments string of a client. + * + * param[in] client Client whose command line string has been already + * cached. + * + * @return Cached client command arguments. Error (NULL) if called: + * - before ClientStateInitial client state notification + * - after ClientStateGone client state notification + * - for remote clients + * - on OS that doesn't support mapping of PID to command line + * + * @see DetermineClientCmd + */ +const char * +GetClientCmdArgs(struct _Client *client) +{ + if (client == NullClient) + return NULL; + + if (!client->clientIds) + return NULL; + + return client->clientIds->cmdargs; +} diff --git a/nx-X11/programs/Xserver/os/connection.c b/nx-X11/programs/Xserver/os/connection.c index 966fe208d..8a5eb756a 100644 --- a/nx-X11/programs/Xserver/os/connection.c +++ b/nx-X11/programs/Xserver/os/connection.c @@ -74,6 +74,7 @@ SOFTWARE. #define TRANS_SERVER #define TRANS_REOPEN #include <nx-X11/Xtrans/Xtrans.h> +#include <nx-X11/Xtrans/Xtransint.h> #include <errno.h> #include <signal.h> #include <stdio.h> @@ -122,7 +123,6 @@ SOFTWARE. int lastfdesc; /* maximum file descriptor */ -fd_set WellKnownConnections; /* Listener mask */ fd_set NotifyReadFds; /* mask for other file descriptors */ fd_set NotifyWriteFds; /* mask for other write file descriptors */ fd_set AllSockets; /* select on this */ @@ -136,7 +136,9 @@ int MaxClients = 0; int NumNotifyWriteFd; /* Number of NotifyFd members with write set */ Bool NewOutputPending; /* not yet attempted to write some new output */ Bool AnyWritesPending; /* true if some client blocked on write or NotifyFd with write */ +Bool NoListenAll; /* Don't establish any listening sockets */ Bool RunFromSmartParent; /* send SIGUSR1 to parent process */ +static char dynamic_display[7]; /* display name */ Bool PartialNetwork; /* continue even if unable to bind all addrs */ static Pid_t ParentProcess; @@ -149,6 +151,9 @@ static fd_set SavedAllSockets; static fd_set SavedClientsWithInput; int GrabInProgress = 0; +static void +QueueNewConnections(int curconn, int ready, void *data); + #if !defined(WIN32) int *ConnectionTranslation = NULL; #else @@ -319,6 +324,72 @@ InitConnectionLimits(void) #endif } +/* + * If SIGUSR1 was set to SIG_IGN when the server started, assume that either + * + * a- The parent process is ignoring SIGUSR1 + * + * or + * + * b- The parent process is expecting a SIGUSR1 + * when the server is ready to accept connections + * + * In the first case, the signal will be harmless, in the second case, + * the signal will be quite useful. + */ +static void +InitParentProcess(void) +{ +#if !defined(WIN32) + OsSigHandlerPtr handler; + handler = OsSignal (SIGUSR1, SIG_IGN); + if ( handler == SIG_IGN) + RunFromSmartParent = TRUE; + OsSignal(SIGUSR1, handler); + ParentProcess = getppid (); +#ifdef __UNIXOS2__ + /* + * fg030505: under OS/2, xinit is not the parent process but + * the "grant parent" process of the server because execvpe() + * presents us an additional process number; + * GetPPID(pid) is part of libemxfix + */ + ParentProcess = GetPPID (ParentProcess); +#endif /* __UNIXOS2__ */ +#endif +} + +void +NotifyParentProcess(void) +{ +#if !defined(WIN32) + if (displayfd >= 0) { + if (write(displayfd, display, strlen(display)) != strlen(display)) + FatalError("Cannot write display number to fd %d\n", displayfd); + if (write(displayfd, "\n", 1) != 1) + FatalError("Cannot write display number to fd %d\n", displayfd); + close(displayfd); + displayfd = -1; + } + if (RunFromSmartParent) { + if (ParentProcess > 1) { + kill (ParentProcess, SIGUSR1); + } + } +#endif +} + +static Bool +TryCreateSocket(int num, int *partial) +{ + char port[20]; + + snprintf(port, sizeof(port), "%d", num); + + return (_XSERVTransMakeAllCOTSServerListeners(port, partial, + &ListenTransCount, + &ListenTransConns) >= 0); +} /***************** * CreateWellKnownSockets @@ -330,8 +401,6 @@ CreateWellKnownSockets(void) { int i; int partial; - char port[20]; - OsSigHandlerPtr handler; FD_ZERO(&AllSockets); FD_ZERO(&AllClients); @@ -344,38 +413,47 @@ CreateWellKnownSockets(void) ClearConnectionTranslation(); #endif - FD_ZERO (&WellKnownConnections); + /* display is initialized to "0" by main(). It is then set to the display + * number if specified on the command line. */ + if (NoListenAll) { + ListenTransCount = 0; + } + else if ((displayfd < 0) || explicit_display) { + if (TryCreateSocket(atoi(display), &partial) && + ListenTransCount >= 1) + if (!PartialNetwork && partial) + FatalError ("Failed to establish all listening sockets"); + } + else { /* -displayfd and no explicit display number */ + Bool found = 0; + for (i = 0; i < 65536 - X_TCP_PORT; i++) { + if (TryCreateSocket(i, &partial) && !partial) { + found = 1; + break; + } + else + CloseWellKnownConnections(); + } + if (!found) + FatalError("Failed to find a socket to listen on"); + snprintf(dynamic_display, sizeof(dynamic_display), "%d", i); + display = dynamic_display; + LogSetDisplay(); + } - sprintf (port, "%d", atoi (display)); + ListenTransFds = malloc(ListenTransCount * sizeof (int)); - if ((_XSERVTransMakeAllCOTSServerListeners (port, &partial, - &ListenTransCount, &ListenTransConns) >= 0) && - (ListenTransCount >= 1)) - { - if (!PartialNetwork && partial) - { - FatalError ("Failed to establish all listening sockets"); - } - else - { - ListenTransFds = (int *) malloc (ListenTransCount * sizeof (int)); + for (i = 0; i < ListenTransCount; i++) { + int fd = _XSERVTransGetConnectionNumber(ListenTransConns[i]); - for (i = 0; i < ListenTransCount; i++) - { - int fd = _XSERVTransGetConnectionNumber (ListenTransConns[i]); - - ListenTransFds[i] = fd; - FD_SET (fd, &WellKnownConnections); - - if (!_XSERVTransIsLocal (ListenTransConns[i])) - { - DefineSelf (fd); - } - } - } + ListenTransFds[i] = fd; + SetNotifyFd(fd, QueueNewConnections, X_NOTIFY_READ, NULL); + + if (!_XSERVTransIsLocal(ListenTransConns[i])) + DefineSelf (fd); } - if (!XFD_ANYSET (&WellKnownConnections)) + if (ListenTransCount == 0 && !NoListenAll) FatalError ("Cannot establish any listening sockets - Make sure an X server isn't already running"); #if !defined(WIN32) OsSignal (SIGPIPE, SIG_IGN); @@ -383,35 +461,10 @@ CreateWellKnownSockets(void) #endif OsSignal (SIGINT, GiveUp); OsSignal (SIGTERM, GiveUp); - XFD_COPYSET (&WellKnownConnections, &AllSockets); ResetHosts(display); - /* - * Magic: If SIGUSR1 was set to SIG_IGN when - * the server started, assume that either - * - * a- The parent process is ignoring SIGUSR1 - * - * or - * - * b- The parent process is expecting a SIGUSR1 - * when the server is ready to accept connections - * - * In the first case, the signal will be harmless, - * in the second case, the signal will be quite - * useful - */ -#if !defined(WIN32) - handler = OsSignal (SIGUSR1, SIG_IGN); - if ( handler == SIG_IGN) - RunFromSmartParent = TRUE; - OsSignal(SIGUSR1, handler); - ParentProcess = getppid (); - if (RunFromSmartParent) { - if (ParentProcess > 1) { - kill (ParentProcess, SIGUSR1); - } - } -#endif + + InitParentProcess(); + #ifdef XDMCP XdmcpInit (); #endif @@ -476,7 +529,7 @@ ResetWellKnownSockets (void) * Remove it from out list. */ - FD_CLR (ListenTransFds[i], &WellKnownConnections); + RemoveNotifyFd(ListenTransFds[i]); ListenTransFds[i] = ListenTransFds[ListenTransCount - 1]; ListenTransConns[i] = ListenTransConns[ListenTransCount - 1]; ListenTransCount -= 1; @@ -490,26 +543,17 @@ ResetWellKnownSockets (void) int newfd = _XSERVTransGetConnectionNumber (ListenTransConns[i]); - FD_CLR (ListenTransFds[i], &WellKnownConnections); ListenTransFds[i] = newfd; - FD_SET(newfd, &WellKnownConnections); } } } + for (i = 0; i < ListenTransCount; i++) + SetNotifyFd(ListenTransFds[i], QueueNewConnections, X_NOTIFY_READ, NULL); + ResetAuthorization (); ResetHosts(display); /* - * See above in CreateWellKnownSockets about SIGUSR1 - */ -#if !defined(WIN32) - if (RunFromSmartParent) { - if (ParentProcess > 1) { - kill (ParentProcess, SIGUSR1); - } - } -#endif - /* * restart XDMCP */ #ifdef XDMCP @@ -522,8 +566,15 @@ CloseWellKnownConnections(void) { int i; - for (i = 0; i < ListenTransCount; i++) - _XSERVTransClose (ListenTransConns[i]); + for (i = 0; i < ListenTransCount; i++) { + if (ListenTransConns[i] != NULL) { + _XSERVTransClose(ListenTransConns[i]); + ListenTransConns[i] = NULL; + if (ListenTransFds != NULL) + RemoveNotifyFd(ListenTransFds[i]); + } + } + ListenTransCount = 0; } static void @@ -534,10 +585,9 @@ AuthAudit (ClientPtr client, Bool letin, char addr[128]; char *out = addr; - if (!((OsCommPtr)client->osPrivate)->trans_conn) { - strcpy(addr, "LBX proxy at "); - out += strlen(addr); - } + char client_uid_string[64]; + LocalClientCredRec *lcc; + if (!len) strcpy(out, "local host"); else @@ -549,7 +599,7 @@ AuthAudit (ClientPtr client, Bool letin, #endif strcpy(out, "local host"); break; -#if defined(TCPCONN) || defined(MNX_TCPCONN) +#if defined(TCPCONN) case AF_INET: sprintf(out, "IP %s", inet_ntoa(((struct sockaddr_in *) saddr)->sin_addr)); @@ -567,14 +617,56 @@ AuthAudit (ClientPtr client, Bool letin, default: strcpy(out, "unknown address"); } - + + if (GetLocalClientCreds(client, &lcc) != -1) { + int slen; /* length written to client_uid_string */ + + strcpy(client_uid_string, " ( "); + slen = 3; + + if (lcc->fieldsSet & LCC_UID_SET) { + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "uid=%ld ", (long) lcc->euid); + slen = strlen(client_uid_string); + } + + if (lcc->fieldsSet & LCC_GID_SET) { + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "gid=%ld ", (long) lcc->egid); + slen = strlen(client_uid_string); + } + + if (lcc->fieldsSet & LCC_PID_SET) { + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "pid=%ld ", (long) lcc->pid); + slen = strlen(client_uid_string); + } + + if (lcc->fieldsSet & LCC_ZID_SET) { + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "zoneid=%ld ", (long) lcc->zoneid); + slen = strlen(client_uid_string); + } + + snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen, ")"); + FreeLocalClientCreds(lcc); + } + else { + client_uid_string[0] = '\0'; + } + if (proto_n) - AuditF("client %d %s from %s\n Auth name: %.*s ID: %d\n", + AuditF("client %d %s from %s%s\n Auth name: %.*s ID: %d\n", client->index, letin ? "connected" : "rejected", addr, - (int)proto_n, auth_proto, auth_id); + client_uid_string, (int)proto_n, auth_proto, auth_id); else - AuditF("client %d %s from %s\n", - client->index, letin ? "connected" : "rejected", addr); + AuditF("client %d %s from %s%s\n", + client->index, letin ? "connected" : "rejected", addr, + client_uid_string); } XID @@ -713,6 +805,7 @@ AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time) free (oc); return NullClient; } + client->local = ComputeLocalClient(client); { #if !defined(WIN32) ConnectionTranslation[fd] = client->index; @@ -746,23 +839,18 @@ AllocNewConnection (XtransConnInfo trans_conn, int fd, CARD32 conn_time) * and AllSockets. *****************/ -/*ARGSUSED*/ -Bool +static Bool EstablishNewConnections(ClientPtr clientUnused, void * closure) { - fd_set readyconnections; /* set of listeners that are ready */ - int curconn; /* fd of listener that's ready */ - register int newconn; /* fd of new client */ + int curconn = (int) (intptr_t) closure; + int newconn; /* fd of new client */ CARD32 connect_time; - register int i; - register ClientPtr client; - register OsCommPtr oc; - fd_set tmask; - - XFD_ANDSET (&tmask, (fd_set*)closure, &WellKnownConnections); - XFD_COPYSET(&tmask, &readyconnections); - if (!XFD_ANYSET(&readyconnections)) - return TRUE; + int i; + ClientPtr client; + OsCommPtr oc; + XtransConnInfo trans_conn, new_trans_conn; + int status; + connect_time = GetTimeInMillis(); /* kill off stragglers */ for (i=1; i<currentMaxClients; i++) @@ -776,60 +864,44 @@ EstablishNewConnections(ClientPtr clientUnused, void * closure) CloseDownClient(client); } } -#ifndef WIN32 - for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++) - { - while (readyconnections.fds_bits[i]) -#else - for (i = 0; i < XFD_SETCOUNT(&readyconnections); i++) -#endif - { - XtransConnInfo trans_conn, new_trans_conn; - int status; - -#ifndef WIN32 - curconn = ffs (readyconnections.fds_bits[i]) - 1; - readyconnections.fds_bits[i] &= ~((fd_mask)1 << curconn); - curconn += (i * (sizeof(fd_mask)*8)); -#else - curconn = XFD_FD(&readyconnections, i); -#endif + if ((trans_conn = lookup_trans_conn(curconn)) == NULL) + return TRUE; - if ((trans_conn = lookup_trans_conn (curconn)) == NULL) - continue; + if ((new_trans_conn = _XSERVTransAccept(trans_conn, &status)) == NULL) + return TRUE; - if ((new_trans_conn = _XSERVTransAccept (trans_conn, &status)) == NULL) - continue; + newconn = _XSERVTransGetConnectionNumber(new_trans_conn); - newconn = _XSERVTransGetConnectionNumber (new_trans_conn); + if (newconn < lastfdesc) { + int clientid; - if (newconn < lastfdesc) - { - int clientid; #if !defined(WIN32) - clientid = ConnectionTranslation[newconn]; + clientid = ConnectionTranslation[newconn]; #else - clientid = GetConnectionTranslation(newconn); + clientid = GetConnectionTranslation(newconn); #endif - if(clientid && (client = clients[clientid])) - CloseDownClient(client); - } + if (clientid && (client = clients[clientid])) + CloseDownClient(client); + } - _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1); + _XSERVTransSetOption(new_trans_conn, TRANS_NONBLOCKING, 1); + + if (trans_conn->flags & TRANS_NOXAUTH) + new_trans_conn->flags = new_trans_conn->flags | TRANS_NOXAUTH; + + if (!AllocNewConnection(new_trans_conn, newconn, connect_time)) { + ErrorConnMax(new_trans_conn); + } - if (!AllocNewConnection (new_trans_conn, newconn, connect_time - )) - { - ErrorConnMax(new_trans_conn); - _XSERVTransClose(new_trans_conn); - } - } -#ifndef WIN32 - } -#endif return TRUE; } +static void +QueueNewConnections(int fd, int ready, void *data) +{ + QueueWorkProc(EstablishNewConnections, NULL, (void *) (intptr_t) fd); +} + #define NOROOM "Maximum number of clients reached" /************ @@ -838,35 +910,28 @@ EstablishNewConnections(ClientPtr clientUnused, void * closure) ************/ static void -ErrorConnMax(XtransConnInfo trans_conn) +ConnMaxNotify(int fd, int events, void *data) { - int fd = _XSERVTransGetConnectionNumber (trans_conn); - xConnSetupPrefix csp; - char pad[3]; - struct iovec iov[3]; - char byteOrder = 0; - int whichbyte = 1; - struct timeval waittime; - fd_set mask; - - /* if these seems like a lot of trouble to go to, it probably is */ - waittime.tv_sec = BOTIMEOUT / MILLI_PER_SECOND; - waittime.tv_usec = (BOTIMEOUT % MILLI_PER_SECOND) * - (1000000 / MILLI_PER_SECOND); - FD_ZERO(&mask); - FD_SET(fd, &mask); - (void)Select(fd + 1, &mask, NULL, NULL, &waittime); + XtransConnInfo trans_conn = data; + char order = 0; + /* try to read the byte-order of the connection */ - (void)_XSERVTransRead(trans_conn, &byteOrder, 1); - if ((byteOrder == 'l') || (byteOrder == 'B')) + (void)_XSERVTransRead(trans_conn, &order, 1); + if (order == 'l' || order == 'B' || order == 'r' || order == 'R') { + + xConnSetupPrefix csp; + char pad[3] = { 0, 0, 0 }; + int whichbyte = 1; + struct iovec iov[3]; + csp.success = xFalse; csp.lengthReason = sizeof(NOROOM) - 1; csp.length = (sizeof(NOROOM) + 2) >> 2; csp.majorVersion = X_PROTOCOL; csp.minorVersion = X_PROTOCOL_REVISION; - if (((*(char *) &whichbyte) && (byteOrder == 'B')) || - (!(*(char *) &whichbyte) && (byteOrder == 'l'))) + if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) || + (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) { swaps(&csp.majorVersion); swaps(&csp.minorVersion); @@ -880,6 +945,15 @@ ErrorConnMax(XtransConnInfo trans_conn) iov[2].iov_base = pad; (void)_XSERVTransWritev(trans_conn, iov, 3); } + RemoveNotifyFd(trans_conn->fd); + _XSERVTransClose(trans_conn); +} + +static void +ErrorConnMax(XtransConnInfo trans_conn) +{ + if (!SetNotifyFd(trans_conn->fd, ConnMaxNotify, X_NOTIFY_READ, trans_conn)) + _XSERVTransClose(trans_conn); } /************ @@ -987,6 +1061,9 @@ CloseDownConnection(ClientPtr client) { OsCommPtr oc = (OsCommPtr)client->osPrivate; + if (FlushCallback) + CallCallbacks(&FlushCallback, client); + if (oc->output && oc->output->count) FlushClient(client, oc, (char *)NULL, 0); #ifdef XDMCP diff --git a/nx-X11/programs/Xserver/os/io.c b/nx-X11/programs/Xserver/os/io.c index 92a3f0476..07399438e 100644 --- a/nx-X11/programs/Xserver/os/io.c +++ b/nx-X11/programs/Xserver/os/io.c @@ -252,7 +252,14 @@ ReadRequestFromClient(ClientPtr client) move_header = FALSE; #endif gotnow = oci->bufcnt + oci->buffer - oci->bufptr; - if (gotnow < sizeof(xReq)) + + if (oci->ignoreBytes > 0) { + if (oci->ignoreBytes > oci->size) + needed = oci->size; + else + needed = oci->ignoreBytes; + } + else if (gotnow < sizeof(xReq)) { /* We don't have an entire xReq yet. Can't tell how big * the request will be until we get the whole xReq. @@ -297,8 +304,13 @@ ReadRequestFromClient(ClientPtr client) if (needed > MAXBUFSIZE) { /* request is too big for us to handle */ - YieldControlDeath(); - return -1; + /* + * Mark the rest of it as needing to be ignored, and then return + * the full size. Dispatch() will turn it into a BadLength error. + */ + oci->ignoreBytes = needed - gotnow; + oci->lenLastReq = gotnow; + return needed; } if ((gotnow == 0) || ((oci->bufptr - oci->buffer + needed) > oci->size)) @@ -405,6 +417,29 @@ ReadRequestFromClient(ClientPtr client) #endif needed = sizeof(xReq); } + + /* If there are bytes to ignore, ignore them now. */ + + if (oci->ignoreBytes > 0) { + assert(needed == oci->ignoreBytes || needed == oci->size); + oci->ignoreBytes -= gotnow; + needed = gotnow = 0; + /* + * The _XSERVTransRead call above may return more or fewer bytes than we + * want to ignore. Ignore the smaller of the two sizes. + */ + if (gotnow < needed) { + oci->ignoreBytes -= gotnow; + oci->bufptr += gotnow; + gotnow = 0; + } else { + oci->ignoreBytes -= needed; + oci->bufptr += needed; + gotnow -= needed; + } + needed = 0; + } + oci->lenLastReq = needed; /* @@ -430,24 +465,15 @@ ReadRequestFromClient(ClientPtr client) FD_SET(fd, &ClientsWithInput); else { - if (!SmartScheduleDisable) - FD_CLR(fd, &ClientsWithInput); - else - YieldControlNoInput(); + FD_CLR(fd, &ClientsWithInput); } } else { if (!gotnow) AvailableInput = oc; - if (!SmartScheduleDisable) - FD_CLR(fd, &ClientsWithInput); - else - YieldControlNoInput(); + FD_CLR(fd, &ClientsWithInput); } - if (SmartScheduleDisable) - if (++timesThisConnection >= MAX_TIMES_PER) - YieldControl(); #ifdef BIGREQS if (move_header) { @@ -755,9 +781,6 @@ FlushAllOutput(void) fd_set newOutputPending; #endif - if (FlushCallback) - CallCallbacks(&FlushCallback, NULL); - if (!newoutput) return; @@ -958,7 +981,7 @@ WriteToClient (ClientPtr who, int count, const void *__buf) } } #endif - if (oco->count + count + padBytes > oco->size) + if (oco->count == 0 || oco->count + count + padBytes > oco->size) { FD_CLR(oc->fd, &OutputPending); if(!XFD_ANYSET(&OutputPending)) { @@ -971,7 +994,11 @@ WriteToClient (ClientPtr who, int count, const void *__buf) NewOutputPending = TRUE; FD_SET(oc->fd, &OutputPending); memmove((char *)oco->buf + oco->count, buf, count); - oco->count += count + padBytes; + oco->count += count; + if (padBytes) { + memset(oco->buf + oco->count, '\0', padBytes); + oco->count += padBytes; + } return(count); } @@ -1004,6 +1031,13 @@ FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount) written = 0; padsize = padlength[extraCount & 3]; notWritten = oco->count + extraCount + padsize; + + if (!notWritten) + return 0; + + if (FlushCallback) + CallCallbacks(&FlushCallback, who); + todo = notWritten; while (notWritten) { long before = written; /* amount of whole thing written */ @@ -1083,10 +1117,11 @@ FlushClient(ClientPtr who, OsCommPtr oc, const void *__extraBuf, int extraCount) if (notWritten > oco->size) { - unsigned char *obuf; + unsigned char *obuf = NULL; - obuf = (unsigned char *)realloc(oco->buf, - notWritten + BUFSIZE); + if (notWritten + BUFSIZE <= INT_MAX) { + obuf = realloc(oco->buf, notWritten + BUFSIZE); + } if (!obuf) { _XSERVTransDisconnect(oc->trans_conn); @@ -1173,6 +1208,7 @@ AllocateInputBuffer(void) oci->bufptr = oci->buffer; oci->bufcnt = 0; oci->lenLastReq = 0; + oci->ignoreBytes = 0; return oci; } @@ -1217,6 +1253,7 @@ FreeOsBuffers(OsCommPtr oc) oci->bufptr = oci->buffer; oci->bufcnt = 0; oci->lenLastReq = 0; + oci->ignoreBytes = 0; } } if ((oco = oc->output)) diff --git a/nx-X11/programs/Xserver/os/log.c b/nx-X11/programs/Xserver/os/log.c index d82f545a0..0ead6e9f0 100644 --- a/nx-X11/programs/Xserver/os/log.c +++ b/nx-X11/programs/Xserver/os/log.c @@ -179,48 +179,87 @@ static Bool needBuffer = TRUE; #endif /* + * LogFilePrep is called to setup files for logging, including getting + * an old file out of the way, but it doesn't actually open the file, + * since it may be used for renaming a file we're already logging to. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + +static char * +LogFilePrep(const char *fname, const char *backup, const char *idstring) +{ + char *logFileName = NULL; + + if (asprintf(&logFileName, fname, idstring) == -1) + FatalError("Cannot allocate space for the log file name\n"); + + if (backup && *backup) { + struct stat buf; + + if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) { + char *suffix; + char *oldLog; + + if ((asprintf(&suffix, backup, idstring) == -1) || + (asprintf(&oldLog, "%s%s", logFileName, suffix) == -1)) { + FatalError("Cannot allocate space for the log file name\n"); + } + free(suffix); + + if (rename(logFileName, oldLog) == -1) { + FatalError("Cannot move old log file \"%s\" to \"%s\"\n", + logFileName, oldLog); + } + free(oldLog); + } + } + else { + if (remove(logFileName) != 0) { + FatalError("Cannot remove old log file \"%s\": %s\n", + logFileName, strerror(errno)); + } + } + + return logFileName; +} +#pragma GCC diagnostic pop + +/* * LogInit is called to start logging to a file. It is also called (with * NULL arguments) when logging to a file is not wanted. It must always be * called, otherwise log messages will continue to accumulate in a buffer. * * %s, if present in the fname or backup strings, is expanded to the display - * string. + * string (or to a string containing the pid if the display is not yet set). */ +static char *saved_log_fname; +static char *saved_log_backup; +static char *saved_log_tempname; + const char * LogInit(const char *fname, const char *backup) { char *logFileName = NULL; if (fname && *fname) { - /* malloc() can't be used yet. */ - logFileName = malloc(strlen(fname) + strlen(display) + 1); - if (!logFileName) - FatalError("Cannot allocate space for the log file name\n"); - sprintf(logFileName, fname, display); - - if (backup && *backup) { - struct stat buf; - - if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) { - char *suffix; - char *oldLog; - - oldLog = malloc(strlen(logFileName) + strlen(backup) + - strlen(display) + 1); - suffix = malloc(strlen(backup) + strlen(display) + 1); - if (!oldLog || !suffix) - FatalError("Cannot allocate space for the log file name\n"); - sprintf(suffix, backup, display); - sprintf(oldLog, "%s%s", logFileName, suffix); - free(suffix); - if (rename(logFileName, oldLog) == -1) { - FatalError("Cannot move old log file (\"%s\" to \"%s\"\n", - logFileName, oldLog); - } - free(oldLog); - } - } + if (displayfd != -1) { + /* Display isn't set yet, so we can't use it in filenames yet. */ + char pidstring[32]; + snprintf(pidstring, sizeof(pidstring), "pid-%ld", + (unsigned long) getpid()); + logFileName = LogFilePrep(fname, backup, pidstring); + saved_log_tempname = logFileName; + + /* Save the patterns for use when the display is named. */ + saved_log_fname = strdup(fname); + if (backup == NULL) + saved_log_backup = NULL; + else + saved_log_backup = strdup(backup); + } else + logFileName = LogFilePrep(fname, backup, display); if ((logFile = fopen(logFileName, "w")) == NULL) FatalError("Cannot open log file \"%s\"\n", logFileName); setvbuf(logFile, NULL, _IONBF, 0); @@ -250,6 +289,36 @@ LogInit(const char *fname, const char *backup) } void +LogSetDisplay(void) +{ + if (saved_log_fname) { + char *logFileName; + + logFileName = LogFilePrep(saved_log_fname, saved_log_backup, display); + + if (rename(saved_log_tempname, logFileName) == 0) { + LogMessageVerb(X_PROBED, 0, + "Log file renamed from \"%s\" to \"%s\"\n", + saved_log_tempname, logFileName); + + if (strlen(saved_log_tempname) >= strlen(logFileName)) + strncpy(saved_log_tempname, logFileName, + strlen(saved_log_tempname)); + } + else { + ErrorF("Failed to rename log file \"%s\" to \"%s\": %s\n", + saved_log_tempname, logFileName, strerror(errno)); + } + + /* free newly allocated string - can't free old one since existing + pointers to it may exist in DDX callers. */ + free(logFileName); + free(saved_log_fname); + free(saved_log_backup); + } +} + +void LogClose() { if (logFile) { diff --git a/nx-X11/programs/Xserver/os/osdep.h b/nx-X11/programs/Xserver/os/osdep.h index 6ac9d860e..d3e9d0b33 100644 --- a/nx-X11/programs/Xserver/os/osdep.h +++ b/nx-X11/programs/Xserver/os/osdep.h @@ -52,7 +52,6 @@ SOFTWARE. #ifndef _OSDEP_H_ #define _OSDEP_H_ 1 -#define BOTIMEOUT 200 /* in milliseconds */ #define BUFSIZE 4096 #define BUFWATERMARK 8192 #ifndef MAXBUFSIZE @@ -129,6 +128,7 @@ typedef struct _connectionInput { int bufcnt; /* count of bytes in buffer */ int lenLastReq; int size; + unsigned int ignoreBytes; /* bytes to ignore before the next request */ } ConnectionInput, *ConnectionInputPtr; typedef struct _connectionOutput { @@ -238,6 +238,9 @@ typedef long int fd_mask; #define ffs mffs extern int mffs(fd_mask); +/* in access.c */ +extern Bool ComputeLocalClient(ClientPtr client); + /* in auth.c */ extern void GenerateRandomData (int len, char *buf); diff --git a/nx-X11/programs/Xserver/os/osinit.c b/nx-X11/programs/Xserver/os/osinit.c index 08fbb8c89..a660337ca 100644 --- a/nx-X11/programs/Xserver/os/osinit.c +++ b/nx-X11/programs/Xserver/os/osinit.c @@ -217,9 +217,8 @@ OsInit(void) * log file name if logging to a file is desired. */ LogInit(NULL, NULL); - if (!SmartScheduleDisable) - if (!SmartScheduleInit ()) - SmartScheduleDisable = TRUE; + SmartScheduleInit(); + OsInitAllocator(); } diff --git a/nx-X11/programs/Xserver/os/utils.c b/nx-X11/programs/Xserver/os/utils.c index af793454f..31ea55bc3 100644 --- a/nx-X11/programs/Xserver/os/utils.c +++ b/nx-X11/programs/Xserver/os/utils.c @@ -290,7 +290,8 @@ OsSignal(sig, handler) sigaddset(&act.sa_mask, sig); act.sa_flags = 0; act.sa_handler = handler; - sigaction(sig, &act, &oact); + if (sigaction(sig, &act, &oact)) + perror("sigaction"); return oact.sa_handler; #endif } @@ -337,7 +338,7 @@ LockServer(void) int len; char port[20]; - if (nolock) return; + if (nolock || NoListenAll) return; /* * Path names */ @@ -463,7 +464,7 @@ LockServer(void) void UnlockServer(void) { - if (nolock) return; + if (nolock || NoListenAll) return; if (!StillLocking){ @@ -621,7 +622,6 @@ void UseMsg(void) ErrorF("v video blanking for screen-saver\n"); ErrorF("-v screen-saver without video blanking\n"); ErrorF("-wm WhenMapped default backing-store\n"); - ErrorF("-x string loads named extension at init time \n"); ErrorF("-maxbigreqsize set maximal bigrequest size \n"); #ifdef PANORAMIX ErrorF("+xinerama Enable XINERAMA (PanoramiX) extension\n"); @@ -703,6 +703,7 @@ ProcessCommandLine(int argc, char *argv[]) { /* initialize display */ display = argv[i]; + explicit_display = TRUE; display++; if( ! VerifyDisplayName( display ) ) { ErrorF("Bad display name: %s\n", display); @@ -779,6 +780,15 @@ ProcessCommandLine(int argc, char *argv[]) else UseMsg(); } + else if (strcmp(argv[i], "-displayfd") == 0) { + if (++i < argc) { + displayfd = atoi(argv[i]); + nolock = TRUE; + } + else + UseMsg(); + } + #ifdef DPMSExtension else if ( strcmp( argv[i], "dpms") == 0) DPMSEnabledSwitch = TRUE; @@ -891,6 +901,11 @@ ProcessCommandLine(int argc, char *argv[]) else if ( strcmp( argv[i], "-nolisten") == 0) { if(++i < argc) { +#ifdef NXAGENT_SERVER + if (strcmp( argv[i], "ANY" ) == 0) + NoListenAll = TRUE; + else +#endif /* NXAGENT_SERVER */ if (_XSERVTransNoListen(argv[i])) FatalError ("Failed to disable listen for %s transport", argv[i]); @@ -996,14 +1011,6 @@ ProcessCommandLine(int argc, char *argv[]) noRRXineramaExtension = TRUE; } #endif - else if ( strcmp( argv[i], "-x") == 0) - { - if(++i >= argc) - UseMsg(); - /* For U**x, which doesn't support dynamic loading, there's nothing - * to do when we see a -x. Either the extension is linked in or - * it isn't */ - } else if ( strcmp( argv[i], "-I") == 0) { /* ignore all remaining arguments */ @@ -1026,10 +1033,12 @@ ProcessCommandLine(int argc, char *argv[]) i = skip - 1; } #endif +#if HAVE_SETITIMER else if ( strcmp( argv[i], "-dumbSched") == 0) { - SmartScheduleDisable = TRUE; + SmartScheduleSignalEnable = FALSE; } +#endif else if ( strcmp( argv[i], "-schedInterval") == 0) { if (++i < argc) @@ -1353,30 +1362,15 @@ XNFstrdup(const char *s) return ret; } -unsigned long SmartScheduleIdleCount; -Bool SmartScheduleIdle; -Bool SmartScheduleTimerStopped; - -#ifdef SIGVTALRM -#define SMART_SCHEDULE_POSSIBLE -#endif - -#ifdef SMART_SCHEDULE_POSSIBLE -#define SMART_SCHEDULE_SIGNAL SIGALRM -#define SMART_SCHEDULE_TIMER ITIMER_REAL -#endif - -#ifdef NX_TRANS_SOCKET void SmartScheduleStopTimer (void) -#else -static void -SmartScheduleStopTimer (void) -#endif { -#ifdef SMART_SCHEDULE_POSSIBLE +#if HAVE_SETITIMER struct itimerval timer; + if (!SmartScheduleSignalEnable) + return; + #ifdef NX_TRANS_TEST fprintf(stderr, "SmartScheduleStopTimer: Stopping timer.\n"); #endif @@ -1386,96 +1380,101 @@ SmartScheduleStopTimer (void) timer.it_value.tv_sec = 0; timer.it_value.tv_usec = 0; (void) setitimer (ITIMER_REAL, &timer, 0); - SmartScheduleTimerStopped = TRUE; #endif } -Bool +void SmartScheduleStartTimer (void) { -#ifdef SMART_SCHEDULE_POSSIBLE +#if HAVE_SETITIMER struct itimerval timer; - #ifdef NX_TRANS_SOCKET - - if (SmartScheduleDisable) - { - return FALSE; - } - - #endif + if (!SmartScheduleSignalEnable) + return; #ifdef NX_TRANS_TEST fprintf(stderr, "SmartScheduleStartTimer: Starting timer with [%ld] ms.\n", SmartScheduleInterval); #endif - SmartScheduleTimerStopped = FALSE; timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = SmartScheduleInterval * 1000; timer.it_value.tv_sec = 0; timer.it_value.tv_usec = SmartScheduleInterval * 1000; - return setitimer (ITIMER_REAL, &timer, 0) >= 0; + setitimer (ITIMER_REAL, &timer, 0); #endif - return FALSE; } -#ifdef SMART_SCHEDULE_POSSIBLE +#if HAVE_SETITIMER static void SmartScheduleTimer (int sig) { - int olderrno = errno; - SmartScheduleTime += SmartScheduleInterval; #ifdef NX_TRANS_TEST fprintf(stderr, "SmartScheduleTimer: Got timer with time [%ld] ms.\n", SmartScheduleTime); #endif - - if (SmartScheduleIdle) - { - SmartScheduleStopTimer (); - } - errno = olderrno; } -#endif -Bool -SmartScheduleInit (void) +int +SmartScheduleEnable (void) { -#ifdef SMART_SCHEDULE_POSSIBLE + int ret = 0; struct sigaction act; - if (SmartScheduleDisable) - return TRUE; - + if (!SmartScheduleSignalEnable) + return 0; + #ifdef NX_TRANS_TEST - fprintf(stderr, "SmartScheduleInit: Initializing the smart scheduler.\n"); + fprintf(stderr, "SmartScheduleEnable: Enabling the smart scheduler.\n"); #endif - bzero ((char *) &act, sizeof(struct sigaction)); + memset((char *) &act, 0, sizeof(struct sigaction)); /* Set up the timer signal function */ + act.sa_flags = SA_RESTART; act.sa_handler = SmartScheduleTimer; sigemptyset (&act.sa_mask); - sigaddset (&act.sa_mask, SMART_SCHEDULE_SIGNAL); - if (sigaction (SMART_SCHEDULE_SIGNAL, &act, 0) < 0) - { - perror ("sigaction for smart scheduler"); - return FALSE; - } - /* Set up the virtual timer */ - if (!SmartScheduleStartTimer ()) - { - perror ("scheduling timer"); - return FALSE; + sigaddset (&act.sa_mask, SIGALRM); + ret = sigaction(SIGALRM, &act, 0); + return ret; +} + +static int +SmartSchedulePause(void) +{ + int ret = 0; + struct sigaction act; + + if (!SmartScheduleSignalEnable) + return 0; + + #ifdef NX_TRANS_TEST + fprintf(stderr, "SmartSchedulePause: Pausing the smart scheduler.\n"); + #endif + + memset((char *) &act, 0, sizeof(struct sigaction)); + + act.sa_handler = SIG_IGN; + sigemptyset(&act.sa_mask); + ret = sigaction(SIGALRM, &act, 0); + return ret; +} +#endif + +void +SmartScheduleInit(void) +{ +#if HAVE_SETITIMER + #ifdef NX_TRANS_TEST + fprintf(stderr, "SmartScheduleInit: Initializing the smart scheduler.\n"); + #endif + + if (SmartScheduleEnable() < 0) { + perror("sigaction for smart scheduler"); + SmartScheduleSignalEnable = FALSE; } - /* stop the timer and wait for WaitForSomething to start it */ - SmartScheduleStopTimer (); - return TRUE; -#else - return FALSE; #endif } @@ -1558,7 +1557,11 @@ System(char *command) return(1); #ifdef SIGCHLD - csig = signal(SIGCHLD, SIG_DFL); + csig = OsSignal(SIGCHLD, SIG_DFL); + if (csig == SIG_ERR) { + perror("signal"); + return -1; + } #endif #ifdef DEBUG @@ -1596,7 +1599,10 @@ System(char *command) #endif #ifdef SIGCHLD - signal(SIGCHLD, csig); + if (OsSignal(SIGCHLD, csig) == SIG_ERR) { + perror("signal"); + return -1; + } #endif return p == -1 ? -1 : status; @@ -1629,6 +1635,17 @@ Popen(char *command, char *type) return NULL; } + /* Ignore the smart scheduler while this is going on */ +#if HAVE_SETITIMER + if (SmartSchedulePause() < 0) { + close(pdes[0]); + close(pdes[1]); + free(cur); + perror("signal"); + return NULL; + } +#endif + #ifdef NX_TRANS_EXIT if (OsVendorStartRedirectErrorFProc != NULL) { OsVendorStartRedirectErrorFProc(); @@ -1640,6 +1657,10 @@ Popen(char *command, char *type) close(pdes[0]); close(pdes[1]); free(cur); +#if HAVE_SETITIMER + if (SmartScheduleEnable() < 0) + perror("signal"); +#endif #ifdef NX_TRANS_EXIT if (OsVendorEndRedirectErrorFProc != NULL) { OsVendorEndRedirectErrorFProc(); @@ -1714,6 +1735,13 @@ Popen(char *command, char *type) OsReleaseSignals (); #endif +#if HAVE_SETITIMER + if (SmartScheduleEnable() < 0) { + perror("signal"); + return NULL; + } +#endif + execl("/bin/sh", "sh", "-c", command, (char *)NULL); _exit(127); } diff --git a/nx-X11/programs/Xserver/os/xdmcp.c b/nx-X11/programs/Xserver/os/xdmcp.c index c4b71f6ec..c1aa57e95 100644 --- a/nx-X11/programs/Xserver/os/xdmcp.c +++ b/nx-X11/programs/Xserver/os/xdmcp.c @@ -205,8 +205,6 @@ extern void XdmcpDeadSession(char * /*reason*/); static void timeout(void); -static void restart(void); - static void XdmcpBlockHandler( void * /*data*/, struct timeval ** /*wt*/, @@ -959,14 +957,6 @@ timeout(void) send_packet(); } -static void -restart(void) -{ - state = XDM_INIT_STATE; - timeOutRtx = 0; - send_packet(); -} - int XdmcpCheckAuthentication ( ARRAY8Ptr Name, |