2012-12-24 15:36:14 +04:00
|
|
|
#ifndef __CR_CRTOOLS_H__
|
|
|
|
#define __CR_CRTOOLS_H__
|
2011-09-23 12:00:45 +04:00
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
2012-05-31 14:50:00 +04:00
|
|
|
#include "list.h"
|
2013-01-09 17:02:47 +04:00
|
|
|
#include "asm/types.h"
|
2011-09-23 12:00:45 +04:00
|
|
|
#include "list.h"
|
fdset: Introduce new fdsets
Current fdsets are ugly, limited (bitmask will exhaust in several months) and
suffer from unknown problems with fdsets reuse :(
With new approach (this set) the images management is simple. The basic function
is open_image, which gives you an fd for an image. If you want to pre-open several
images at once instead of calling open_image every single time, you can use the
new fdsets.
Images CR_FD_ descriptors should be grouped like
_CR_FD_FOO_FROM,
CR_FD_FOO_ITEM1,
CR_FD_FOO_ITEM2,
..
CR_FD_FOO_ITEMN,
_CR_FD_FOO_TO,
After this you can call cr_fd_open() specifying ranges -- _FROM and _TO macros,
it will give you an cr_fdset object. Then the fdset_fd(set, type) will give you
the descriptor of the open "set" group corresponding to the "type" type.
3 groups are introduced in this set -- tasks, ns and global.
That's it.
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
2012-03-26 17:46:39 +04:00
|
|
|
#include "util.h"
|
2011-09-23 12:00:45 +04:00
|
|
|
#include "image.h"
|
2013-01-11 18:16:23 +04:00
|
|
|
#include "lock.h"
|
2013-05-28 22:12:06 +04:00
|
|
|
#include "cr-show.h"
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2013-02-15 17:33:06 +04:00
|
|
|
#include "protobuf/vma.pb-c.h"
|
2012-07-19 12:43:36 +04:00
|
|
|
|
2011-10-03 11:52:13 +04:00
|
|
|
#define CR_FD_PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2012-09-17 20:05:23 +04:00
|
|
|
struct script {
|
|
|
|
struct list_head node;
|
|
|
|
char *path;
|
|
|
|
};
|
|
|
|
|
2011-10-04 01:50:19 +04:00
|
|
|
struct cr_options {
|
2012-03-01 19:09:02 +04:00
|
|
|
int final_state;
|
2012-01-26 15:27:00 +04:00
|
|
|
char *show_dump_file;
|
2013-04-23 23:38:47 +04:00
|
|
|
bool check_ms_kernel;
|
2012-01-26 15:27:00 +04:00
|
|
|
bool show_pages_content;
|
|
|
|
bool restore_detach;
|
2012-04-19 11:48:00 +04:00
|
|
|
bool ext_unix_sk;
|
2012-10-18 15:51:57 +04:00
|
|
|
bool shell_job;
|
2013-01-17 16:09:27 +08:00
|
|
|
bool handle_file_locks;
|
2012-04-28 17:15:12 +04:00
|
|
|
bool tcp_established_ok;
|
2012-08-07 19:33:49 +04:00
|
|
|
bool evasive_devices;
|
2012-09-26 06:39:23 +04:00
|
|
|
bool link_remap_ok;
|
2013-01-17 18:14:55 +04:00
|
|
|
unsigned int rst_namespaces_flags;
|
2012-05-02 14:42:00 +04:00
|
|
|
bool log_file_per_pid;
|
|
|
|
char *output;
|
2012-08-02 16:07:43 +04:00
|
|
|
char *root;
|
2012-08-14 12:54:00 +04:00
|
|
|
char *pidfile;
|
2012-09-02 01:07:32 +04:00
|
|
|
struct list_head veth_pairs;
|
2012-09-17 20:05:23 +04:00
|
|
|
struct list_head scripts;
|
2013-03-12 21:23:06 +04:00
|
|
|
bool use_page_server;
|
2013-08-11 12:01:14 +04:00
|
|
|
unsigned short ps_port;
|
|
|
|
char *addr;
|
2013-05-08 15:52:48 +04:00
|
|
|
bool track_mem;
|
|
|
|
char *img_parent;
|
2011-10-04 01:50:19 +04:00
|
|
|
};
|
|
|
|
|
2012-05-02 14:42:00 +04:00
|
|
|
extern struct cr_options opts;
|
|
|
|
|
2012-09-13 14:45:06 +04:00
|
|
|
enum sfd_type {
|
|
|
|
SERVICE_FD_MIN,
|
|
|
|
|
|
|
|
LOG_FD_OFF,
|
2012-09-02 01:02:30 +04:00
|
|
|
LOG_DIR_FD_OFF,
|
2012-03-16 17:21:00 +04:00
|
|
|
IMG_FD_OFF,
|
2013-09-23 14:33:25 +04:00
|
|
|
PROC_FD_OFF, /* /proc in the restored pidns */
|
2012-09-12 20:00:58 +04:00
|
|
|
CTL_TTY_OFF,
|
2012-10-18 15:51:56 +04:00
|
|
|
SELF_STDIN_OFF,
|
2013-04-11 17:50:42 +04:00
|
|
|
PARENT_FD_OFF,
|
2013-09-23 14:33:25 +04:00
|
|
|
CR_PROC_FD_OFF, /* /proc in criu's pidns */
|
2012-09-13 14:45:06 +04:00
|
|
|
|
|
|
|
SERVICE_FD_MAX
|
2012-03-16 17:21:00 +04:00
|
|
|
};
|
|
|
|
|
2013-04-11 17:50:42 +04:00
|
|
|
#define CR_PARENT_LINK "parent"
|
|
|
|
|
2013-01-11 18:16:19 +04:00
|
|
|
extern int clone_service_fd(int id);
|
2012-09-13 14:45:06 +04:00
|
|
|
extern int init_service_fd(void);
|
|
|
|
extern int get_service_fd(enum sfd_type type);
|
2013-03-18 23:04:09 +04:00
|
|
|
extern int reserve_service_fd(enum sfd_type type);
|
2013-01-11 18:16:20 +04:00
|
|
|
extern int install_service_fd(enum sfd_type type, int fd);
|
|
|
|
extern int close_service_fd(enum sfd_type type);
|
2012-09-13 14:45:06 +04:00
|
|
|
extern bool is_service_fd(int fd, enum sfd_type type);
|
2012-09-29 11:01:53 +04:00
|
|
|
extern bool is_any_service_fd(int fd);
|
2012-03-16 17:21:00 +04:00
|
|
|
|
2012-07-19 17:37:25 +04:00
|
|
|
int check_img_inventory(void);
|
|
|
|
int write_img_inventory(void);
|
2013-03-27 16:16:25 +04:00
|
|
|
void kill_inventory(void);
|
2012-07-19 17:37:25 +04:00
|
|
|
|
2012-04-12 15:33:09 +04:00
|
|
|
extern void print_data(unsigned long addr, unsigned char *data, size_t size);
|
2012-12-10 18:57:54 +03:00
|
|
|
extern void print_image_data(int fd, unsigned int length, int show);
|
2011-12-29 19:56:34 +04:00
|
|
|
extern struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX];
|
|
|
|
|
2012-03-16 17:24:00 +04:00
|
|
|
extern int open_image_dir(void);
|
|
|
|
extern void close_image_dir(void);
|
2012-03-19 15:38:00 +04:00
|
|
|
|
2013-04-11 17:49:43 +04:00
|
|
|
int open_image_at(int dfd, int type, unsigned long flags, ...);
|
|
|
|
#define open_image(typ, flags, ...) open_image_at(get_service_fd(IMG_FD_OFF), typ, flags, ##__VA_ARGS__)
|
2013-03-12 21:00:05 +04:00
|
|
|
int open_pages_image(unsigned long flags, int pm_fd);
|
2013-04-11 17:49:43 +04:00
|
|
|
int open_pages_image_at(int dfd, unsigned long flags, int pm_fd);
|
2013-03-14 18:28:38 +04:00
|
|
|
void up_page_ids_base(void);
|
2011-12-07 13:48:00 +04:00
|
|
|
|
2011-12-01 18:21:17 +04:00
|
|
|
#define LAST_PID_PATH "/proc/sys/kernel/ns_last_pid"
|
|
|
|
|
2011-09-23 12:00:45 +04:00
|
|
|
struct cr_fdset {
|
fdset: Introduce new fdsets
Current fdsets are ugly, limited (bitmask will exhaust in several months) and
suffer from unknown problems with fdsets reuse :(
With new approach (this set) the images management is simple. The basic function
is open_image, which gives you an fd for an image. If you want to pre-open several
images at once instead of calling open_image every single time, you can use the
new fdsets.
Images CR_FD_ descriptors should be grouped like
_CR_FD_FOO_FROM,
CR_FD_FOO_ITEM1,
CR_FD_FOO_ITEM2,
..
CR_FD_FOO_ITEMN,
_CR_FD_FOO_TO,
After this you can call cr_fd_open() specifying ranges -- _FROM and _TO macros,
it will give you an cr_fdset object. Then the fdset_fd(set, type) will give you
the descriptor of the open "set" group corresponding to the "type" type.
3 groups are introduced in this set -- tasks, ns and global.
That's it.
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
2012-03-26 17:46:39 +04:00
|
|
|
int fd_off;
|
|
|
|
int fd_nr;
|
|
|
|
int *_fds;
|
2011-09-23 12:00:45 +04:00
|
|
|
};
|
|
|
|
|
2012-03-26 17:43:29 +04:00
|
|
|
static inline int fdset_fd(const struct cr_fdset *fdset, int type)
|
|
|
|
{
|
fdset: Introduce new fdsets
Current fdsets are ugly, limited (bitmask will exhaust in several months) and
suffer from unknown problems with fdsets reuse :(
With new approach (this set) the images management is simple. The basic function
is open_image, which gives you an fd for an image. If you want to pre-open several
images at once instead of calling open_image every single time, you can use the
new fdsets.
Images CR_FD_ descriptors should be grouped like
_CR_FD_FOO_FROM,
CR_FD_FOO_ITEM1,
CR_FD_FOO_ITEM2,
..
CR_FD_FOO_ITEMN,
_CR_FD_FOO_TO,
After this you can call cr_fd_open() specifying ranges -- _FROM and _TO macros,
it will give you an cr_fdset object. Then the fdset_fd(set, type) will give you
the descriptor of the open "set" group corresponding to the "type" type.
3 groups are introduced in this set -- tasks, ns and global.
That's it.
Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
2012-03-26 17:46:39 +04:00
|
|
|
int idx;
|
|
|
|
|
|
|
|
idx = type - fdset->fd_off;
|
|
|
|
BUG_ON(idx > fdset->fd_nr);
|
|
|
|
|
|
|
|
return fdset->_fds[idx];
|
2012-03-26 17:43:29 +04:00
|
|
|
}
|
|
|
|
|
2012-03-26 17:47:38 +04:00
|
|
|
extern struct cr_fdset *glob_fdset;
|
|
|
|
|
2013-05-08 16:00:53 +04:00
|
|
|
int cr_dump_tasks(pid_t pid);
|
2013-05-14 12:00:40 +04:00
|
|
|
int cr_pre_dump_tasks(pid_t pid);
|
2013-05-28 21:11:13 +04:00
|
|
|
int cr_restore_tasks(void);
|
|
|
|
int cr_show(int pid);
|
2011-10-04 01:50:19 +04:00
|
|
|
int convert_to_elf(char *elf_path, int fd_core);
|
2012-03-02 14:01:08 +04:00
|
|
|
int cr_check(void);
|
2012-12-17 22:56:06 +03:00
|
|
|
int cr_exec(int pid, char **opts);
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2012-03-26 17:45:08 +04:00
|
|
|
#define O_DUMP (O_RDWR | O_CREAT | O_EXCL)
|
|
|
|
#define O_SHOW (O_RDONLY)
|
2013-03-12 21:00:05 +04:00
|
|
|
#define O_RSTR (O_RDONLY)
|
2012-03-26 17:45:08 +04:00
|
|
|
|
|
|
|
struct cr_fdset *cr_task_fdset_open(int pid, int mode);
|
2013-09-28 05:39:52 +04:00
|
|
|
struct cr_fdset *cr_fdset_open_range(int pid, int from, int to,
|
2013-09-30 17:16:44 +04:00
|
|
|
unsigned long flags);
|
2013-09-28 05:39:52 +04:00
|
|
|
#define cr_fdset_open(pid, type, flags) cr_fdset_open_range(pid, \
|
|
|
|
_CR_FD_##type##_FROM, _CR_FD_##type##_TO, flags)
|
2012-03-26 17:47:38 +04:00
|
|
|
struct cr_fdset *cr_glob_fdset_open(int mode);
|
|
|
|
|
2012-01-12 21:25:19 +04:00
|
|
|
void close_cr_fdset(struct cr_fdset **cr_fdset);
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2013-03-01 20:11:51 +04:00
|
|
|
struct vm_area_list {
|
|
|
|
struct list_head h;
|
|
|
|
unsigned nr;
|
2013-03-01 20:12:33 +04:00
|
|
|
unsigned long priv_size; /* nr of pages in private VMAs */
|
|
|
|
unsigned long longest; /* nr of pages in longest VMA */
|
2013-03-01 20:11:51 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
#define VM_AREA_LIST(name) struct vm_area_list name = { .h = LIST_HEAD_INIT(name.h), .nr = 0, }
|
|
|
|
|
|
|
|
int collect_mappings(pid_t pid, struct vm_area_list *vma_area_list);
|
|
|
|
void free_mappings(struct vm_area_list *vma_area_list);
|
2013-03-01 20:12:02 +04:00
|
|
|
bool privately_dump_vma(struct vma_area *vma);
|
2011-10-26 22:48:10 +04:00
|
|
|
|
2011-09-23 12:00:45 +04:00
|
|
|
struct vma_area {
|
|
|
|
struct list_head list;
|
2012-07-19 12:43:36 +04:00
|
|
|
VmaEntry vma;
|
2012-11-02 16:00:18 +03:00
|
|
|
|
|
|
|
union {
|
|
|
|
int vm_file_fd;
|
|
|
|
int vm_socket_id;
|
|
|
|
};
|
2012-11-20 20:48:33 +04:00
|
|
|
unsigned long *page_bitmap; /* existent pages */
|
|
|
|
unsigned long *ppage_bitmap; /* parent's existent pages */
|
2011-09-23 12:00:45 +04:00
|
|
|
};
|
|
|
|
|
2011-11-15 17:12:29 +04:00
|
|
|
#define vma_area_is(vma_area, s) vma_entry_is(&((vma_area)->vma), s)
|
|
|
|
#define vma_area_len(vma_area) vma_entry_len(&((vma_area)->vma))
|
2011-09-23 12:00:45 +04:00
|
|
|
|
2013-01-11 18:16:23 +04:00
|
|
|
struct fdt {
|
|
|
|
int nr; /* How many tasks share this fd table */
|
|
|
|
pid_t pid; /* Who should restore this fd table */
|
|
|
|
/*
|
|
|
|
* The fd table is ready for restoing, if fdt_lock is equal to nr
|
|
|
|
* The fdt table was restrored, if fdt_lock is equal to nr + 1
|
|
|
|
*/
|
|
|
|
futex_t fdt_lock;
|
|
|
|
};
|
|
|
|
|
2012-04-18 15:42:26 +04:00
|
|
|
struct rst_info {
|
2012-04-18 16:24:08 +04:00
|
|
|
struct list_head fds;
|
2012-05-04 16:31:00 +04:00
|
|
|
struct list_head eventpoll;
|
2012-09-12 20:00:52 +04:00
|
|
|
struct list_head tty_slaves;
|
2012-12-06 13:19:01 +03:00
|
|
|
|
|
|
|
void *premmapped_addr;
|
|
|
|
unsigned long premmapped_len;
|
2013-01-19 01:16:19 +04:00
|
|
|
unsigned long clone_flags;
|
2013-01-11 18:16:23 +04:00
|
|
|
|
2013-09-23 14:33:35 +04:00
|
|
|
void *munmap_restorer;
|
|
|
|
|
2013-03-25 23:39:52 +04:00
|
|
|
int nr_zombies;
|
|
|
|
|
2013-01-12 00:44:26 +04:00
|
|
|
int service_fd_id;
|
2013-01-11 18:16:23 +04:00
|
|
|
struct fdt *fdt;
|
2013-09-27 04:38:00 +04:00
|
|
|
|
|
|
|
union {
|
|
|
|
struct pstree_item *pgrp_leader;
|
|
|
|
futex_t pgrp_set;
|
|
|
|
};
|
2012-04-18 15:42:26 +04:00
|
|
|
};
|
|
|
|
|
2011-09-23 12:00:45 +04:00
|
|
|
static inline int in_vma_area(struct vma_area *vma, unsigned long addr)
|
|
|
|
{
|
|
|
|
return addr >= (unsigned long)vma->vma.start &&
|
|
|
|
addr < (unsigned long)vma->vma.end;
|
|
|
|
}
|
|
|
|
|
2013-08-29 08:07:15 +04:00
|
|
|
/*
|
|
|
|
* When we have to restore a shared resource, we mush select which
|
|
|
|
* task should do it, and make other(s) wait for it. In order to
|
|
|
|
* avoid deadlocks, always make task with lower pid be the restorer.
|
|
|
|
*/
|
|
|
|
static inline bool pid_rst_prio(unsigned pid_a, unsigned pid_b)
|
|
|
|
{
|
|
|
|
return pid_a < pid_b;
|
|
|
|
}
|
|
|
|
|
2013-09-28 06:16:17 +04:00
|
|
|
void restrict_uid(unsigned int uid);
|
|
|
|
bool may_dump_uid(unsigned int uid);
|
2013-10-02 17:11:17 +04:00
|
|
|
bool may_restore_uid(unsigned int uid);
|
2013-09-28 06:16:17 +04:00
|
|
|
|
2012-12-25 22:40:24 +04:00
|
|
|
#endif /* __CR_CRTOOLS_H__ */
|