mirror of
https://github.com/checkpoint-restore/criu
synced 2025-09-01 14:55:39 +00:00
sfd: Make sure we're not overwriting existing files
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com> Signed-off-by: Andrei Vagin <avagin@gmail.com>
This commit is contained in:
committed by
Andrei Vagin
parent
d2d3b6ff48
commit
5adf790859
@@ -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);
|
||||||
|
@@ -1,7 +1,13 @@
|
|||||||
#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 {
|
|||||||
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 @@
|
|||||||
#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];
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user