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)
__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)
......
......@@ -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();
......
......@@ -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;
......
......@@ -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))
......
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