netwerk/sctp/src/netinet/sctp_callout.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rwxr-xr-x

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /*-
     2  * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
     3  * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
     4  * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
     5  *
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions are met:
     8  *
     9  * a) Redistributions of source code must retain the above copyright notice,
    10  *    this list of conditions and the following disclaimer.
    11  *
    12  * b) Redistributions in binary form must reproduce the above copyright
    13  *    notice, this list of conditions and the following disclaimer in
    14  *    the documentation and/or other materials provided with the distribution.
    15  *
    16  * c) Neither the name of Cisco Systems, Inc. nor the names of its
    17  *    contributors may be used to endorse or promote products derived
    18  *    from this software without specific prior written permission.
    19  *
    20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
    22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
    30  * THE POSSIBILITY OF SUCH DAMAGE.
    31  */
    33 #if defined(__Userspace__)
    34 #include <sys/types.h>
    35 #if !defined (__Userspace_os_Windows)
    36 #include <sys/wait.h>
    37 #include <unistd.h>
    38 #include <pthread.h>
    39 #endif
    40 #if defined(__Userspace_os_NaCl)
    41 #include <sys/select.h>
    42 #endif
    43 #include <stdlib.h>
    44 #include <string.h>
    45 #include <stdio.h>
    46 #include <errno.h>
    47 #include <netinet/sctp_sysctl.h>
    48 #include <netinet/sctp_pcb.h>
    49 #else
    50 #include <netinet/sctp_os.h>
    51 #include <netinet/sctp_callout.h>
    52 #include <netinet/sctp_pcb.h>
    53 #endif
    55 /*
    56  * Callout/Timer routines for OS that doesn't have them
    57  */
    58 #if defined(__APPLE__) || defined(__Userspace__)
    59 int ticks = 0;
    60 #else
    61 extern int ticks;
    62 #endif
    64 /*
    65  * SCTP_TIMERQ_LOCK protects:
    66  * - SCTP_BASE_INFO(callqueue)
    67  * - sctp_os_timer_current: current timer in process
    68  * - sctp_os_timer_next: next timer to check
    69  */
    70 static sctp_os_timer_t *sctp_os_timer_current = NULL;
    71 static sctp_os_timer_t *sctp_os_timer_next = NULL;
    73 void
    74 sctp_os_timer_init(sctp_os_timer_t *c)
    75 {
    76 	bzero(c, sizeof(*c));
    77 }
    79 void
    80 sctp_os_timer_start(sctp_os_timer_t *c, int to_ticks, void (*ftn) (void *),
    81                     void *arg)
    82 {
    83 	/* paranoia */
    84 	if ((c == NULL) || (ftn == NULL))
    85 	    return;
    87 	SCTP_TIMERQ_LOCK();
    88 	/* check to see if we're rescheduling a timer */
    89 	if (c->c_flags & SCTP_CALLOUT_PENDING) {
    90 		if (c == sctp_os_timer_next) {
    91 			sctp_os_timer_next = TAILQ_NEXT(c, tqe);
    92 		}
    93 		TAILQ_REMOVE(&SCTP_BASE_INFO(callqueue), c, tqe);
    94 		/*
    95 		 * part of the normal "stop a pending callout" process
    96 		 * is to clear the CALLOUT_ACTIVE and CALLOUT_PENDING
    97 		 * flags.  We don't bother since we are setting these
    98 		 * below and we still hold the lock.
    99 		 */
   100 	}
   102 	/*
   103 	 * We could unlock/splx here and lock/spl at the TAILQ_INSERT_TAIL,
   104 	 * but there's no point since doing this setup doesn't take much time.
   105 	 */
   106 	if (to_ticks <= 0)
   107 		to_ticks = 1;
   109 	c->c_arg = arg;
   110 	c->c_flags = (SCTP_CALLOUT_ACTIVE | SCTP_CALLOUT_PENDING);
   111 	c->c_func = ftn;
   112 	c->c_time = ticks + to_ticks;
   113 	TAILQ_INSERT_TAIL(&SCTP_BASE_INFO(callqueue), c, tqe);
   114 	SCTP_TIMERQ_UNLOCK();
   115 }
   117 int
   118 sctp_os_timer_stop(sctp_os_timer_t *c)
   119 {
   120 	SCTP_TIMERQ_LOCK();
   121 	/*
   122 	 * Don't attempt to delete a callout that's not on the queue.
   123 	 */
   124 	if (!(c->c_flags & SCTP_CALLOUT_PENDING)) {
   125 		c->c_flags &= ~SCTP_CALLOUT_ACTIVE;
   126 		SCTP_TIMERQ_UNLOCK();
   127 		return (0);
   128 	}
   129 	c->c_flags &= ~(SCTP_CALLOUT_ACTIVE | SCTP_CALLOUT_PENDING);
   130 	if (c == sctp_os_timer_next) {
   131 		sctp_os_timer_next = TAILQ_NEXT(c, tqe);
   132 	}
   133 	TAILQ_REMOVE(&SCTP_BASE_INFO(callqueue), c, tqe);
   134 	SCTP_TIMERQ_UNLOCK();
   135 	return (1);
   136 }
   138 static void
   139 sctp_handle_tick(int delta)
   140 {
   141 	sctp_os_timer_t *c;
   142 	void (*c_func)(void *);
   143 	void *c_arg;
   145 	SCTP_TIMERQ_LOCK();
   146 	/* update our tick count */
   147 	ticks += delta;
   148 	c = TAILQ_FIRST(&SCTP_BASE_INFO(callqueue));
   149 	while (c) {
   150 		if (c->c_time <= ticks) {
   151 			sctp_os_timer_next = TAILQ_NEXT(c, tqe);
   152 			TAILQ_REMOVE(&SCTP_BASE_INFO(callqueue), c, tqe);
   153 			c_func = c->c_func;
   154 			c_arg = c->c_arg;
   155 			c->c_flags &= ~SCTP_CALLOUT_PENDING;
   156 			sctp_os_timer_current = c;
   157 			SCTP_TIMERQ_UNLOCK();
   158 			c_func(c_arg);
   159 			SCTP_TIMERQ_LOCK();
   160 			sctp_os_timer_current = NULL;
   161 			c = sctp_os_timer_next;
   162 		} else {
   163 			c = TAILQ_NEXT(c, tqe);
   164 		}
   165 	}
   166 	sctp_os_timer_next = NULL;
   167 	SCTP_TIMERQ_UNLOCK();
   168 }
   170 #if defined(__APPLE__)
   171 void
   172 sctp_timeout(void *arg SCTP_UNUSED)
   173 {
   174 	sctp_handle_tick(SCTP_BASE_VAR(sctp_main_timer_ticks));
   175 	sctp_start_main_timer();
   176 }
   177 #endif
   179 #if defined(__Userspace__)
   180 #define TIMEOUT_INTERVAL 10
   182 void *
   183 user_sctp_timer_iterate(void *arg)
   184 {
   185 	for (;;) {
   186 #if defined (__Userspace_os_Windows)
   187 		Sleep(TIMEOUT_INTERVAL);
   188 #else
   189 		struct timeval timeout;
   191 		timeout.tv_sec  = 0;
   192 		timeout.tv_usec = 1000 * TIMEOUT_INTERVAL;
   193 		select(0, NULL, NULL, NULL, &timeout);
   194 #endif
   195 		if (SCTP_BASE_VAR(timer_thread_should_exit)) {
   196 			break;
   197 		}
   198 		sctp_handle_tick(MSEC_TO_TICKS(TIMEOUT_INTERVAL));
   199 	}
   200 	return (NULL);
   201 }
   203 void
   204 sctp_start_timer(void)
   205 {
   206 	/*
   207 	 * No need to do SCTP_TIMERQ_LOCK_INIT();
   208 	 * here, it is being done in sctp_pcb_init()
   209 	 */
   210 #if defined (__Userspace_os_Windows)
   211 	if ((SCTP_BASE_VAR(timer_thread) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)user_sctp_timer_iterate, NULL, 0, NULL)) == NULL) {
   212 		SCTP_PRINTF("ERROR; Creating ithread failed\n");
   213 	}
   214 #else
   215 	int rc;
   217 	rc = pthread_create(&SCTP_BASE_VAR(timer_thread), NULL, user_sctp_timer_iterate, NULL);
   218 	if (rc) {
   219 		SCTP_PRINTF("ERROR; return code from pthread_create() is %d\n", rc);
   220 	}
   221 #endif
   222 }
   224 #endif

mercurial