]> git.ipfire.org Git - people/ms/strongswan.git/blame - src/libstrongswan/utils/utils.c
traffic-selector: Avoid out-of-bound array access when calculating range
[people/ms/strongswan.git] / src / libstrongswan / utils / utils.c
CommitLineData
552cc11b 1/*
b410d7f8 2 * Copyright (C) 2008-2015 Tobias Brunner
552cc11b 3 * Copyright (C) 2005-2008 Martin Willi
1b671669 4 * HSR Hochschule fuer Technik Rapperswil
552cc11b
MW
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
552cc11b
MW
15 */
16
4de7401a
MW
17#include "utils.h"
18
b410d7f8 19#include <sys/types.h>
6c20579a 20#include <unistd.h>
80e05dc8 21#include <limits.h>
b410d7f8 22#include <ctype.h>
ef4279f2 23#include <errno.h>
66c0801d
MW
24#ifndef WIN32
25# include <signal.h>
26#endif
552cc11b 27
b410d7f8 28#ifndef HAVE_CLOSEFROM
f25f4192
TB
29#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
30# include <sys/stat.h>
31# include <fcntl.h>
32# include <sys/syscall.h>
33/* This is from the kernel sources. We limit the length of directory names to
34 * 256 as we only use it to enumerate FDs. */
35struct linux_dirent64 {
b12c53ce 36 uint64_t d_ino;
f25f4192
TB
37 int64_t d_off;
38 unsigned short d_reclen;
39 unsigned char d_type;
40 char d_name[256];
41};
42#else /* !defined(__linux__) || !defined(HAVE_SYS_SYSCALL_H) */
b410d7f8 43# include <dirent.h>
f25f4192 44#endif /* defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) */
b410d7f8
TB
45#endif
46
f1c9653e 47#include <library.h>
f1c9653e 48#include <collections/enumerator.h>
552cc11b 49
b410d7f8
TB
50#define FD_DIR "/proc/self/fd"
51
66c0801d
MW
52#ifdef WIN32
53
80e05dc8
MW
54#include <threading/mutex.h>
55#include <threading/condvar.h>
56
66c0801d
MW
57/**
58 * Flag to indicate signaled wait_sigint()
59 */
60static bool sigint_signaled = FALSE;
61
62/**
63 * Condvar to wait in wait_sigint()
64 */
65static condvar_t *sigint_cond;
66
67/**
68 * Mutex to check signaling()
69 */
70static mutex_t *sigint_mutex;
71
72/**
73 * Control handler to catch ^C
74 */
cab59c73 75static BOOL WINAPI handler(DWORD dwCtrlType)
66c0801d
MW
76{
77 switch (dwCtrlType)
78 {
79 case CTRL_C_EVENT:
80 case CTRL_BREAK_EVENT:
81 case CTRL_CLOSE_EVENT:
82 sigint_mutex->lock(sigint_mutex);
83 sigint_signaled = TRUE;
84 sigint_cond->signal(sigint_cond);
85 sigint_mutex->unlock(sigint_mutex);
86 return TRUE;
87 default:
88 return FALSE;
89 }
90}
91
92/**
93 * Windows variant
94 */
95void wait_sigint()
96{
97 SetConsoleCtrlHandler(handler, TRUE);
98
99 sigint_mutex = mutex_create(MUTEX_TYPE_DEFAULT);
100 sigint_cond = condvar_create(CONDVAR_TYPE_DEFAULT);
101
102 sigint_mutex->lock(sigint_mutex);
103 while (!sigint_signaled)
104 {
105 sigint_cond->wait(sigint_cond, sigint_mutex);
106 }
107 sigint_mutex->unlock(sigint_mutex);
108
109 sigint_mutex->destroy(sigint_mutex);
110 sigint_cond->destroy(sigint_cond);
111}
112
113#else /* !WIN32 */
114
115/**
116 * Unix variant
117 */
118void wait_sigint()
119{
120 sigset_t set;
66c0801d
MW
121
122 sigemptyset(&set);
123 sigaddset(&set, SIGINT);
124 sigaddset(&set, SIGTERM);
125
126 sigprocmask(SIG_BLOCK, &set, NULL);
88b85e02
TB
127 while (sigwaitinfo(&set, NULL) == -1 && errno == EINTR)
128 {
129 /* wait for signal */
130 }
66c0801d
MW
131}
132
ef4279f2
TB
133#ifndef HAVE_SIGWAITINFO
134int sigwaitinfo(const sigset_t *set, void *info)
135{
136 int sig, err;
137
138 if (info)
139 { /* we don't replicate siginfo_t, fail if anybody tries to use it */
140 errno = EINVAL;
141 return -1;
142 }
143 err = sigwait(set, &sig);
144 if (err != 0)
145 {
146 errno = err;
147 sig = -1;
148 }
149 return sig;
150}
151#endif /* HAVE_SIGWAITINFO */
152#endif /* WIN32 */
66c0801d 153
9a8fdc15
TB
154#ifndef HAVE_CLOSEFROM
155/**
156 * Described in header.
157 */
b410d7f8 158void closefrom(int low_fd)
9a8fdc15 159{
f25f4192
TB
160 int max_fd, dir_fd, fd;
161
162 /* try to close only open file descriptors on Linux... */
163#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
164 /* By directly using a syscall we avoid any calls that might be unsafe after
165 * fork() (e.g. malloc()). */
166 char buffer[sizeof(struct linux_dirent64)];
167 struct linux_dirent64 *entry;
168 int offset, len;
169
170 dir_fd = open("/proc/self/fd", O_RDONLY);
171 if (dir_fd != -1)
172 {
5461efe7 173 while ((len = syscall(__NR_getdents64, dir_fd, buffer,
f25f4192
TB
174 sizeof(buffer))) > 0)
175 {
176 for (offset = 0; offset < len; offset += entry->d_reclen)
177 {
178 entry = (struct linux_dirent64*)(buffer + offset);
179 if (!isdigit(entry->d_name[0]))
180 {
181 continue;
182 }
183 fd = atoi(entry->d_name);
184 if (fd != dir_fd && fd >= low_fd)
185 {
186 close(fd);
187 }
188 }
189 }
190 close(dir_fd);
191 return;
192 }
193#else /* !defined(__linux__) || !defined(HAVE_SYS_SYSCALL_H) */
194 /* This is potentially unsafe when called after fork() in multi-threaded
195 * applications. In particular opendir() will require an allocation.
196 * Depends on how the malloc() implementation handles such situations. */
b410d7f8
TB
197 DIR *dir;
198 struct dirent *entry;
b410d7f8 199
6d9cd1d6
TB
200#ifndef HAVE_DIRFD
201 /* if we don't have dirfd() lets close the lowest FD and hope it gets reused
202 * by opendir() */
203 close(low_fd);
204 dir_fd = low_fd++;
205#endif
206
b410d7f8
TB
207 dir = opendir(FD_DIR);
208 if (dir)
5051bd23 209 {
6d9cd1d6 210#ifdef HAVE_DIRFD
b410d7f8 211 dir_fd = dirfd(dir);
6d9cd1d6 212#endif
b410d7f8 213 while ((entry = readdir(dir)))
5051bd23 214 {
b410d7f8
TB
215 if (!isdigit(entry->d_name[0]))
216 {
217 continue;
218 }
219 fd = atoi(entry->d_name);
220 if (fd != dir_fd && fd >= low_fd)
5051bd23 221 {
b410d7f8 222 close(fd);
5051bd23 223 }
5051bd23 224 }
b410d7f8
TB
225 closedir(dir);
226 return;
5051bd23 227 }
f25f4192 228#endif /* defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) */
5051bd23
TB
229
230 /* ...fall back to closing all fds otherwise */
d3c30b35 231#ifdef WIN32
b410d7f8 232 max_fd = _getmaxstdio();
d3c30b35 233#else
b410d7f8 234 max_fd = (int)sysconf(_SC_OPEN_MAX);
d3c30b35 235#endif
b410d7f8 236 if (max_fd < 0)
9a8fdc15 237 {
b410d7f8 238 max_fd = 256;
9a8fdc15 239 }
b410d7f8 240 for (fd = low_fd; fd < max_fd; fd++)
9a8fdc15
TB
241 {
242 close(fd);
243 }
244}
245#endif /* HAVE_CLOSEFROM */
246
081ae2eb
MW
247/**
248 * return null
249 */
250void *return_null()
251{
252 return NULL;
253}
254
da17b016
MW
255/**
256 * returns TRUE
257 */
258bool return_true()
259{
260 return TRUE;
261}
262
263/**
264 * returns FALSE
265 */
266bool return_false()
267{
268 return FALSE;
269}
270
233b853d
MW
271/**
272 * nop operation
273 */
274void nop()
275{
276}
277
f1c9653e
MW
278/**
279 * See header
280 */
281void utils_init()
282{
283#ifdef WIN32
284 windows_init();
285#endif
717313c5 286 atomics_init();
f1c9653e
MW
287 strerror_init();
288}
289
290/**
291 * See header
292 */
293void utils_deinit()
294{
295#ifdef WIN32
296 windows_deinit();
297#endif
717313c5 298 atomics_deinit();
f1c9653e
MW
299 strerror_deinit();
300}