mirror of
https://github.com/checkpoint-restore/criu.git
synced 2026-07-17 16:47:50 +00:00
cr: Support rlimits
Dump the with "new" prlimit syscall that works on arbitrary pid. Restore is done in restorer _after_ mappings mixup and _before_ caps drop to make it set any max value. The RLIM_INFINITY is handled explicitly to help future 64<->32 bits migration. Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
parent
d2b3a26b2f
commit
748be83181
14 changed files with 127 additions and 0 deletions
|
|
@ -61,6 +61,7 @@ __NR_setpriority 141 sys_setpriority (int which, int who, int nice)
|
|||
__NR_sched_setscheduler 144 sys_sched_setscheduler (int pid, int policy, struct sched_param *p)
|
||||
__NR_prctl 157 sys_prctl (int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)
|
||||
__NR_arch_prctl 158 sys_arch_prctl (int option, unsigned long addr)
|
||||
__NR_setrlimit 160 sys_setrlimit (int resource, struct rlimit *rlim)
|
||||
__NR_mount 165 sys_mount (char *dev_nmae, char *dir_name, char *type, unsigned long flags, void *data)
|
||||
__NR_umount2 166 sys_umount2 (char *name, int flags)
|
||||
__NR_gettid 186 sys_gettid (void)
|
||||
|
|
|
|||
37
cr-dump.c
37
cr-dump.c
|
|
@ -29,6 +29,7 @@
|
|||
#include "protobuf/mm.pb-c.h"
|
||||
#include "protobuf/creds.pb-c.h"
|
||||
#include "protobuf/core.pb-c.h"
|
||||
#include "protobuf/rlimit.pb-c.h"
|
||||
|
||||
#include "asm/types.h"
|
||||
#include "list.h"
|
||||
|
|
@ -442,6 +443,36 @@ static int dump_task_fs(pid_t pid, struct parasite_dump_misc *misc, struct cr_fd
|
|||
return pb_write_one(fdset_fd(fdset, CR_FD_FS), &fe, PB_FS);
|
||||
}
|
||||
|
||||
static inline u_int64_t encode_rlim(unsigned long val)
|
||||
{
|
||||
return val == RLIM_INFINITY ? -1 : val;
|
||||
}
|
||||
|
||||
static int dump_task_rlims(int pid, struct cr_fdset *fds)
|
||||
{
|
||||
int res, fd;
|
||||
|
||||
fd = fdset_fd(fds, CR_FD_RLIMIT);
|
||||
|
||||
for (res = 0; res < RLIM_NLIMITS; res++) {
|
||||
struct rlimit lim;
|
||||
RlimitEntry re = RLIMIT_ENTRY__INIT;
|
||||
|
||||
if (prlimit(pid, res, NULL, &lim)) {
|
||||
pr_perror("Can't get rlimit %d", res);
|
||||
return -1;
|
||||
}
|
||||
|
||||
re.cur = encode_rlim(lim.rlim_cur);
|
||||
re.max = encode_rlim(lim.rlim_max);
|
||||
|
||||
if (pb_write_one(fd, &re, PB_RLIMIT))
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dump_filemap(pid_t pid, VmaEntry *vma, int file_fd,
|
||||
const struct cr_fdset *fdset)
|
||||
{
|
||||
|
|
@ -1469,6 +1500,12 @@ static int dump_one_task(struct pstree_item *item)
|
|||
goto err;
|
||||
}
|
||||
|
||||
ret = dump_task_rlims(pid, cr_fdset);
|
||||
if (ret) {
|
||||
pr_err("Dump %d rlimits failed %d\n", pid, ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
close_cr_fdset(&cr_fdset);
|
||||
err:
|
||||
close_pid_proc();
|
||||
|
|
|
|||
56
cr-restore.c
56
cr-restore.c
|
|
@ -60,6 +60,7 @@
|
|||
#include "protobuf/sa.pb-c.h"
|
||||
#include "protobuf/itimer.pb-c.h"
|
||||
#include "protobuf/vma.pb-c.h"
|
||||
#include "protobuf/rlimit.pb-c.h"
|
||||
|
||||
#include "asm/restore.h"
|
||||
|
||||
|
|
@ -1568,6 +1569,58 @@ static int prep_sched_info(struct rst_sched_param *sp, ThreadCoreEntry *tc)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long decode_rlim(u_int64_t ival)
|
||||
{
|
||||
return ival == -1 ? RLIM_INFINITY : ival;
|
||||
}
|
||||
|
||||
static int prepare_rlimits(int pid, struct task_restore_core_args *ta)
|
||||
{
|
||||
int fd, ret;
|
||||
|
||||
ta->nr_rlim = 0;
|
||||
|
||||
fd = open_image_ro(CR_FD_RLIMIT, pid);
|
||||
if (fd < 0) {
|
||||
if (errno == ENOENT) {
|
||||
pr_info("Skip rlimits for %d\n", pid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
int l;
|
||||
RlimitEntry *re;
|
||||
|
||||
ret = pb_read_one_eof(fd, &re, PB_RLIMIT);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
|
||||
l = ta->nr_rlim;
|
||||
if (l == RLIM_NLIMITS) {
|
||||
pr_err("Too many rlimits in image for %d\n", pid);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
ta->rlims[l].rlim_cur = decode_rlim(re->cur);
|
||||
ta->rlims[l].rlim_max = decode_rlim(re->max);
|
||||
if (ta->rlims[l].rlim_cur > ta->rlims[l].rlim_max) {
|
||||
pr_err("Can't restore cur > max for %d.%d\n", pid, l);
|
||||
ta->rlims[l].rlim_cur = ta->rlims[l].rlim_max;
|
||||
}
|
||||
|
||||
rlimit_entry__free_unpacked(re, NULL);
|
||||
|
||||
ta->nr_rlim++;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern void __gcov_flush(void) __attribute__((weak));
|
||||
void __gcov_flush(void) {}
|
||||
|
||||
|
|
@ -1730,6 +1783,9 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
|
|||
|
||||
strncpy(task_args->comm, core->tc->comm, sizeof(task_args->comm));
|
||||
|
||||
if (prepare_rlimits(pid, task_args))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* Fill up per-thread data.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -129,6 +129,11 @@ void show_vmas(int fd_vma, struct cr_options *o)
|
|||
pb_show_plain(fd_vma, PB_VMAS);
|
||||
}
|
||||
|
||||
void show_rlimit(int fd, struct cr_options *o)
|
||||
{
|
||||
pb_show_plain(fd, PB_RLIMIT);
|
||||
}
|
||||
|
||||
static int nice_width_for(unsigned long addr)
|
||||
{
|
||||
int ret = 3;
|
||||
|
|
|
|||
1
image.c
1
image.c
|
|
@ -130,6 +130,7 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = {
|
|||
FD_ENTRY(TMPFS, "tmpfs-%d.tar.gz", show_raw_image),
|
||||
FD_ENTRY(TTY, "tty", show_tty),
|
||||
FD_ENTRY(TTY_INFO, "tty-info", show_tty_info),
|
||||
FD_ENTRY(RLIMIT, "rlimit", show_rlimit),
|
||||
};
|
||||
|
||||
static struct cr_fdset *alloc_cr_fdset(int nr)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ enum {
|
|||
CR_FD_ITIMERS,
|
||||
CR_FD_CREDS,
|
||||
CR_FD_FS,
|
||||
CR_FD_RLIMIT,
|
||||
_CR_FD_TASK_TO,
|
||||
|
||||
/*
|
||||
|
|
@ -154,6 +155,7 @@ void show_fown_cont(void *p);
|
|||
void show_eventfds(int fd, struct cr_options *o);
|
||||
void show_tty(int fd, struct cr_options *o);
|
||||
void show_tty_info(int fd, struct cr_options *o);
|
||||
void show_rlimit(int fd, struct cr_options *o);
|
||||
|
||||
int check_img_inventory(void);
|
||||
int write_img_inventory(void);
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
#define NETDEV_MAGIC 0x57373951 /* Yaroslavl */
|
||||
#define TTY_MAGIC 0x59433025 /* Pushkin */
|
||||
#define TTY_INFO_MAGIC 0x59453036 /* Kolpino */
|
||||
#define RLIMIT_MAGIC 0x57113925 /* Rostov */
|
||||
|
||||
#define IFADDR_MAGIC RAW_IMAGE_MAGIC
|
||||
#define ROUTE_MAGIC RAW_IMAGE_MAGIC
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ enum {
|
|||
PB_INOTIFY_WD,
|
||||
PB_TTY,
|
||||
PB_TTY_INFO,
|
||||
PB_RLIMIT,
|
||||
|
||||
PB_MAX
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <signal.h>
|
||||
#include <limits.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include "compiler.h"
|
||||
#include "asm/types.h"
|
||||
|
|
@ -122,6 +123,9 @@ struct task_restore_core_args {
|
|||
u32 mm_saved_auxv_size;
|
||||
char comm[TASK_COMM_LEN];
|
||||
|
||||
int nr_rlim;
|
||||
struct rlimit rlims[RLIM_NLIMITS];
|
||||
|
||||
int *rst_tcp_socks;
|
||||
int rst_tcp_socks_size;
|
||||
} __aligned(sizeof(long));
|
||||
|
|
|
|||
|
|
@ -61,4 +61,6 @@ struct robust_list_head;
|
|||
|
||||
#define setns sys_setns
|
||||
|
||||
struct rlimit;
|
||||
|
||||
#endif /* __CR_SYSCALL_TYPES_H__ */
|
||||
|
|
|
|||
|
|
@ -143,6 +143,14 @@ static void restore_sched_info(struct rst_sched_param *p)
|
|||
sys_sched_setscheduler(0, p->policy, &parm);
|
||||
}
|
||||
|
||||
static void restore_rlims(struct task_restore_core_args *ta)
|
||||
{
|
||||
int r;
|
||||
|
||||
for (r = 0; r < ta->nr_rlim; r++)
|
||||
sys_setrlimit(r, &ta->rlims[r]);
|
||||
}
|
||||
|
||||
static int restore_thread_common(struct rt_sigframe *sigframe,
|
||||
struct thread_restore_args *args)
|
||||
{
|
||||
|
|
@ -656,6 +664,8 @@ long __export_restore_task(struct task_restore_core_args *args)
|
|||
sys_close(fd);
|
||||
}
|
||||
|
||||
restore_rlims(args);
|
||||
|
||||
/*
|
||||
* Writing to last-pid is CAP_SYS_ADMIN protected, thus restore
|
||||
* creds _after_ all threads creation.
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#include "protobuf/netdev.pb-c.h"
|
||||
#include "protobuf/tcp-stream.pb-c.h"
|
||||
#include "protobuf/tty.pb-c.h"
|
||||
#include "protobuf/rlimit.pb-c.h"
|
||||
|
||||
typedef size_t (*pb_getpksize_t)(void *obj);
|
||||
typedef size_t (*pb_pack_t)(void *obj, void *where);
|
||||
|
|
@ -125,6 +126,7 @@ void cr_pb_init(void)
|
|||
CR_PB_DESC(PACKETSK, PacketSock, packet_sock);
|
||||
CR_PB_DESC(TTY, TtyFile, tty_file);
|
||||
CR_PB_DESC(TTY_INFO, TtyInfo, tty_info);
|
||||
CR_PB_DESC(RLIMIT, Rlimit, rlimit);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ PROTO_FILES += vma.proto
|
|||
PROTO_FILES += core.proto
|
||||
PROTO_FILES += netdev.proto
|
||||
PROTO_FILES += tty.proto
|
||||
PROTO_FILES += rlimit.proto
|
||||
|
||||
PROTO_HDRS := $(patsubst %.proto,%.pb-c.h,$(PROTO_FILES))
|
||||
PROTO_SRCS := $(patsubst %.proto,%.pb-c.c,$(PROTO_FILES))
|
||||
|
|
|
|||
4
protobuf/rlimit.proto
Normal file
4
protobuf/rlimit.proto
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
message rlimit_entry {
|
||||
required uint64 cur = 1;
|
||||
required uint64 max = 2;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue