Commit 748be831 authored by Pavel Emelyanov's avatar Pavel Emelyanov

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: 's avatarPavel Emelyanov <xemul@parallels.com>
parent d2b3a26b
...@@ -61,6 +61,7 @@ __NR_setpriority 141 sys_setpriority (int which, int who, int nice) ...@@ -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_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_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_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_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_umount2 166 sys_umount2 (char *name, int flags)
__NR_gettid 186 sys_gettid (void) __NR_gettid 186 sys_gettid (void)
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "protobuf/mm.pb-c.h" #include "protobuf/mm.pb-c.h"
#include "protobuf/creds.pb-c.h" #include "protobuf/creds.pb-c.h"
#include "protobuf/core.pb-c.h" #include "protobuf/core.pb-c.h"
#include "protobuf/rlimit.pb-c.h"
#include "asm/types.h" #include "asm/types.h"
#include "list.h" #include "list.h"
...@@ -442,6 +443,36 @@ static int dump_task_fs(pid_t pid, struct parasite_dump_misc *misc, struct cr_fd ...@@ -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); 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, static int dump_filemap(pid_t pid, VmaEntry *vma, int file_fd,
const struct cr_fdset *fdset) const struct cr_fdset *fdset)
{ {
...@@ -1469,6 +1500,12 @@ static int dump_one_task(struct pstree_item *item) ...@@ -1469,6 +1500,12 @@ static int dump_one_task(struct pstree_item *item)
goto err; 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); close_cr_fdset(&cr_fdset);
err: err:
close_pid_proc(); close_pid_proc();
......
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
#include "protobuf/sa.pb-c.h" #include "protobuf/sa.pb-c.h"
#include "protobuf/itimer.pb-c.h" #include "protobuf/itimer.pb-c.h"
#include "protobuf/vma.pb-c.h" #include "protobuf/vma.pb-c.h"
#include "protobuf/rlimit.pb-c.h"
#include "asm/restore.h" #include "asm/restore.h"
...@@ -1568,6 +1569,58 @@ static int prep_sched_info(struct rst_sched_param *sp, ThreadCoreEntry *tc) ...@@ -1568,6 +1569,58 @@ static int prep_sched_info(struct rst_sched_param *sp, ThreadCoreEntry *tc)
return 0; 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)); extern void __gcov_flush(void) __attribute__((weak));
void __gcov_flush(void) {} void __gcov_flush(void) {}
...@@ -1730,6 +1783,9 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core) ...@@ -1730,6 +1783,9 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
strncpy(task_args->comm, core->tc->comm, sizeof(task_args->comm)); strncpy(task_args->comm, core->tc->comm, sizeof(task_args->comm));
if (prepare_rlimits(pid, task_args))
goto err;
/* /*
* Fill up per-thread data. * Fill up per-thread data.
*/ */
......
...@@ -129,6 +129,11 @@ void show_vmas(int fd_vma, struct cr_options *o) ...@@ -129,6 +129,11 @@ void show_vmas(int fd_vma, struct cr_options *o)
pb_show_plain(fd_vma, PB_VMAS); 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) static int nice_width_for(unsigned long addr)
{ {
int ret = 3; int ret = 3;
......
...@@ -130,6 +130,7 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = { ...@@ -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(TMPFS, "tmpfs-%d.tar.gz", show_raw_image),
FD_ENTRY(TTY, "tty", show_tty), FD_ENTRY(TTY, "tty", show_tty),
FD_ENTRY(TTY_INFO, "tty-info", show_tty_info), FD_ENTRY(TTY_INFO, "tty-info", show_tty_info),
FD_ENTRY(RLIMIT, "rlimit", show_rlimit),
}; };
static struct cr_fdset *alloc_cr_fdset(int nr) static struct cr_fdset *alloc_cr_fdset(int nr)
......
...@@ -32,6 +32,7 @@ enum { ...@@ -32,6 +32,7 @@ enum {
CR_FD_ITIMERS, CR_FD_ITIMERS,
CR_FD_CREDS, CR_FD_CREDS,
CR_FD_FS, CR_FD_FS,
CR_FD_RLIMIT,
_CR_FD_TASK_TO, _CR_FD_TASK_TO,
/* /*
...@@ -154,6 +155,7 @@ void show_fown_cont(void *p); ...@@ -154,6 +155,7 @@ void show_fown_cont(void *p);
void show_eventfds(int fd, struct cr_options *o); void show_eventfds(int fd, struct cr_options *o);
void show_tty(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_tty_info(int fd, struct cr_options *o);
void show_rlimit(int fd, struct cr_options *o);
int check_img_inventory(void); int check_img_inventory(void);
int write_img_inventory(void); int write_img_inventory(void);
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
#define NETDEV_MAGIC 0x57373951 /* Yaroslavl */ #define NETDEV_MAGIC 0x57373951 /* Yaroslavl */
#define TTY_MAGIC 0x59433025 /* Pushkin */ #define TTY_MAGIC 0x59433025 /* Pushkin */
#define TTY_INFO_MAGIC 0x59453036 /* Kolpino */ #define TTY_INFO_MAGIC 0x59453036 /* Kolpino */
#define RLIMIT_MAGIC 0x57113925 /* Rostov */
#define IFADDR_MAGIC RAW_IMAGE_MAGIC #define IFADDR_MAGIC RAW_IMAGE_MAGIC
#define ROUTE_MAGIC RAW_IMAGE_MAGIC #define ROUTE_MAGIC RAW_IMAGE_MAGIC
......
...@@ -43,6 +43,7 @@ enum { ...@@ -43,6 +43,7 @@ enum {
PB_INOTIFY_WD, PB_INOTIFY_WD,
PB_TTY, PB_TTY,
PB_TTY_INFO, PB_TTY_INFO,
PB_RLIMIT,
PB_MAX PB_MAX
}; };
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <signal.h> #include <signal.h>
#include <limits.h> #include <limits.h>
#include <sys/resource.h>
#include "compiler.h" #include "compiler.h"
#include "asm/types.h" #include "asm/types.h"
...@@ -122,6 +123,9 @@ struct task_restore_core_args { ...@@ -122,6 +123,9 @@ struct task_restore_core_args {
u32 mm_saved_auxv_size; u32 mm_saved_auxv_size;
char comm[TASK_COMM_LEN]; char comm[TASK_COMM_LEN];
int nr_rlim;
struct rlimit rlims[RLIM_NLIMITS];
int *rst_tcp_socks; int *rst_tcp_socks;
int rst_tcp_socks_size; int rst_tcp_socks_size;
} __aligned(sizeof(long)); } __aligned(sizeof(long));
......
...@@ -61,4 +61,6 @@ struct robust_list_head; ...@@ -61,4 +61,6 @@ struct robust_list_head;
#define setns sys_setns #define setns sys_setns
struct rlimit;
#endif /* __CR_SYSCALL_TYPES_H__ */ #endif /* __CR_SYSCALL_TYPES_H__ */
...@@ -143,6 +143,14 @@ static void restore_sched_info(struct rst_sched_param *p) ...@@ -143,6 +143,14 @@ static void restore_sched_info(struct rst_sched_param *p)
sys_sched_setscheduler(0, p->policy, &parm); 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, static int restore_thread_common(struct rt_sigframe *sigframe,
struct thread_restore_args *args) struct thread_restore_args *args)
{ {
...@@ -656,6 +664,8 @@ long __export_restore_task(struct task_restore_core_args *args) ...@@ -656,6 +664,8 @@ long __export_restore_task(struct task_restore_core_args *args)
sys_close(fd); sys_close(fd);
} }
restore_rlims(args);
/* /*
* Writing to last-pid is CAP_SYS_ADMIN protected, thus restore * Writing to last-pid is CAP_SYS_ADMIN protected, thus restore
* creds _after_ all threads creation. * creds _after_ all threads creation.
......
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include "protobuf/netdev.pb-c.h" #include "protobuf/netdev.pb-c.h"
#include "protobuf/tcp-stream.pb-c.h" #include "protobuf/tcp-stream.pb-c.h"
#include "protobuf/tty.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_getpksize_t)(void *obj);
typedef size_t (*pb_pack_t)(void *obj, void *where); typedef size_t (*pb_pack_t)(void *obj, void *where);
...@@ -125,6 +126,7 @@ void cr_pb_init(void) ...@@ -125,6 +126,7 @@ void cr_pb_init(void)
CR_PB_DESC(PACKETSK, PacketSock, packet_sock); CR_PB_DESC(PACKETSK, PacketSock, packet_sock);
CR_PB_DESC(TTY, TtyFile, tty_file); CR_PB_DESC(TTY, TtyFile, tty_file);
CR_PB_DESC(TTY_INFO, TtyInfo, tty_info); CR_PB_DESC(TTY_INFO, TtyInfo, tty_info);
CR_PB_DESC(RLIMIT, Rlimit, rlimit);
} }
/* /*
......
...@@ -37,6 +37,7 @@ PROTO_FILES += vma.proto ...@@ -37,6 +37,7 @@ PROTO_FILES += vma.proto
PROTO_FILES += core.proto PROTO_FILES += core.proto
PROTO_FILES += netdev.proto PROTO_FILES += netdev.proto
PROTO_FILES += tty.proto PROTO_FILES += tty.proto
PROTO_FILES += rlimit.proto
PROTO_HDRS := $(patsubst %.proto,%.pb-c.h,$(PROTO_FILES)) PROTO_HDRS := $(patsubst %.proto,%.pb-c.h,$(PROTO_FILES))
PROTO_SRCS := $(patsubst %.proto,%.pb-c.c,$(PROTO_FILES)) PROTO_SRCS := $(patsubst %.proto,%.pb-c.c,$(PROTO_FILES))
......
message rlimit_entry {
required uint64 cur = 1;
required uint64 max = 2;
}
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