Coverage Report

Created: 2024-02-29 06:05

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