Tue, 06 Jan 2015 21:39:09 +0100
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