Apply a patch for fixing TDIS-5990 (CVE-2013-1940 allow physically proximate attacker...
[framework/uifw/xorg/server/xorg-server.git] / os / WaitFor.c
1 /***********************************************************
2
3 Copyright 1987, 1998  The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24
25 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
26
27                         All Rights Reserved
28
29 Permission to use, copy, modify, and distribute this software and its 
30 documentation for any purpose and without fee is hereby granted, 
31 provided that the above copyright notice appear in all copies and that
32 both that copyright notice and this permission notice appear in 
33 supporting documentation, and that the name of Digital not be
34 used in advertising or publicity pertaining to distribution of the
35 software without specific, written prior permission.  
36
37 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43 SOFTWARE.
44
45 ******************************************************************/
46
47 /*****************************************************************
48  * OS Dependent input routines:
49  *
50  *  WaitForSomething
51  *  TimerForce, TimerSet, TimerCheck, TimerFree
52  *
53  *****************************************************************/
54
55 #ifdef HAVE_DIX_CONFIG_H
56 #include <dix-config.h>
57 #endif
58
59 #ifdef WIN32
60 #include <X11/Xwinsock.h>
61 #endif
62 #include <X11/Xos.h>            /* for strings, fcntl, time */
63 #include <errno.h>
64 #include <stdio.h>
65 #include <X11/X.h>
66 #include "misc.h"
67
68 #include "osdep.h"
69 #include <X11/Xpoll.h>
70 #include "dixstruct.h"
71 #include "opaque.h"
72 #ifdef DPMSExtension
73 #include "dpmsproc.h"
74 #endif
75
76 #ifdef WIN32
77 /* Error codes from windows sockets differ from fileio error codes  */
78 #undef EINTR
79 #define EINTR WSAEINTR
80 #undef EINVAL
81 #define EINVAL WSAEINVAL
82 #undef EBADF
83 #define EBADF WSAENOTSOCK
84 /* Windows select does not set errno. Use GetErrno as wrapper for 
85    WSAGetLastError */
86 #define GetErrno WSAGetLastError
87 #else
88 /* This is just a fallback to errno to hide the differences between unix and
89    Windows in the code */
90 #define GetErrno() errno
91 #endif
92
93 /* like ffs, but uses fd_mask instead of int as argument, so it works
94    when fd_mask is longer than an int, such as common 64-bit platforms */
95 /* modifications by raphael */
96 int
97 mffs(fd_mask mask)
98 {
99     int i;
100
101     if (!mask)
102         return 0;
103     i = 1;
104     while (!(mask & 1)) {
105         i++;
106         mask >>= 1;
107     }
108     return i;
109 }
110
111 #ifdef DPMSExtension
112 #include <X11/extensions/dpmsconst.h>
113 #endif
114
115 struct _OsTimerRec {
116     OsTimerPtr next;
117     CARD32 expires;
118     CARD32 delta;
119     OsTimerCallback callback;
120     pointer arg;
121 };
122
123 static void DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev);
124 static void CheckAllTimers(void);
125 static OsTimerPtr timers = NULL;
126
127 /*****************
128  * WaitForSomething:
129  *     Make the server suspend until there is
130  *      1. data from clients or
131  *      2. input events available or
132  *      3. ddx notices something of interest (graphics
133  *         queue ready, etc.) or
134  *      4. clients that have buffered replies/events are ready
135  *
136  *     If the time between INPUT events is
137  *     greater than ScreenSaverTime, the display is turned off (or
138  *     saved, depending on the hardware).  So, WaitForSomething()
139  *     has to handle this also (that's why the select() has a timeout.
140  *     For more info on ClientsWithInput, see ReadRequestFromClient().
141  *     pClientsReady is an array to store ready client->index values into.
142  *****************/
143
144 int
145 WaitForSomething(int *pClientsReady)
146 {
147     int i;
148     struct timeval waittime, *wt;
149     INT32 timeout = 0;
150     fd_set clientsReadable;
151     fd_set clientsWritable;
152     int curclient;
153     int selecterr;
154     static int nready;
155     fd_set devicesReadable;
156     CARD32 now = 0;
157     Bool someReady = FALSE;
158
159     FD_ZERO(&clientsReadable);
160
161     if (nready)
162         SmartScheduleStopTimer();
163     nready = 0;
164
165     /* We need a while loop here to handle 
166        crashed connections and the screen saver timeout */
167     while (1) {
168         /* deal with any blocked jobs */
169         if (workQueue)
170             ProcessWorkQueue();
171         if (XFD_ANYSET(&ClientsWithInput)) {
172             if (!SmartScheduleDisable) {
173                 someReady = TRUE;
174                 waittime.tv_sec = 0;
175                 waittime.tv_usec = 0;
176                 wt = &waittime;
177             }
178             else {
179                 XFD_COPYSET(&ClientsWithInput, &clientsReadable);
180                 break;
181             }
182         }
183         if (someReady) {
184             XFD_COPYSET(&AllSockets, &LastSelectMask);
185             XFD_UNSET(&LastSelectMask, &ClientsWithInput);
186         }
187         else {
188             wt = NULL;
189             if (timers) {
190                 now = GetTimeInMillis();
191                 timeout = timers->expires - now;
192                 if (timeout > 0 && timeout > timers->delta + 250) {
193                     /* time has rewound.  reset the timers. */
194                     CheckAllTimers();
195                 }
196
197                 if (timers) {
198                     timeout = timers->expires - now;
199                     if (timeout < 0)
200                         timeout = 0;
201                     waittime.tv_sec = timeout / MILLI_PER_SECOND;
202                     waittime.tv_usec = (timeout % MILLI_PER_SECOND) *
203                         (1000000 / MILLI_PER_SECOND);
204                     wt = &waittime;
205                 }
206             }
207             XFD_COPYSET(&AllSockets, &LastSelectMask);
208         }
209
210         BlockHandler((pointer) &wt, (pointer) &LastSelectMask);
211         if (NewOutputPending)
212             FlushAllOutput();
213         /* keep this check close to select() call to minimize race */
214         if (dispatchException)
215             i = -1;
216         else if (AnyClientsWriteBlocked) {
217             XFD_COPYSET(&ClientsWriteBlocked, &clientsWritable);
218 #ifndef _F_EXCLUDE_NON_MASK_SELECTED_FD_FROM_MAXCLIENTS_
219             i = Select(MaxClients, &LastSelectMask, &clientsWritable, NULL, wt);
220 #else
221             i = Select(FD_SETSIZE, &LastSelectMask, &clientsWritable, NULL, wt);
222 #endif
223         }
224         else {
225 #ifndef _F_EXCLUDE_NON_MASK_SELECTED_FD_FROM_MAXCLIENTS_
226             i = Select(MaxClients, &LastSelectMask, NULL, NULL, wt);
227 #else
228             i = Select(FD_SETSIZE, &LastSelectMask, NULL, NULL, wt);
229 #endif
230         }
231         selecterr = GetErrno();
232         WakeupHandler(i, (pointer) &LastSelectMask);
233         if (i <= 0) {           /* An error or timeout occurred */
234             if (dispatchException)
235                 return 0;
236             if (i < 0) {
237                 if (selecterr == EBADF) {       /* Some client disconnected */
238                     CheckConnections();
239                     if (!XFD_ANYSET(&AllClients))
240                         return 0;
241                 }
242                 else if (selecterr == EINVAL) {
243                     FatalError("WaitForSomething(): select: %s\n",
244                                strerror(selecterr));
245                 }
246                 else if (selecterr != EINTR && selecterr != EAGAIN) {
247                     ErrorF("WaitForSomething(): select: %s\n",
248                            strerror(selecterr));
249                 }
250             }
251             else if (someReady) {
252                 /*
253                  * If no-one else is home, bail quickly
254                  */
255                 XFD_COPYSET(&ClientsWithInput, &LastSelectMask);
256                 XFD_COPYSET(&ClientsWithInput, &clientsReadable);
257                 break;
258             }
259             if (*checkForInput[0] != *checkForInput[1])
260                 return 0;
261
262             if (timers) {
263                 int expired = 0;
264
265                 now = GetTimeInMillis();
266                 if ((int) (timers->expires - now) <= 0)
267                     expired = 1;
268
269                 while (timers && (int) (timers->expires - now) <= 0)
270                     DoTimer(timers, now, &timers);
271
272                 if (expired)
273                     return 0;
274             }
275         }
276         else {
277             fd_set tmp_set;
278
279             if (*checkForInput[0] == *checkForInput[1]) {
280                 if (timers) {
281                     int expired = 0;
282
283                     now = GetTimeInMillis();
284                     if ((int) (timers->expires - now) <= 0)
285                         expired = 1;
286
287                     while (timers && (int) (timers->expires - now) <= 0)
288                         DoTimer(timers, now, &timers);
289
290                     if (expired)
291                         return 0;
292                 }
293             }
294             if (someReady)
295                 XFD_ORSET(&LastSelectMask, &ClientsWithInput, &LastSelectMask);
296             if (AnyClientsWriteBlocked && XFD_ANYSET(&clientsWritable)) {
297                 NewOutputPending = TRUE;
298                 XFD_ORSET(&OutputPending, &clientsWritable, &OutputPending);
299                 XFD_UNSET(&ClientsWriteBlocked, &clientsWritable);
300                 if (!XFD_ANYSET(&ClientsWriteBlocked))
301                     AnyClientsWriteBlocked = FALSE;
302             }
303
304             XFD_ANDSET(&devicesReadable, &LastSelectMask, &EnabledDevices);
305             XFD_ANDSET(&clientsReadable, &LastSelectMask, &AllClients);
306             XFD_ANDSET(&tmp_set, &LastSelectMask, &WellKnownConnections);
307             if (XFD_ANYSET(&tmp_set))
308                 QueueWorkProc(EstablishNewConnections, NULL,
309                               (pointer) &LastSelectMask);
310
311             if (XFD_ANYSET(&devicesReadable) || XFD_ANYSET(&clientsReadable))
312                 break;
313             /* check here for DDXes that queue events during Block/Wakeup */
314             if (*checkForInput[0] != *checkForInput[1])
315                 return 0;
316         }
317     }
318
319     nready = 0;
320     if (XFD_ANYSET(&clientsReadable)) {
321 #ifndef WIN32
322         for (i = 0; i < howmany(XFD_SETSIZE, NFDBITS); i++) {
323             int highest_priority = 0;
324
325             while (clientsReadable.fds_bits[i]) {
326                 int client_priority, client_index;
327
328                 curclient = mffs(clientsReadable.fds_bits[i]) - 1;
329                 client_index =  /* raphael: modified */
330                     ConnectionTranslation[curclient +
331                                           (i * (sizeof(fd_mask) * 8))];
332 #else
333         int highest_priority = 0;
334         fd_set savedClientsReadable;
335
336         XFD_COPYSET(&clientsReadable, &savedClientsReadable);
337         for (i = 0; i < XFD_SETCOUNT(&savedClientsReadable); i++) {
338             int client_priority, client_index;
339
340             curclient = XFD_FD(&savedClientsReadable, i);
341             client_index = GetConnectionTranslation(curclient);
342 #endif
343             /*  We implement "strict" priorities.
344              *  Only the highest priority client is returned to
345              *  dix.  If multiple clients at the same priority are
346              *  ready, they are all returned.  This means that an
347              *  aggressive client could take over the server.
348              *  This was not considered a big problem because
349              *  aggressive clients can hose the server in so many 
350              *  other ways :)
351              */
352             client_priority = clients[client_index]->priority;
353             if (nready == 0 || client_priority > highest_priority) {
354                 /*  Either we found the first client, or we found
355                  *  a client whose priority is greater than all others
356                  *  that have been found so far.  Either way, we want 
357                  *  to initialize the list of clients to contain just
358                  *  this client.
359                  */
360                 pClientsReady[0] = client_index;
361                 highest_priority = client_priority;
362                 nready = 1;
363             }
364             /*  the following if makes sure that multiple same-priority 
365              *  clients get batched together
366              */
367             else if (client_priority == highest_priority) {
368                 pClientsReady[nready++] = client_index;
369             }
370 #ifndef WIN32
371             clientsReadable.fds_bits[i] &= ~(((fd_mask) 1L) << curclient);
372         }
373 #else
374             FD_CLR(curclient, &clientsReadable);
375 #endif
376         }
377     }
378
379     if (nready)
380         SmartScheduleStartTimer();
381
382     return nready;
383 }
384
385 /* If time has rewound, re-run every affected timer.
386  * Timers might drop out of the list, so we have to restart every time. */
387 static void
388 CheckAllTimers(void)
389 {
390     OsTimerPtr timer;
391     CARD32 now;
392
393     OsBlockSignals();
394  start:
395     now = GetTimeInMillis();
396
397     for (timer = timers; timer; timer = timer->next) {
398         if (timer->expires - now > timer->delta + 250) {
399             TimerForce(timer);
400             goto start;
401         }
402     }
403     OsReleaseSignals();
404 }
405
406 static void
407 DoTimer(OsTimerPtr timer, CARD32 now, OsTimerPtr *prev)
408 {
409     CARD32 newTime;
410
411     OsBlockSignals();
412     *prev = timer->next;
413     timer->next = NULL;
414     newTime = (*timer->callback) (timer, now, timer->arg);
415     if (newTime)
416         TimerSet(timer, 0, newTime, timer->callback, timer->arg);
417     OsReleaseSignals();
418 }
419
420 OsTimerPtr
421 TimerSet(OsTimerPtr timer, int flags, CARD32 millis,
422          OsTimerCallback func, pointer arg)
423 {
424     register OsTimerPtr *prev;
425     CARD32 now = GetTimeInMillis();
426
427     if (!timer) {
428         timer = malloc(sizeof(struct _OsTimerRec));
429         if (!timer)
430             return NULL;
431     }
432     else {
433         OsBlockSignals();
434         for (prev = &timers; *prev; prev = &(*prev)->next) {
435             if (*prev == timer) {
436                 *prev = timer->next;
437                 if (flags & TimerForceOld)
438                     (void) (*timer->callback) (timer, now, timer->arg);
439                 break;
440             }
441         }
442         OsReleaseSignals();
443     }
444     if (!millis)
445         return timer;
446     if (flags & TimerAbsolute) {
447         timer->delta = millis - now;
448     }
449     else {
450         timer->delta = millis;
451         millis += now;
452     }
453     timer->expires = millis;
454     timer->callback = func;
455     timer->arg = arg;
456     if ((int) (millis - now) <= 0) {
457         timer->next = NULL;
458         millis = (*timer->callback) (timer, now, timer->arg);
459         if (!millis)
460             return timer;
461     }
462     OsBlockSignals();
463     for (prev = &timers;
464          *prev && (int) ((*prev)->expires - millis) <= 0;
465          prev = &(*prev)->next);
466     timer->next = *prev;
467     *prev = timer;
468     OsReleaseSignals();
469     return timer;
470 }
471
472 Bool
473 TimerForce(OsTimerPtr timer)
474 {
475     int rc = FALSE;
476     OsTimerPtr *prev;
477
478     OsBlockSignals();
479     for (prev = &timers; *prev; prev = &(*prev)->next) {
480         if (*prev == timer) {
481             DoTimer(timer, GetTimeInMillis(), prev);
482             rc = TRUE;
483             break;
484         }
485     }
486     OsReleaseSignals();
487     return rc;
488 }
489
490 void
491 TimerCancel(OsTimerPtr timer)
492 {
493     OsTimerPtr *prev;
494
495     if (!timer)
496         return;
497     OsBlockSignals();
498     for (prev = &timers; *prev; prev = &(*prev)->next) {
499         if (*prev == timer) {
500             *prev = timer->next;
501             break;
502         }
503     }
504     OsReleaseSignals();
505 }
506
507 void
508 TimerFree(OsTimerPtr timer)
509 {
510     if (!timer)
511         return;
512     TimerCancel(timer);
513     free(timer);
514 }
515
516 void
517 TimerCheck(void)
518 {
519     CARD32 now = GetTimeInMillis();
520
521     while (timers && (int) (timers->expires - now) <= 0)
522         DoTimer(timers, now, &timers);
523 }
524
525 void
526 TimerInit(void)
527 {
528     OsTimerPtr timer;
529
530     while ((timer = timers)) {
531         timers = timer->next;
532         free(timer);
533     }
534 }
535
536 #ifdef DPMSExtension
537
538 #define DPMS_CHECK_MODE(mode,time)\
539     if (time > 0 && DPMSPowerLevel < mode && timeout >= time)\
540         DPMSSet(serverClient, mode);
541
542 #define DPMS_CHECK_TIMEOUT(time)\
543     if (time > 0 && (time - timeout) > 0)\
544         return time - timeout;
545
546 static CARD32
547 NextDPMSTimeout(INT32 timeout)
548 {
549     /*
550      * Return the amount of time remaining until we should set
551      * the next power level. Fallthroughs are intentional.
552      */
553     switch (DPMSPowerLevel) {
554     case DPMSModeOn:
555         DPMS_CHECK_TIMEOUT(DPMSStandbyTime)
556
557     case DPMSModeStandby:
558         DPMS_CHECK_TIMEOUT(DPMSSuspendTime)
559
560     case DPMSModeSuspend:
561         DPMS_CHECK_TIMEOUT(DPMSOffTime)
562
563     default:                   /* DPMSModeOff */
564         return 0;
565     }
566 }
567 #endif                          /* DPMSExtension */
568
569 static CARD32
570 ScreenSaverTimeoutExpire(OsTimerPtr timer, CARD32 now, pointer arg)
571 {
572     INT32 timeout = now - lastDeviceEventTime[XIAllDevices].milliseconds;
573     CARD32 nextTimeout = 0;
574
575 #ifdef DPMSExtension
576     /*
577      * Check each mode lowest to highest, since a lower mode can
578      * have the same timeout as a higher one.
579      */
580     if (DPMSEnabled) {
581         DPMS_CHECK_MODE(DPMSModeOff, DPMSOffTime)
582             DPMS_CHECK_MODE(DPMSModeSuspend, DPMSSuspendTime)
583             DPMS_CHECK_MODE(DPMSModeStandby, DPMSStandbyTime)
584
585             nextTimeout = NextDPMSTimeout(timeout);
586     }
587
588     /*
589      * Only do the screensaver checks if we're not in a DPMS
590      * power saving mode
591      */
592     if (DPMSPowerLevel != DPMSModeOn)
593         return nextTimeout;
594 #endif                          /* DPMSExtension */
595
596     if (!ScreenSaverTime)
597         return nextTimeout;
598
599     if (timeout < ScreenSaverTime) {
600         return nextTimeout > 0 ?
601             min(ScreenSaverTime - timeout, nextTimeout) :
602             ScreenSaverTime - timeout;
603     }
604
605     ResetOsBuffers();           /* not ideal, but better than nothing */
606     dixSaveScreens(serverClient, SCREEN_SAVER_ON, ScreenSaverActive);
607
608     if (ScreenSaverInterval > 0) {
609         nextTimeout = nextTimeout > 0 ?
610             min(ScreenSaverInterval, nextTimeout) : ScreenSaverInterval;
611     }
612
613     return nextTimeout;
614 }
615
616 static OsTimerPtr ScreenSaverTimer = NULL;
617
618 void
619 FreeScreenSaverTimer(void)
620 {
621     if (ScreenSaverTimer) {
622         TimerFree(ScreenSaverTimer);
623         ScreenSaverTimer = NULL;
624     }
625 }
626
627 void
628 SetScreenSaverTimer(void)
629 {
630     CARD32 timeout = 0;
631
632 #ifdef DPMSExtension
633     if (DPMSEnabled) {
634         /*
635          * A higher DPMS level has a timeout that's either less
636          * than or equal to that of a lower DPMS level.
637          */
638         if (DPMSStandbyTime > 0)
639             timeout = DPMSStandbyTime;
640
641         else if (DPMSSuspendTime > 0)
642             timeout = DPMSSuspendTime;
643
644         else if (DPMSOffTime > 0)
645             timeout = DPMSOffTime;
646     }
647 #endif
648
649     if (ScreenSaverTime > 0) {
650         timeout = timeout > 0 ? min(ScreenSaverTime, timeout) : ScreenSaverTime;
651     }
652
653 #ifdef SCREENSAVER
654     if (timeout && !screenSaverSuspended) {
655 #else
656     if (timeout) {
657 #endif
658         ScreenSaverTimer = TimerSet(ScreenSaverTimer, 0, timeout,
659                                     ScreenSaverTimeoutExpire, NULL);
660     }
661     else if (ScreenSaverTimer) {
662         FreeScreenSaverTimer();
663     }
664 }