Commit 5adf7908 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Andrei Vagin

sfd: Make sure we're not overwriting existing files

Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@gmail.com>
parent d2d3b6ff
...@@ -34,6 +34,7 @@ extern int log_get_fd(void); ...@@ -34,6 +34,7 @@ extern int log_get_fd(void);
extern void log_set_loglevel(unsigned int loglevel); extern void log_set_loglevel(unsigned int loglevel);
extern unsigned int log_get_loglevel(void); extern unsigned int log_get_loglevel(void);
struct timeval;
extern void log_get_logstart(struct timeval *); extern void log_get_logstart(struct timeval *);
extern int write_pidfile(int pid); extern int write_pidfile(int pid);
......
#ifndef __CR_SERVICE_FD_H__ #ifndef __CR_SERVICE_FD_H__
#define __CR_SERVICE_FD_H__ #define __CR_SERVICE_FD_H__
#include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include "criu-log.h"
enum sfd_type { enum sfd_type {
SERVICE_FD_MIN, SERVICE_FD_MIN,
...@@ -28,6 +34,19 @@ enum sfd_type { ...@@ -28,6 +34,19 @@ enum sfd_type {
struct pstree_item; struct pstree_item;
extern bool sfds_protected; extern bool sfds_protected;
#define sfd_verify_target(_type, _old_fd, _new_fd) \
({ \
int __ret = 0; \
if (fcntl(_new_fd, F_GETFD) != -1 && errno != EBADF) { \
pr_err("%s busy target %d -> %d\n", \
sfd_type_name(_type), _old_fd, _new_fd); \
__ret = -1; \
} \
__ret; \
})
extern const char *sfd_type_name(enum sfd_type type);
extern int init_service_fd(void); extern int init_service_fd(void);
extern int get_service_fd(enum sfd_type type); extern int get_service_fd(enum sfd_type type);
extern bool is_any_service_fd(int fd); extern bool is_any_service_fd(int fd);
......
...@@ -10,8 +10,6 @@ ...@@ -10,8 +10,6 @@
#include "common/compiler.h" #include "common/compiler.h"
#include "common/list.h" #include "common/list.h"
#include "criu-log.h"
#include "util.h" #include "util.h"
#include "bitops.h" #include "bitops.h"
#include "pstree.h" #include "pstree.h"
...@@ -40,6 +38,31 @@ static int sfd_arr[SERVICE_FD_MAX]; ...@@ -40,6 +38,31 @@ static int sfd_arr[SERVICE_FD_MAX];
*/ */
bool sfds_protected = false; bool sfds_protected = false;
const char *sfd_type_name(enum sfd_type type)
{
static const char *names[] = {
[SERVICE_FD_MIN] = __stringify_1(SERVICE_FD_MIN),
[LOG_FD_OFF] = __stringify_1(LOG_FD_OFF),
[IMG_FD_OFF] = __stringify_1(IMG_FD_OFF),
[PROC_FD_OFF] = __stringify_1(PROC_FD_OFF),
[PROC_PID_FD_OFF] = __stringify_1(PROC_PID_FD_OFF),
[CR_PROC_FD_OFF] = __stringify_1(CR_PROC_FD_OFF),
[ROOT_FD_OFF] = __stringify_1(ROOT_FD_OFF),
[CGROUP_YARD] = __stringify_1(CGROUP_YARD),
[USERNSD_SK] = __stringify_1(USERNSD_SK),
[NS_FD_OFF] = __stringify_1(NS_FD_OFF),
[TRANSPORT_FD_OFF] = __stringify_1(TRANSPORT_FD_OFF),
[RPC_SK_OFF] = __stringify_1(RPC_SK_OFF),
[FDSTORE_SK_OFF] = __stringify_1(FDSTORE_SK_OFF),
[SERVICE_FD_MAX] = __stringify_1(SERVICE_FD_MAX),
};
if (type < ARRAY_SIZE(names))
return names[type];
return "UNKNOWN";
}
int init_service_fd(void) int init_service_fd(void)
{ {
struct rlimit64 rlimit; struct rlimit64 rlimit;
...@@ -107,7 +130,8 @@ int service_fd_min_fd(struct pstree_item *item) ...@@ -107,7 +130,8 @@ int service_fd_min_fd(struct pstree_item *item)
static void sfds_protection_bug(enum sfd_type type) static void sfds_protection_bug(enum sfd_type type)
{ {
pr_err("Service fd %u is being modified in protected context\n", type); pr_err("Service fd %s is being modified in protected context\n",
sfd_type_name(type));
print_stack_trace(current ? vpid(current) : 0); print_stack_trace(current ? vpid(current) : 0);
BUG(); BUG();
} }
...@@ -128,8 +152,14 @@ int install_service_fd(enum sfd_type type, int fd) ...@@ -128,8 +152,14 @@ int install_service_fd(enum sfd_type type, int fd)
return fd; return fd;
} }
if (!test_bit(type, sfd_map)) {
if (sfd_verify_target(type, fd, sfd))
return -1;
}
if (dup3(fd, sfd, O_CLOEXEC) != sfd) { if (dup3(fd, sfd, O_CLOEXEC) != sfd) {
pr_perror("Dup %d -> %d failed", fd, sfd); pr_perror("%s dup %d -> %d failed",
sfd_type_name(type), fd, sfd);
close(fd); close(fd);
return -1; return -1;
} }
...@@ -166,10 +196,14 @@ static void move_service_fd(struct pstree_item *me, int type, int new_id, int ne ...@@ -166,10 +196,14 @@ static void move_service_fd(struct pstree_item *me, int type, int new_id, int ne
if (old < 0) if (old < 0)
return; return;
if (!test_bit(type, sfd_map))
sfd_verify_target(type, old, new);
ret = dup2(old, new); ret = dup2(old, new);
if (ret == -1) { if (ret == -1) {
if (errno != EBADF) if (errno != EBADF)
pr_perror("Unable to clone %d->%d", old, new); pr_perror("%s unable to clone %d->%d",
sfd_type_name(type), old, new);
} else if (!(rsti(me)->clone_flags & CLONE_FILES)) } else if (!(rsti(me)->clone_flags & CLONE_FILES))
close(old); close(old);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment