mirror of
https://github.com/aljazceru/lightning.git
synced 2026-02-02 04:34:20 +01:00
ccan: update to include closefrom
Signed-off-by: ZmnSCPxj jxPCSnmZ <ZmnSCPxj@protonmail.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
committed by
Christian Decker
parent
ed6eaf9171
commit
5a84abb09e
4
Makefile
4
Makefile
@@ -96,6 +96,7 @@ CCAN_OBJS := \
|
||||
ccan-bitmap.o \
|
||||
ccan-bitops.o \
|
||||
ccan-breakpoint.o \
|
||||
ccan-closefrom.o \
|
||||
ccan-crc32c.o \
|
||||
ccan-crypto-hmac.o \
|
||||
ccan-crypto-hkdf.o \
|
||||
@@ -154,6 +155,7 @@ CCAN_HEADERS := \
|
||||
$(CCANDIR)/ccan/cast/cast.h \
|
||||
$(CCANDIR)/ccan/cdump/cdump.h \
|
||||
$(CCANDIR)/ccan/check_type/check_type.h \
|
||||
$(CCANDIR)/ccan/closefrom/closefrom.h \
|
||||
$(CCANDIR)/ccan/compiler/compiler.h \
|
||||
$(CCANDIR)/ccan/container_of/container_of.h \
|
||||
$(CCANDIR)/ccan/cppmagic/cppmagic.h \
|
||||
@@ -857,3 +859,5 @@ ccan-json_escape.o: $(CCANDIR)/ccan/json_escape/json_escape.c
|
||||
@$(call VERBOSE, "cc $<", $(CC) $(CFLAGS) -c -o $@ $<)
|
||||
ccan-json_out.o: $(CCANDIR)/ccan/json_out/json_out.c
|
||||
@$(call VERBOSE, "cc $<", $(CC) $(CFLAGS) -c -o $@ $<)
|
||||
ccan-closefrom.o: $(CCANDIR)/ccan/closefrom/closefrom.c
|
||||
@$(call VERBOSE, "cc $<", $(CC) $(CFLAGS) -c -o $@ $<)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
CCAN imported from http://ccodearchive.net.
|
||||
|
||||
CCAN version: init-2507-g05ec8351
|
||||
CCAN version: init-2519-gcc888f28
|
||||
|
||||
1
ccan/ccan/closefrom/LICENSE
Symbolic link
1
ccan/ccan/closefrom/LICENSE
Symbolic link
@@ -0,0 +1 @@
|
||||
../../licenses/CC0
|
||||
69
ccan/ccan/closefrom/_info
Normal file
69
ccan/ccan/closefrom/_info
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "config.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* closefrom - close all fds starting from specified fd.
|
||||
*
|
||||
* This code is an example of what to do in a child process to
|
||||
* ensure that none of the (possibly sensitive) file descriptors
|
||||
* in the parent remain in the child process.
|
||||
*
|
||||
* License: CC0 (Public domain)
|
||||
* Author: ZmnSCPxj jxPCSnmZ <ZmnSCPxj@protonmail.com>
|
||||
*
|
||||
* Example:
|
||||
* #include <ccan/closefrom/closefrom.h>
|
||||
* #include <ccan/err/err.h>
|
||||
* #include <stdio.h>
|
||||
* #include <sys/resource.h>
|
||||
* #include <sys/time.h>
|
||||
* #include <sys/types.h>
|
||||
* #include <sys/wait.h>
|
||||
* #include <unistd.h>
|
||||
*
|
||||
* int main(int argc, char **argv)
|
||||
* {
|
||||
* pid_t child;
|
||||
*
|
||||
* // If being emulated, then we might end up
|
||||
* // looping over a large _SC_OPEN_MAX
|
||||
* // (Some systems have it as INT_MAX!)
|
||||
* // If so, closefrom_limit will lower this limit
|
||||
* // to a value you specify, or if given 0 will
|
||||
* // limit to 4096.
|
||||
* // Call this as early as possible.
|
||||
* closefrom_limit(0);
|
||||
*
|
||||
* // If we limited, we can query this so we can
|
||||
* // print it in debug logs or something.
|
||||
* if (closefrom_may_be_slow())
|
||||
* printf("we limited ourselves to 4096 fds.\n");
|
||||
*
|
||||
* child = fork();
|
||||
* if (child < 0)
|
||||
* err(1, "Forking");
|
||||
* if (child == 0) {
|
||||
* closefrom(STDERR_FILENO + 1);
|
||||
* // Insert your *whatever* code here.
|
||||
* _exit(0);
|
||||
* }
|
||||
*
|
||||
* waitpid(child, NULL, 0);
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* Expect exactly one argument */
|
||||
if (argc != 2)
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
225
ccan/ccan/closefrom/closefrom.c
Normal file
225
ccan/ccan/closefrom/closefrom.c
Normal file
@@ -0,0 +1,225 @@
|
||||
/* CC0 license (public domain) - see LICENSE file for details */
|
||||
#include <ccan/closefrom/closefrom.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* See also:
|
||||
* https://stackoverflow.com/a/918469
|
||||
*
|
||||
* The implementation below is not exhaustive of all the suggested above.
|
||||
*/
|
||||
|
||||
#if !HAVE_CLOSEFROM
|
||||
|
||||
/* IBM AIX.
|
||||
* https://www.ibm.com/docs/en/aix/7.2?topic=f-fcntl-dup-dup2-subroutine
|
||||
*/
|
||||
#if HAVE_F_CLOSEM
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
void closefrom(int fromfd)
|
||||
{
|
||||
(void) fcntl(fromfd, F_CLOSEM, 0);
|
||||
}
|
||||
|
||||
bool closefrom_may_be_slow(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#else /* !HAVE_F_CLOSEM */
|
||||
|
||||
#if HAVE_NR_CLOSE_RANGE
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
#define PROC_PID_FD_LEN \
|
||||
( 6 /* /proc/ */ \
|
||||
+ 20 /* 64-bit $PID */ \
|
||||
+ 3 /* /fd */ \
|
||||
+ 1 /* NUL */ \
|
||||
)
|
||||
|
||||
static bool can_get_maxfd(void)
|
||||
{
|
||||
#if HAVE_F_MAXFD
|
||||
int res = fcntl(0, F_MAXFD);
|
||||
if (res < 0)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Linux >= 5.9 */
|
||||
static bool can_close_range(void)
|
||||
{
|
||||
#if HAVE_NR_CLOSE_RANGE
|
||||
int res = syscall(__NR_close_range, INT_MAX, INT_MAX, 0);
|
||||
if (res < 0)
|
||||
return false;
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* On Linux, Solaris, AIX, Cygwin, and NetBSD. */
|
||||
static bool can_open_proc_pid_fd(void)
|
||||
{
|
||||
char dnam[PROC_PID_FD_LEN];
|
||||
DIR *dir;
|
||||
|
||||
sprintf(dnam, "/proc/%ld/fd", (long) getpid());
|
||||
dir = opendir(dnam);
|
||||
if (!dir)
|
||||
return false;
|
||||
closedir(dir);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* On FreeBSD and MacOS. */
|
||||
static bool can_open_dev_fd(void)
|
||||
{
|
||||
DIR *dir;
|
||||
dir = opendir("/dev/fd");
|
||||
if (!dir)
|
||||
return false;
|
||||
closedir(dir);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool closefrom_may_be_slow(void)
|
||||
{
|
||||
if (can_get_maxfd())
|
||||
return false;
|
||||
else if (can_close_range())
|
||||
return false;
|
||||
else if (can_open_proc_pid_fd())
|
||||
return false;
|
||||
else if (can_open_dev_fd())
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/* It is possible that we run out of available file descriptors.
|
||||
* However, if we are going to close anyway, we could just try
|
||||
* closing file descriptors until we reach maxfd.
|
||||
*/
|
||||
static
|
||||
DIR *try_opendir(const char *dnam, int *fromfd, int maxfd)
|
||||
{
|
||||
DIR *dir;
|
||||
|
||||
do {
|
||||
dir = opendir(dnam);
|
||||
if (!dir && (errno == ENFILE || errno == EMFILE)) {
|
||||
if (*fromfd < maxfd)
|
||||
close((*fromfd)++);
|
||||
else
|
||||
break;
|
||||
}
|
||||
} while (!dir && (errno == ENFILE || errno == EMFILE));
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
void closefrom(int fromfd)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
|
||||
int res;
|
||||
int maxfd;
|
||||
|
||||
char dnam[PROC_PID_FD_LEN];
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
|
||||
(void) res;
|
||||
|
||||
if (fromfd < 0)
|
||||
goto quit;
|
||||
|
||||
#if HAVE_NR_CLOSE_RANGE
|
||||
res = syscall(__NR_close_range, fromfd, INT_MAX, 0);
|
||||
if (res == 0)
|
||||
goto quit;
|
||||
#endif
|
||||
|
||||
maxfd = sysconf(_SC_OPEN_MAX);
|
||||
|
||||
sprintf(dnam, "/proc/%ld/fd", (long) getpid());
|
||||
dir = try_opendir(dnam, &fromfd, maxfd);
|
||||
if (!dir)
|
||||
dir = try_opendir("/dev/fd", &fromfd, maxfd);
|
||||
|
||||
if (dir) {
|
||||
while ((entry = readdir(dir))) {
|
||||
long fd;
|
||||
char *endp;
|
||||
|
||||
fd = strtol(entry->d_name, &endp, 10);
|
||||
if (entry->d_name != endp && *endp == '\0' &&
|
||||
fd >= 0 && fd < INT_MAX && fd >= fromfd &&
|
||||
fd != dirfd(dir) )
|
||||
close(fd);
|
||||
}
|
||||
closedir(dir);
|
||||
goto quit;
|
||||
}
|
||||
|
||||
#if HAVE_F_MAXFD
|
||||
res = fcntl(0, F_MAXFD);
|
||||
if (res >= 0)
|
||||
maxfd = res + 1;
|
||||
#endif
|
||||
|
||||
/* Fallback. */
|
||||
for (; fromfd < maxfd; ++fromfd)
|
||||
close(fromfd);
|
||||
|
||||
quit:
|
||||
errno = saved_errno;
|
||||
}
|
||||
|
||||
#endif /* !HAVE_F_CLOSEM */
|
||||
|
||||
void closefrom_limit(unsigned int arg_limit)
|
||||
{
|
||||
rlim_t limit = (rlim_t) arg_limit;
|
||||
|
||||
struct rlimit nofile;
|
||||
|
||||
if (!closefrom_may_be_slow())
|
||||
return;
|
||||
|
||||
if (limit == 0)
|
||||
limit = 4096;
|
||||
|
||||
getrlimit(RLIMIT_NOFILE, &nofile);
|
||||
|
||||
/* Respect the max limit.
|
||||
* If we are not running as root then we cannot raise
|
||||
* it, but we *can* lower the max limit.
|
||||
*/
|
||||
if (nofile.rlim_max != RLIM_INFINITY && limit > nofile.rlim_max)
|
||||
limit = nofile.rlim_max;
|
||||
|
||||
nofile.rlim_cur = limit;
|
||||
nofile.rlim_max = limit;
|
||||
|
||||
setrlimit(RLIMIT_NOFILE, &nofile);
|
||||
}
|
||||
|
||||
#endif /* !HAVE_CLOSEFROM */
|
||||
81
ccan/ccan/closefrom/closefrom.h
Normal file
81
ccan/ccan/closefrom/closefrom.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/* CC0 license (public domain) - see LICENSE file for details */
|
||||
#ifndef CCAN_CLOSEFROM_H
|
||||
#define CCAN_CLOSEFROM_H
|
||||
#include "config.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#if HAVE_CLOSEFROM
|
||||
/* BSD. */
|
||||
#include <unistd.h>
|
||||
/* Solaris. */
|
||||
#include <stdlib.h>
|
||||
|
||||
static inline
|
||||
bool closefrom_may_be_slow(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
void closefrom_limit(unsigned int limit)
|
||||
{
|
||||
}
|
||||
|
||||
#else /* !HAVE_CLOSEFROM */
|
||||
|
||||
/**
|
||||
* closefrom - Close all open file descriptors, starting
|
||||
* at fromfd onwards.
|
||||
* @fromfd: the first fd to close; it and all higher file descriptors
|
||||
* will be closed.
|
||||
*
|
||||
* This is not multithread-safe: other threads in the same process
|
||||
* may or may not open new file descriptors in parallel to this call.
|
||||
* However, the expected use-case is that this will be called in a
|
||||
* child process just after fork(), meaning the child process is still
|
||||
* single-threaded.
|
||||
*/
|
||||
void closefrom_(int fromfd);
|
||||
/* In case the standard library has it, but declared in some
|
||||
* *other* header we do not know of yet, we use closefrom_ in
|
||||
* the actual name the linker sees.
|
||||
*/
|
||||
#define closefrom closefrom_
|
||||
|
||||
/**
|
||||
* closefrom_may_be_slow - check if the closefrom() function could
|
||||
* potentially take a long time.
|
||||
*
|
||||
* The return value is true if closefrom() is emulated by
|
||||
* looping from fromfd to sysconf(_SC_OPEN_MAX), which can be
|
||||
* very large (possibly even INT_MAX on some systems).
|
||||
* If so, you might want to use setrlimit to limit _SC_OPEN_MAX.
|
||||
* If this returns false, then closefrom is efficient and you do not
|
||||
* need to limit the number of file descriptors.
|
||||
*
|
||||
* You can use closefrom_limit to perform the limiting based on
|
||||
* closefrom_may_be_slow.
|
||||
* This API is exposed in case you want to output to debug logs or
|
||||
* something similar.
|
||||
*/
|
||||
bool closefrom_may_be_slow(void);
|
||||
|
||||
/**
|
||||
* closefrom_limit - If closefrom_may_be_slow(), lower the limit on
|
||||
* the number of file descriptors we keep open, to prevent closefrom
|
||||
* from being *too* slow.
|
||||
* @limit: 0 to use a reasonable default of 4096, or non-zero for the
|
||||
* limit you prefer.
|
||||
*
|
||||
* This function does nothing if closefrom_may_be_slow() return false.
|
||||
*
|
||||
* This function only *lowers* the limit from the hard limit set by
|
||||
* root before running this program.
|
||||
* If the limit is higher than the hard limit, then the hard limit is
|
||||
* respected.
|
||||
*/
|
||||
void closefrom_limit(unsigned int limit);
|
||||
|
||||
#endif /* !HAVE_CLOSEFROM */
|
||||
|
||||
#endif /* CCAN_CLOSEFROM_H */
|
||||
192
ccan/ccan/closefrom/test/run.c
Normal file
192
ccan/ccan/closefrom/test/run.c
Normal file
@@ -0,0 +1,192 @@
|
||||
#include <ccan/closefrom/closefrom.h>
|
||||
/* Include the C files directly. */
|
||||
#include <ccan/closefrom/closefrom.c>
|
||||
#include <ccan/tap/tap.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Open a pipe, do closefrom, check pipe no longer works. */
|
||||
static
|
||||
int pipe_close(void)
|
||||
{
|
||||
int fds[2];
|
||||
ssize_t wres;
|
||||
|
||||
char buf = '\0';
|
||||
|
||||
if (pipe(fds) < 0)
|
||||
return 0;
|
||||
|
||||
/* Writing to the write end should succeed, the
|
||||
* pipe is working. */
|
||||
do {
|
||||
wres = write(fds[1], &buf, 1);
|
||||
} while ((wres < 0) && (errno == EINTR));
|
||||
if (wres < 0)
|
||||
return 0;
|
||||
|
||||
closefrom(STDERR_FILENO + 1);
|
||||
|
||||
/* Writing to the write end should fail because
|
||||
* everything should be closed. */
|
||||
do {
|
||||
wres = write(fds[1], &buf, 1);
|
||||
} while ((wres < 0) && (errno == EINTR));
|
||||
|
||||
return (wres < 0) && (errno == EBADF);
|
||||
}
|
||||
|
||||
/* Open a pipe, fork, do closefrom in child, read pipe from parent,
|
||||
* parent should see EOF.
|
||||
*/
|
||||
static
|
||||
int fork_close(void)
|
||||
{
|
||||
int fds[2];
|
||||
pid_t child;
|
||||
|
||||
char buf;
|
||||
ssize_t rres;
|
||||
|
||||
if (pipe(fds) < 0)
|
||||
return 0;
|
||||
|
||||
child = fork();
|
||||
if (child < 0)
|
||||
return 0;
|
||||
|
||||
if (child == 0) {
|
||||
/* Child. */
|
||||
closefrom(STDERR_FILENO + 1);
|
||||
_exit(0);
|
||||
} else {
|
||||
/* Parent. */
|
||||
|
||||
/* Close write end of pipe. */
|
||||
close(fds[1]);
|
||||
|
||||
do {
|
||||
rres = read(fds[0], &buf, 1);
|
||||
} while ((rres < 0) && (errno == EINTR));
|
||||
|
||||
/* Should have seen EOF. */
|
||||
if (rres != 0)
|
||||
return 0;
|
||||
|
||||
/* Clean up. */
|
||||
waitpid(child, NULL, 0);
|
||||
closefrom(STDERR_FILENO + 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/* Open a pipe, fork, in child set the write end to fd #3,
|
||||
* in parent set the read end to fd #3, send a byte from
|
||||
* child to parent, check.
|
||||
*/
|
||||
static
|
||||
int fork_communicate(void)
|
||||
{
|
||||
int fds[2];
|
||||
pid_t child;
|
||||
|
||||
char wbuf = 42;
|
||||
char rbuf;
|
||||
ssize_t rres;
|
||||
ssize_t wres;
|
||||
|
||||
int status;
|
||||
|
||||
if (pipe(fds) < 0)
|
||||
return 0;
|
||||
|
||||
child = fork();
|
||||
if (child < 0)
|
||||
return 0;
|
||||
|
||||
if (child == 0) {
|
||||
/* Child. */
|
||||
|
||||
/* Move write end to fd #3. */
|
||||
if (fds[1] != 3) {
|
||||
if (dup2(fds[1], 3) < 0)
|
||||
_exit(127);
|
||||
close(fds[1]);
|
||||
fds[1] = 3;
|
||||
}
|
||||
|
||||
closefrom(4);
|
||||
|
||||
do {
|
||||
wres = write(fds[1], &wbuf, 1);
|
||||
} while ((wres < 0) && (errno == EINTR));
|
||||
if (wres < 0)
|
||||
_exit(127);
|
||||
|
||||
_exit(0);
|
||||
} else {
|
||||
/* Parent. */
|
||||
|
||||
/* Move read end to fd #3. */
|
||||
if (fds[0] != 3) {
|
||||
if (dup2(fds[0], 3) < 0)
|
||||
return 0;
|
||||
close(fds[0]);
|
||||
fds[0] = 3;
|
||||
}
|
||||
|
||||
closefrom(4);
|
||||
|
||||
/* Wait for child to finish. */
|
||||
waitpid(child, &status, 0);
|
||||
if (!WIFEXITED(status))
|
||||
return 0;
|
||||
if (WEXITSTATUS(status) != 0)
|
||||
return 0;
|
||||
|
||||
/* Read 1 byte. */
|
||||
do {
|
||||
rres = read(fds[0], &rbuf, 1);
|
||||
} while ((rres < 0) && (errno == EINTR));
|
||||
if (rres < 0)
|
||||
return 0;
|
||||
if (rres != 1)
|
||||
return 0;
|
||||
/* Should get same byte as what was sent. */
|
||||
if (rbuf != wbuf)
|
||||
return 0;
|
||||
|
||||
/* Next attempt to read should EOF. */
|
||||
do {
|
||||
rres = read(fds[0], &rbuf, 1);
|
||||
} while ((rres < 0) && (errno == EINTR));
|
||||
if (rres < 0)
|
||||
return 0;
|
||||
/* Should EOF. */
|
||||
if (rres != 0)
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* Clean up. */
|
||||
close(fds[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* Limit closefrom. */
|
||||
closefrom_limit(0);
|
||||
|
||||
/* This is how many tests you plan to run */
|
||||
plan_tests(3);
|
||||
|
||||
ok1(pipe_close());
|
||||
ok1(fork_close());
|
||||
ok1(fork_communicate());
|
||||
|
||||
/* This exits depending on whether all tests passed */
|
||||
return exit_status();
|
||||
}
|
||||
@@ -72,7 +72,8 @@ static inline uint32_t gf2_matrix_times(uint32_t *mat, uint32_t vec) {
|
||||
/* Multiply a matrix by itself over GF(2). Both mat and square must have 32
|
||||
rows. */
|
||||
static inline void gf2_matrix_square(uint32_t *square, uint32_t *mat) {
|
||||
for (unsigned n = 0; n < 32; n++)
|
||||
unsigned n;
|
||||
for (n = 0; n < 32; n++)
|
||||
square[n] = gf2_matrix_times(mat, mat[n]);
|
||||
}
|
||||
|
||||
@@ -87,7 +88,8 @@ static void crc32c_zeros_op(uint32_t *even, size_t len) {
|
||||
/* put operator for one zero bit in odd */
|
||||
odd[0] = POLY; /* CRC-32C polynomial */
|
||||
uint32_t row = 1;
|
||||
for (unsigned n = 1; n < 32; n++) {
|
||||
unsigned n;
|
||||
for (n = 1; n < 32; n++) {
|
||||
odd[n] = row;
|
||||
row <<= 1;
|
||||
}
|
||||
@@ -111,7 +113,7 @@ static void crc32c_zeros_op(uint32_t *even, size_t len) {
|
||||
} while (len);
|
||||
|
||||
/* answer ended up in odd -- copy to even */
|
||||
for (unsigned n = 0; n < 32; n++)
|
||||
for (n = 0; n < 32; n++)
|
||||
even[n] = odd[n];
|
||||
}
|
||||
|
||||
@@ -121,7 +123,8 @@ static void crc32c_zeros(uint32_t zeros[][256], size_t len) {
|
||||
uint32_t op[32];
|
||||
|
||||
crc32c_zeros_op(op, len);
|
||||
for (unsigned n = 0; n < 256; n++) {
|
||||
unsigned n;
|
||||
for (n = 0; n < 256; n++) {
|
||||
zeros[0][n] = gf2_matrix_times(op, n);
|
||||
zeros[1][n] = gf2_matrix_times(op, n << 8);
|
||||
zeros[2][n] = gf2_matrix_times(op, n << 16);
|
||||
@@ -265,7 +268,8 @@ uint32_t crc32c(uint32_t crc, void const *buf, size_t len) {
|
||||
static bool crc32c_once_little;
|
||||
static uint32_t crc32c_table_little[8][256];
|
||||
static void crc32c_init_sw_little(void) {
|
||||
for (unsigned n = 0; n < 256; n++) {
|
||||
unsigned n;
|
||||
for (n = 0; n < 256; n++) {
|
||||
uint32_t crc = n;
|
||||
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
|
||||
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
|
||||
@@ -277,9 +281,10 @@ static void crc32c_init_sw_little(void) {
|
||||
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
|
||||
crc32c_table_little[0][n] = crc;
|
||||
}
|
||||
for (unsigned n = 0; n < 256; n++) {
|
||||
for (n = 0; n < 256; n++) {
|
||||
uint32_t crc = crc32c_table_little[0][n];
|
||||
for (unsigned k = 1; k < 8; k++) {
|
||||
unsigned k;
|
||||
for (k = 1; k < 8; k++) {
|
||||
crc = crc32c_table_little[0][crc & 0xff] ^ (crc >> 8);
|
||||
crc32c_table_little[k][n] = crc;
|
||||
}
|
||||
@@ -340,7 +345,8 @@ static bool crc32c_once_big;
|
||||
static uint32_t crc32c_table_big_byte[256];
|
||||
static uint64_t crc32c_table_big[8][256];
|
||||
static void crc32c_init_sw_big(void) {
|
||||
for (unsigned n = 0; n < 256; n++) {
|
||||
unsigned n;
|
||||
for (n = 0; n < 256; n++) {
|
||||
uint32_t crc = n;
|
||||
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
|
||||
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
|
||||
@@ -352,10 +358,11 @@ static void crc32c_init_sw_big(void) {
|
||||
crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
|
||||
crc32c_table_big_byte[n] = crc;
|
||||
}
|
||||
for (unsigned n = 0; n < 256; n++) {
|
||||
for (n = 0; n < 256; n++) {
|
||||
uint32_t crc = crc32c_table_big_byte[n];
|
||||
crc32c_table_big[0][n] = swap(crc);
|
||||
for (unsigned k = 1; k < 8; k++) {
|
||||
unsigned k;
|
||||
for (k = 1; k < 8; k++) {
|
||||
crc = crc32c_table_big_byte[crc & 0xff] ^ (crc >> 8);
|
||||
crc32c_table_big[k][n] = swap(crc);
|
||||
}
|
||||
|
||||
@@ -121,7 +121,9 @@ bool add_listener(struct io_listener *l)
|
||||
|
||||
static int find_always(const struct io_plan *plan)
|
||||
{
|
||||
for (size_t i = 0; i < num_always; i++)
|
||||
size_t i = 0;
|
||||
|
||||
for (i = 0; i < num_always; i++)
|
||||
if (always[i] == plan)
|
||||
return i;
|
||||
return -1;
|
||||
@@ -287,8 +289,10 @@ static bool *exclusive(struct io_plan *plan)
|
||||
/* For simplicity, we do one always at a time */
|
||||
static bool handle_always(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Backwards is simple easier to remove entries */
|
||||
for (int i = num_always - 1; i >= 0; i--) {
|
||||
for (i = num_always - 1; i >= 0; i--) {
|
||||
struct io_plan *plan = always[i];
|
||||
|
||||
if (num_exclusive && !*exclusive(plan))
|
||||
@@ -323,10 +327,12 @@ bool backend_set_exclusive(struct io_plan *plan, bool excl)
|
||||
* else that we manipulate events. */
|
||||
static void exclude_pollfds(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (num_exclusive == 0)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < num_fds; i++) {
|
||||
for (i = 0; i < num_fds; i++) {
|
||||
struct pollfd *pfd = &pollfds[fds[i]->backend_info];
|
||||
|
||||
if (!fds[i]->exclusive[IO_IN])
|
||||
@@ -343,10 +349,12 @@ static void exclude_pollfds(void)
|
||||
|
||||
static void restore_pollfds(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (num_exclusive == 0)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < num_fds; i++) {
|
||||
for (i = 0; i < num_fds; i++) {
|
||||
struct pollfd *pfd = &pollfds[fds[i]->backend_info];
|
||||
|
||||
if (fds[i]->listener) {
|
||||
|
||||
@@ -21,7 +21,8 @@ bool json_escape_eq(const struct json_escape *a, const struct json_escape *b)
|
||||
|
||||
bool json_escape_needed(const char *str, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
size_t i;
|
||||
for (i = 0; i < len; i++) {
|
||||
if ((unsigned)str[i] < ' '
|
||||
|| str[i] == 127
|
||||
|| str[i] == '"'
|
||||
|
||||
@@ -51,6 +51,7 @@ int main(int argc, char *argv[])
|
||||
return 1;
|
||||
|
||||
if (strcmp(argv[1], "depends") == 0) {
|
||||
printf("ccan/closefrom\n");
|
||||
printf("ccan/noerr\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* CC0 license (public domain) - see LICENSE file for details */
|
||||
#include <ccan/closefrom/closefrom.h>
|
||||
#include <ccan/pipecmd/pipecmd.h>
|
||||
#include <ccan/noerr/noerr.h>
|
||||
#include <stdlib.h>
|
||||
@@ -115,7 +116,8 @@ pid_t pipecmdarr(int *fd_tochild, int *fd_fromchild, int *fd_errfromchild,
|
||||
goto fail;
|
||||
|
||||
if (childpid == 0) {
|
||||
for (int i = 0; i < num_child_close; i++)
|
||||
int i;
|
||||
for (i = 0; i < num_child_close; i++)
|
||||
close(child_close[i]);
|
||||
|
||||
// Child runs command.
|
||||
@@ -138,11 +140,21 @@ pid_t pipecmdarr(int *fd_tochild, int *fd_fromchild, int *fd_errfromchild,
|
||||
close(errfromchild[1]);
|
||||
}
|
||||
|
||||
/* Map execfail[1] to fd 3. */
|
||||
if (execfail[1] != 3) {
|
||||
if (dup2(execfail[1], 3) == -1)
|
||||
goto child_errno_fail;
|
||||
/* CLOEXEC is not shared by dup2, so copy the flags
|
||||
* from execfail[1] to 3.
|
||||
*/
|
||||
if (fcntl(3, F_SETFD, fcntl(execfail[1], F_GETFD)) < 0)
|
||||
goto child_errno_fail;
|
||||
close(execfail[1]);
|
||||
execfail[1] = 3;
|
||||
}
|
||||
|
||||
/* Make (fairly!) sure all other fds are closed. */
|
||||
int max = sysconf(_SC_OPEN_MAX);
|
||||
for (int i = 3; i < max; i++)
|
||||
if (i != execfail[1])
|
||||
close(i);
|
||||
closefrom(4);
|
||||
|
||||
execvp(arr[0], arr);
|
||||
|
||||
@@ -155,7 +167,8 @@ pid_t pipecmdarr(int *fd_tochild, int *fd_fromchild, int *fd_errfromchild,
|
||||
exit(127);
|
||||
}
|
||||
|
||||
for (int i = 0; i < num_par_close; i++)
|
||||
int i;
|
||||
for (i = 0; i < num_par_close; i++)
|
||||
close(par_close[i]);
|
||||
|
||||
/* Child will close this without writing on successful exec. */
|
||||
@@ -175,7 +188,7 @@ pid_t pipecmdarr(int *fd_tochild, int *fd_fromchild, int *fd_errfromchild,
|
||||
return childpid;
|
||||
|
||||
fail:
|
||||
for (int i = 0; i < num_par_close; i++)
|
||||
for (i = 0; i < num_par_close; i++)
|
||||
close_noerr(par_close[i]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,8 @@ static bool decode_8_chars(const char c[8], beint64_t *res, int *bytes)
|
||||
{
|
||||
uint64_t acc = 0;
|
||||
size_t num_pad = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int i;
|
||||
for (i = 0; i < 8; i++) {
|
||||
const char *p;
|
||||
|
||||
acc <<= 5;
|
||||
|
||||
@@ -498,6 +498,43 @@ static const struct test base_tests[] = {
|
||||
" return __builtin_cpu_supports(\"mmx\");\n"
|
||||
"}"
|
||||
},
|
||||
{ "HAVE_CLOSEFROM", "closefrom() offered by system",
|
||||
"DEFINES_EVERYTHING", NULL, NULL,
|
||||
"#include <stdlib.h>\n"
|
||||
"#include <unistd.h>\n"
|
||||
"int main(void) {\n"
|
||||
" closefrom(STDERR_FILENO + 1);\n"
|
||||
" return 0;\n"
|
||||
"}\n"
|
||||
},
|
||||
{ "HAVE_F_CLOSEM", "F_CLOSEM defined for fctnl.",
|
||||
"DEFINES_EVERYTHING", NULL, NULL,
|
||||
"#include <fcntl.h>\n"
|
||||
"#include <unistd.h>\n"
|
||||
"int main(void) {\n"
|
||||
" int res = fcntl(STDERR_FILENO + 1, F_CLOSEM, 0);\n"
|
||||
" return res < 0;\n"
|
||||
"}\n"
|
||||
},
|
||||
{ "HAVE_NR_CLOSE_RANGE", "close_range syscall available as __NR_close_range.",
|
||||
"DEFINES_EVERYTHING", NULL, NULL,
|
||||
"#include <limits.h>\n"
|
||||
"#include <sys/syscall.h>\n"
|
||||
"#include <unistd.h>\n"
|
||||
"int main(void) {\n"
|
||||
" int res = syscall(__NR_close_range, STDERR_FILENO + 1, INT_MAX, 0);\n"
|
||||
" return res < 0;\n"
|
||||
"}\n"
|
||||
},
|
||||
{ "HAVE_F_MAXFD", "F_MAXFD defined for fcntl.",
|
||||
"DEFINES_EVERYTHING", NULL, NULL,
|
||||
"#include <fcntl.h>\n"
|
||||
"#include <unistd.h>\n"
|
||||
"int main(void) {\n"
|
||||
" int res = fcntl(0, F_MAXFD);\n"
|
||||
" return res < 0;\n"
|
||||
"}\n"
|
||||
},
|
||||
};
|
||||
|
||||
static void c12r_err(int eval, const char *fmt, ...)
|
||||
@@ -765,9 +802,7 @@ static bool run_test(const char *cmd, const char *wrapper, struct test *test)
|
||||
strcpy(cmd, wrapper);
|
||||
strcat(cmd, " ." DIR_SEP OUTPUT_FILE);
|
||||
output = run(cmd, &status);
|
||||
if (wrapper) {
|
||||
free(cmd);
|
||||
}
|
||||
free(cmd);
|
||||
if (!strstr(test->style, "EXECUTE") && status != 0)
|
||||
c12r_errx(EXIT_BAD_TEST,
|
||||
"Test for %s failed with %i:\n%s",
|
||||
|
||||
Reference in New Issue
Block a user