mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-14 22:34:41 +00:00
utils: fix task_blocking_signal()
Closes #2342. Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
parent
a2db71c041
commit
573ad77fc2
@ -2008,7 +2008,7 @@ static bool do_lxcapi_shutdown(struct lxc_container *c, int timeout)
|
||||
/* Detect whether we should send SIGRTMIN + 3 (e.g. systemd). */
|
||||
if (c->lxc_conf && c->lxc_conf->haltsignal)
|
||||
haltsignal = c->lxc_conf->haltsignal;
|
||||
else if (task_blocking_signal(pid, (SIGRTMIN + 3)))
|
||||
else if (task_blocks_signal(pid, (SIGRTMIN + 3)))
|
||||
haltsignal = (SIGRTMIN + 3);
|
||||
|
||||
/* Add a new state client before sending the shutdown signal so that we
|
||||
|
@ -144,29 +144,42 @@ int lxc_file_for_each_line(const char *file, lxc_file_cb callback, void *data)
|
||||
int lxc_char_left_gc(const char *buffer, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (buffer[i] == ' ' ||
|
||||
buffer[i] == '\t')
|
||||
continue;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lxc_char_right_gc(const char *buffer, size_t len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = len - 1; i >= 0; i--) {
|
||||
if (buffer[i] == ' ' ||
|
||||
buffer[i] == '\t' ||
|
||||
buffer[i] == '\n' ||
|
||||
buffer[i] == '\0')
|
||||
continue;
|
||||
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *lxc_trim_whitespace_in_place(char *buffer)
|
||||
{
|
||||
buffer += lxc_char_left_gc(buffer, strlen(buffer));
|
||||
buffer[lxc_char_right_gc(buffer, strlen(buffer))] = '\0';
|
||||
return buffer;
|
||||
}
|
||||
|
||||
int lxc_is_line_empty(const char *line)
|
||||
{
|
||||
int i;
|
||||
|
@ -41,6 +41,8 @@ extern int lxc_char_left_gc(const char *buffer, size_t len);
|
||||
|
||||
extern int lxc_char_right_gc(const char *buffer, size_t len);
|
||||
|
||||
extern char *lxc_trim_whitespace_in_place(char *buffer);
|
||||
|
||||
extern int lxc_is_line_empty(const char *line);
|
||||
|
||||
/* mmap() wrapper. lxc_strmmap() will take care to \0-terminate files so that
|
||||
|
@ -215,13 +215,13 @@ static int get_seccomp_arg_value(char *key, struct seccomp_v2_rule_args *rule_ar
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = lxc_safe_uint64(v, &value);
|
||||
ret = lxc_safe_uint64(v, &value, 0);
|
||||
if (ret < 0) {
|
||||
ERROR("Invalid argument value");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = lxc_safe_uint64(m, &mask);
|
||||
ret = lxc_safe_uint64(m, &mask, 0);
|
||||
if (ret < 0) {
|
||||
ERROR("Invalid argument mask");
|
||||
return -1;
|
||||
|
@ -1815,12 +1815,12 @@ int lxc_count_file_lines(const char *fn)
|
||||
/* Check whether a signal is blocked by a process. */
|
||||
/* /proc/pid-to-str/status\0 = (5 + 21 + 7 + 1) */
|
||||
#define __PROC_STATUS_LEN (6 + (LXC_NUMSTRLEN64) + 7 + 1)
|
||||
bool task_blocking_signal(pid_t pid, int signal)
|
||||
bool task_blocks_signal(pid_t pid, int signal)
|
||||
{
|
||||
int ret;
|
||||
char status[__PROC_STATUS_LEN];
|
||||
FILE *f;
|
||||
long unsigned int sigblk = 0;
|
||||
uint64_t sigblk = 0, one = 1;
|
||||
size_t n = 0;
|
||||
bool bret = false;
|
||||
char *line = NULL;
|
||||
@ -1834,14 +1834,20 @@ bool task_blocking_signal(pid_t pid, int signal)
|
||||
return bret;
|
||||
|
||||
while (getline(&line, &n, f) != -1) {
|
||||
char *numstr;
|
||||
|
||||
if (strncmp(line, "SigBlk:", 7))
|
||||
continue;
|
||||
|
||||
if (sscanf(line + 7, "%lx", &sigblk) != 1)
|
||||
numstr = lxc_trim_whitespace_in_place(line + 7);
|
||||
ret = lxc_safe_uint64(numstr, &sigblk, 16);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (sigblk & (1LU << (signal - 1)))
|
||||
if (sigblk & (one << (signal - 1)))
|
||||
bret = true;
|
||||
|
||||
out:
|
||||
@ -1958,7 +1964,7 @@ int lxc_safe_ulong(const char *numstr, unsigned long *converted)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lxc_safe_uint64(const char *numstr, uint64_t *converted)
|
||||
int lxc_safe_uint64(const char *numstr, uint64_t *converted, int base)
|
||||
{
|
||||
char *err = NULL;
|
||||
uint64_t u;
|
||||
@ -1970,7 +1976,7 @@ int lxc_safe_uint64(const char *numstr, uint64_t *converted)
|
||||
return -EINVAL;
|
||||
|
||||
errno = 0;
|
||||
u = strtoull(numstr, &err, 0);
|
||||
u = strtoull(numstr, &err, base);
|
||||
if (errno == ERANGE && u == ULLONG_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
|
@ -523,7 +523,7 @@ extern int lxc_count_file_lines(const char *fn);
|
||||
extern int lxc_preserve_ns(const int pid, const char *ns);
|
||||
|
||||
/* Check whether a signal is blocked by a process. */
|
||||
extern bool task_blocking_signal(pid_t pid, int signal);
|
||||
extern bool task_blocks_signal(pid_t pid, int signal);
|
||||
|
||||
/* Helper functions to parse numbers. */
|
||||
extern int lxc_safe_uint(const char *numstr, unsigned int *converted);
|
||||
@ -531,7 +531,7 @@ extern int lxc_safe_int(const char *numstr, int *converted);
|
||||
extern int lxc_safe_long(const char *numstr, long int *converted);
|
||||
extern int lxc_safe_long_long(const char *numstr, long long int *converted);
|
||||
extern int lxc_safe_ulong(const char *numstr, unsigned long *converted);
|
||||
extern int lxc_safe_uint64(const char *numstr, uint64_t *converted);
|
||||
extern int lxc_safe_uint64(const char *numstr, uint64_t *converted, int base);
|
||||
/* Handles B, kb, MB, GB. Detects overflows and reports -ERANGE. */
|
||||
extern int parse_byte_size_string(const char *s, int64_t *converted);
|
||||
|
||||
|
@ -44,7 +44,8 @@ AM_CFLAGS=-DLXCROOTFSMOUNT=\"$(LXCROOTFSMOUNT)\" \
|
||||
-I $(top_srcdir)/src/lxc \
|
||||
-I $(top_srcdir)/src/lxc/bdev \
|
||||
-I $(top_srcdir)/src/lxc/cgroups \
|
||||
-I $(top_srcdir)/src/lxc/tools
|
||||
-I $(top_srcdir)/src/lxc/tools \
|
||||
-pthread
|
||||
|
||||
if ENABLE_APPARMOR
|
||||
AM_CFLAGS += -DHAVE_APPARMOR
|
||||
|
@ -27,14 +27,16 @@
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lxctest.h"
|
||||
#include "utils.h"
|
||||
@ -507,6 +509,67 @@ void test_lxc_config_net_hwaddr(void)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void test_task_blocks_signal(void)
|
||||
{
|
||||
int ret;
|
||||
pid_t pid;
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
if (pid == 0) {
|
||||
int i;
|
||||
sigset_t mask;
|
||||
int signals[] = {SIGBUS, SIGILL, SIGSEGV,
|
||||
SIGWINCH, SIGQUIT, SIGUSR1,
|
||||
SIGUSR2, SIGRTMIN + 3, SIGRTMIN + 4};
|
||||
|
||||
sigemptyset(&mask);
|
||||
|
||||
for (i = 0; i < (sizeof(signals) / sizeof(signals[0])); i++) {
|
||||
ret = sigaddset(&mask, signals[i]);
|
||||
if (ret < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = pthread_sigmask(SIG_BLOCK, &mask, NULL);
|
||||
if (ret < 0) {
|
||||
lxc_error("%s\n", "Failed to block signals");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (i = 0; i < (sizeof(signals) / sizeof(signals[0])); i++) {
|
||||
if (!task_blocks_signal(getpid(), signals[i])) {
|
||||
lxc_error("Failed to detect blocked signal "
|
||||
"(idx = %d, signal number = %d)\n",
|
||||
i, signals[i]);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (task_blocks_signal(getpid(), SIGKILL)) {
|
||||
lxc_error("%s\n",
|
||||
"Falsely detected SIGKILL as blocked signal");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (task_blocks_signal(getpid(), SIGSTOP)) {
|
||||
lxc_error("%s\n",
|
||||
"Falsely detected SIGSTOP as blocked signal");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
ret = wait_for_pid(pid);
|
||||
if (ret < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
test_lxc_string_replace();
|
||||
@ -518,6 +581,7 @@ int main(int argc, char *argv[])
|
||||
test_lxc_safe_long();
|
||||
test_parse_byte_size_string();
|
||||
test_lxc_config_net_hwaddr();
|
||||
test_task_blocks_signal();
|
||||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user