Using kernel headers directly from userspace is strongly discouraged. This patch attempts to sanitize kernel headers for userspace by extracting non-__KERNEL__ portions of the various checkpoint headers and placing them in a similar organization of userspace headers. The script is run from the top level of the user-cr source tree like: ./scripts/extract-headers.sh -s <path-to-kern-source> -o ./include The patch includes a copy of the auto-generated headers and adjusts the user-cr programs to use them. Signed-off-by: Matt Helsley <matthltc@xxxxxxxxxx> TODO: Builds on i386. Probably needs more testing, especially on other non-i386, non-32-bit platforms. Look at mergiing checkpoint_syscalls.h with checkpoint.h Or at least find a better, shorter name for checkpoint_syscalls.h NOTES: The script is much larger (2.5x) than for cr_tests because cr_tests only required the syscall numbers and a few flags for the syscalls. The headers have a similar organization to the kernel headers because struct ckpt_hdr must be defined before the arch hdrs and yet CKPT_ARCH_NSIG must be defined before the generic signal hdrs. Plus it's easier to avoid rewriting the paths within the include directories... checkpoint_syscalls.h is a multi-arch file with all the syscall numbers normally found in the arch's unistd.h. I chose to use a different name to avoid clashes with /usr/include headers. --- Makefile | 31 +-- ckpt.c | 1 + ckptinfo.c | 2 + ckptinfo.py | 2 + include/asm/checkpoint_hdr.h | 205 ++++++++++++ include/linux/checkpoint.h | 26 ++ include/linux/checkpoint_hdr.h | 580 +++++++++++++++++++++++++++++++++++ include/linux/checkpoint_syscalls.h | 30 ++ mktree.c | 4 + rstr.c | 1 + scripts/extract-headers.sh | 194 ++++++++++++ self.c | 1 + 12 files changed, 1056 insertions(+), 21 deletions(-) create mode 100644 include/asm/checkpoint_hdr.h create mode 100644 include/linux/checkpoint.h create mode 100644 include/linux/checkpoint_hdr.h create mode 100644 include/linux/checkpoint_syscalls.h create mode 100755 scripts/extract-headers.sh diff --git a/Makefile b/Makefile index afff3f5..509a2a4 100644 --- a/Makefile +++ b/Makefile @@ -1,24 +1,5 @@ - -KERNELSRC ?= ../linux -KERNELBUILD ?= ../linux - -# default with 'make headers_install' -KERNELHDR ?= $(KERNELSRC)/usr/include - -ifneq "$(realpath $(KERNELHDR)/linux/checkpoint.h)" "" -# if .../usr/include contains our headers -CKPT_INCLUDE = -I$(KERNELHDR) -CKPT_HEADERS = $(KERNELHDR)/linux/checkpoint_hdr.h \ - $(KERNELHDR)/asm/checkpoint_hdr.h -else -# else, usr the kernel source itself -# but first, find linux architecure -KERN_ARCH = $(shell readlink $(KERNELBUILD)/include/asm | sed 's/^asm-//') -CKPT_INCLUDE = -I$(KERNELSRC)/include \ - -I$(KERNELSRC)/arch/$(KERN_ARCH)/include -CKPT_HEADERS = $(KERNELSRC)/include/linux/checkpoint_hdr.h \ - $(KERNELSRC)/arch/$(KERN_ARCH)/include/asm/checkpoint_hdr.h -endif +CKPT_INCLUDE = -I./include +CKPT_HEADERS = $(shell find ./include -name '*.h') # compile with debug ? DEBUG = -DCHECKPOINT_DEBUG @@ -39,6 +20,8 @@ OTHER = ckptinfo_types.c LDLIBS = -lm +.PHONY: all distclean clean headers install + all: $(PROGS) @make -C test @@ -56,10 +39,16 @@ ckptinfo_types.c: $(CKPT_HEADERS) ckptinfo.py %.o: %.c +headers: + ./scripts/extract-headers.sh -s ../linux-2.6.git + install: @echo /usr/bin/install -m 755 mktree ckpt rstr ckptinfo $(INSTALL_DIR) @/usr/bin/install -m 755 mktree ckpt rstr ckptinfo $(INSTALL_DIR) +distclean: clean + @rm -f $(CKPT_HEADERS) + clean: @rm -f $(PROGS) $(OTHER) *~ *.o @make -C test clean diff --git a/ckpt.c b/ckpt.c index b3f8dea..fb853f9 100644 --- a/ckpt.c +++ b/ckpt.c @@ -16,6 +16,7 @@ #include <unistd.h> #include <sys/syscall.h> +#include <linux/checkpoint_syscalls.h> #include <linux/checkpoint.h> static char usage_str[] = diff --git a/ckptinfo.c b/ckptinfo.c index 962a62f..2b8aaef 100644 --- a/ckptinfo.c +++ b/ckptinfo.c @@ -17,6 +17,8 @@ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> +#include <sys/socket.h> +#include <sys/un.h> #include <linux/checkpoint_hdr.h> #include <asm/checkpoint_hdr.h> diff --git a/ckptinfo.py b/ckptinfo.py index ae7e5da..e0959f1 100755 --- a/ckptinfo.py +++ b/ckptinfo.py @@ -78,6 +78,8 @@ print """ * This file is auto-generated by ckptinfo.py */ +#include <sys/socket.h> +#include <sys/un.h> #include <linux/checkpoint_hdr.h> """ diff --git a/include/asm/checkpoint_hdr.h b/include/asm/checkpoint_hdr.h new file mode 100644 index 0000000..57f3635 --- /dev/null +++ b/include/asm/checkpoint_hdr.h @@ -0,0 +1,205 @@ +/* + * Generated by extract-headers.sh. + */ +#ifndef __ASM_CHECKPOINT_HDR_H_ +#define __ASM_CHECKPOINT_HDR_H_ +#include <sys/user.h> + +#if __s390x__ + +/* + * Checkpoint/restart - architecture specific headers s/390 + * + * Copyright IBM Corp. 2009 + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of the Linux + * distribution for more details. + */ + +#include <linux/types.h> +#include <asm/ptrace.h> + +/* + * Notes + * NUM_GPRS defined in <asm/ptrace.h> to be 16 + * NUM_FPRS defined in <asm/ptrace.h> to be 16 + * NUM_APRS defined in <asm/ptrace.h> to be 16 + * NUM_CR_WORDS defined in <asm/ptrace.h> to be 3 + */ +struct ckpt_hdr_cpu { + struct ckpt_hdr h; + __u64 args[1]; + __u64 gprs[NUM_GPRS]; + __u64 orig_gpr2; + __u16 svcnr; + __u16 ilc; + __u32 acrs[NUM_ACRS]; + __u64 ieee_instruction_pointer; + + /* psw_t */ + __u64 psw_t_mask; + __u64 psw_t_addr; + + /* s390_fp_regs_t */ + __u32 fpc; + union { + float f; + double d; + __u64 ui; + struct { + __u32 fp_hi; + __u32 fp_lo; + } fp; + } fprs[NUM_FPRS]; + + /* per_struct */ + __u64 per_control_regs[NUM_CR_WORDS]; + __u64 starting_addr; + __u64 ending_addr; + __u64 address; + __u16 perc_atmid; + __u8 access_id; + __u8 single_step; + __u8 instruction_fetch; +}; + +struct ckpt_hdr_mm_context { + struct ckpt_hdr h; + unsigned long vdso_base; + int noexec; + int has_pgste; + int alloc_pgste; + unsigned long asce_bits; + unsigned long asce_limit; +}; + +#define CKPT_ARCH_NSIG 64 + +struct ckpt_hdr_header_arch { + struct ckpt_hdr h; +}; + + +#elif __i386__ || __x86_64__ + +/* + * Checkpoint/restart - architecture specific headers x86 + * + * Copyright (C) 2008-2009 Oren Laadan + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of the Linux + * distribution for more details. + */ + +#include <linux/types.h> + +/* + * To maintain compatibility between 32-bit and 64-bit architecture flavors, + * keep data 64-bit aligned: use padding for structure members, and use + * __attribute__((aligned (8))) for the entire structure. + * + * Quoting Arnd Bergmann: + * "This structure has an odd multiple of 32-bit members, which means + * that if you put it into a larger structure that also contains 64-bit + * members, the larger structure may get different alignment on x86-32 + * and x86-64, which you might want to avoid. I can't tell if this is + * an actual problem here. ... In this case, I'm pretty sure that + * sizeof(ckpt_hdr_task) on x86-32 is different from x86-64, since it + * will be 32-bit aligned on x86-32." + */ + +/* i387 structure seen from kernel/userspace */ + +/* arch dependent header types */ +enum { + CKPT_HDR_CPU_FPU = 201, + CKPT_HDR_MM_CONTEXT_LDT, +}; + +#define CKPT_ARCH_NSIG 64 + +struct ckpt_hdr_header_arch { + struct ckpt_hdr h; + /* FIXME: add HAVE_HWFP */ + __u16 has_fxsr; + __u16 has_xsave; + __u16 xstate_size; + __u16 _pading; +} __attribute__((aligned(8))); + +struct ckpt_hdr_thread { + struct ckpt_hdr h; + __u32 thread_info_flags; + __u16 gdt_entry_tls_entries; + __u16 sizeof_tls_array; +} __attribute__((aligned(8))); + +/* designed to work for both x86_32 and x86_64 */ +struct ckpt_hdr_cpu { + struct ckpt_hdr h; + /* see struct pt_regs (x86_64) */ + __u64 r15; + __u64 r14; + __u64 r13; + __u64 r12; + __u64 bp; + __u64 bx; + __u64 r11; + __u64 r10; + __u64 r9; + __u64 r8; + __u64 ax; + __u64 cx; + __u64 dx; + __u64 si; + __u64 di; + __u64 orig_ax; + __u64 ip; + __u64 sp; + + __u64 flags; + + /* segment registers */ + __u64 fs; + __u64 gs; + + __u16 fsindex; + __u16 gsindex; + __u16 cs; + __u16 ss; + __u16 ds; + __u16 es; + + __u32 used_math; + + /* debug registers */ + __u64 debugreg0; + __u64 debugreg1; + __u64 debugreg2; + __u64 debugreg3; + __u64 debugreg6; + __u64 debugreg7; + + /* thread_xstate contents follow (if used_math) */ +} __attribute__((aligned(8))); + +#define CKPT_X86_SEG_NULL 0 +#define CKPT_X86_SEG_USER32_CS 1 +#define CKPT_X86_SEG_USER32_DS 2 +#define CKPT_X86_SEG_TLS 0x4000 /* 0100 0000 0000 00xx */ +#define CKPT_X86_SEG_LDT 0x8000 /* 100x xxxx xxxx xxxx */ + +struct ckpt_hdr_mm_context { + struct ckpt_hdr h; + __u64 vdso; + __u32 ldt_entry_size; + __u32 nldt; +} __attribute__((aligned(8))); + + +#else +#error "Architecture does not have definitons needed for checkpoint images." +#endif +#endif /* __ASM_CHECKPOINT_HDR_H_ */ diff --git a/include/linux/checkpoint.h b/include/linux/checkpoint.h new file mode 100644 index 0000000..db6c6a4 --- /dev/null +++ b/include/linux/checkpoint.h @@ -0,0 +1,26 @@ +/* + * Generated by extract-headers.sh. + */ +#ifndef _LINUX_CHECKPOINT_H_ +#define _LINUX_CHECKPOINT_H_ +/* + * Generic checkpoint-restart + * + * Copyright (C) 2008-2009 Oren Laadan + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of the Linux + * distribution for more details. + */ + +#define CHECKPOINT_VERSION 1 + +/* checkpoint user flags */ +#define CHECKPOINT_SUBTREE 0x1 + +/* restart user flags */ +#define RESTART_TASKSELF 0x1 +#define RESTART_FROZEN 0x2 + + +#endif /* _LINUX_CHECKPOINT_H_ */ diff --git a/include/linux/checkpoint_hdr.h b/include/linux/checkpoint_hdr.h new file mode 100644 index 0000000..a6f4a57 --- /dev/null +++ b/include/linux/checkpoint_hdr.h @@ -0,0 +1,580 @@ +/* + * Generated by extract-headers.sh. + */ +#ifndef _CHECKPOINT_CKPT_HDR_H_ +#define _CHECKPOINT_CKPT_HDR_H_ +/* + * Generic container checkpoint-restart + * + * Copyright (C) 2008-2009 Oren Laadan + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of the Linux + * distribution for more details. + */ + +#include <linux/types.h> +#include <linux/utsname.h> + +/* + * To maintain compatibility between 32-bit and 64-bit architecture flavors, + * keep data 64-bit aligned: use padding for structure members, and use + * __attribute__((aligned (8))) for the entire structure. + * + * Quoting Arnd Bergmann: + * "This structure has an odd multiple of 32-bit members, which means + * that if you put it into a larger structure that also contains 64-bit + * members, the larger structure may get different alignment on x86-32 + * and x86-64, which you might want to avoid. I can't tell if this is + * an actual problem here. ... In this case, I'm pretty sure that + * sizeof(ckpt_hdr_task) on x86-32 is different from x86-64, since it + * will be 32-bit aligned on x86-32." + */ + +/* + * header format: 'struct ckpt_hdr' must prefix all other headers. Therfore + * when a header is passed around, the information about it (type, size) + * is readily available. + */ +struct ckpt_hdr { + __u32 type; + __u32 len; +} __attribute__((aligned(8))); + +#include <asm/checkpoint_hdr.h> + +/* header types */ +enum { + CKPT_HDR_HEADER = 1, + CKPT_HDR_HEADER_ARCH, + CKPT_HDR_BUFFER, + CKPT_HDR_STRING, + CKPT_HDR_OBJREF, + + CKPT_HDR_TREE = 101, + CKPT_HDR_TASK, + CKPT_HDR_TASK_NS, + CKPT_HDR_TASK_OBJS, + CKPT_HDR_RESTART_BLOCK, + CKPT_HDR_THREAD, + CKPT_HDR_CPU, + CKPT_HDR_NS, + CKPT_HDR_UTS_NS, + CKPT_HDR_IPC_NS, + CKPT_HDR_CAPABILITIES, + CKPT_HDR_USER_NS, + CKPT_HDR_CRED, + CKPT_HDR_USER, + CKPT_HDR_GROUPINFO, + CKPT_HDR_TASK_CREDS, + + /* 201-299: reserved for arch-dependent */ + + CKPT_HDR_FILE_TABLE = 301, + CKPT_HDR_FILE_DESC, + CKPT_HDR_FILE_NAME, + CKPT_HDR_FILE, + CKPT_HDR_PIPE_BUF, + + CKPT_HDR_MM = 401, + CKPT_HDR_VMA, + CKPT_HDR_PGARR, + CKPT_HDR_MM_CONTEXT, + + CKPT_HDR_IPC = 501, + CKPT_HDR_IPC_SHM, + CKPT_HDR_IPC_MSG, + CKPT_HDR_IPC_MSG_MSG, + CKPT_HDR_IPC_SEM, + + CKPT_HDR_SIGHAND = 601, + + CKPT_HDR_FD_SOCKET = 701, + CKPT_HDR_SOCKET, + CKPT_HDR_SOCKET_QUEUE, + CKPT_HDR_SOCKET_BUFFER, + CKPT_HDR_SOCKET_UNIX, + + CKPT_HDR_TAIL = 9001, + + CKPT_HDR_ERROR = 9999, +}; + +/* architecture */ +enum { + /* do not change order (will break ABI) */ + CKPT_ARCH_X86_32 = 1, + CKPT_ARCH_S390X, +}; + +/* shared objrects (objref) */ +struct ckpt_hdr_objref { + struct ckpt_hdr h; + __u32 objtype; + __s32 objref; +} __attribute__((aligned(8))); + +/* shared objects types */ +enum obj_type { + CKPT_OBJ_IGNORE = 0, + CKPT_OBJ_INODE, + CKPT_OBJ_FILE_TABLE, + CKPT_OBJ_FILE, + CKPT_OBJ_MM, + CKPT_OBJ_SIGHAND, + CKPT_OBJ_NS, + CKPT_OBJ_UTS_NS, + CKPT_OBJ_IPC_NS, + CKPT_OBJ_USER_NS, + CKPT_OBJ_CRED, + CKPT_OBJ_USER, + CKPT_OBJ_GROUPINFO, + CKPT_OBJ_SOCK, + CKPT_OBJ_MAX +}; + +/* kernel constants */ +struct ckpt_hdr_const { + /* task */ + __u16 task_comm_len; + /* mm */ + __u16 mm_saved_auxv_len; + /* signal */ + __u16 signal_nsig; + /* uts */ + __u16 uts_sysname_len; + __u16 uts_nodename_len; + __u16 uts_release_len; + __u16 uts_version_len; + __u16 uts_machine_len; + __u16 uts_domainname_len; +} __attribute__((aligned(8))); + +/* checkpoint image header */ +struct ckpt_hdr_header { + struct ckpt_hdr h; + __u64 magic; + + __u16 arch_id; + + __u16 major; + __u16 minor; + __u16 patch; + __u16 rev; + + struct ckpt_hdr_const constants; + + __u64 time; /* when checkpoint taken */ + __u64 uflags; /* uflags from checkpoint */ + + /* + * the header is followed by three strings: + * char release[const.uts_release_len]; + * char version[const.uts_version_len]; + * char machine[const.uts_machine_len]; + */ +} __attribute__((aligned(8))); + +/* checkpoint image trailer */ +struct ckpt_hdr_tail { + struct ckpt_hdr h; + __u64 magic; +} __attribute__((aligned(8))); + +/* task tree */ +struct ckpt_hdr_tree { + struct ckpt_hdr h; + __s32 nr_tasks; +} __attribute__((aligned(8))); + +struct ckpt_hdr_pids { + __s32 vpid; + __s32 vppid; + __s32 vtgid; + __s32 vpgid; + __s32 vsid; +} __attribute__((aligned(8))); + +/* task data */ +struct ckpt_hdr_task { + struct ckpt_hdr h; + __u32 state; + __u32 exit_state; + __u32 exit_code; + __u32 exit_signal; + __u32 pdeath_signal; + + __u64 set_child_tid; + __u64 clear_child_tid; + + __u32 compat_robust_futex_head_len; + __u32 compat_robust_futex_list; /* a compat __user ptr */ + __u32 robust_futex_head_len; + __u64 robust_futex_list; /* a __user ptr */ + +} __attribute__((aligned(8))); + +/* Posix capabilities */ +struct ckpt_capabilities { + __u32 cap_i_0, cap_i_1; /* inheritable set */ + __u32 cap_p_0, cap_p_1; /* permitted set */ + __u32 cap_e_0, cap_e_1; /* effective set */ + __u32 cap_b_0, cap_b_1; /* bounding set */ + __u32 securebits; + __u32 padding; +} __attribute__((aligned(8))); + +struct ckpt_hdr_task_creds { + struct ckpt_hdr h; + __s32 cred_ref; + __s32 ecred_ref; +} __attribute__((aligned(8))); + +struct ckpt_hdr_cred { + struct ckpt_hdr h; + __u32 uid, suid, euid, fsuid; + __u32 gid, sgid, egid, fsgid; + __s32 user_ref; + __s32 groupinfo_ref; + struct ckpt_capabilities cap_s; +} __attribute__((aligned(8))); + +struct ckpt_hdr_groupinfo { + struct ckpt_hdr h; + __u32 ngroups; + /* + * This is followed by ngroups __u32s + */ + __u32 groups[0]; +} __attribute__((aligned(8))); + +/* + * todo - keyrings and LSM + * These may be better done with userspace help though + */ +struct ckpt_hdr_user_struct { + struct ckpt_hdr h; + __u32 uid; + __s32 userns_ref; +} __attribute__((aligned(8))); + +/* + * The user-struct mostly tracks system resource usage. + * Most of it's contents therefore will simply be set + * correctly as restart opens resources + */ +struct ckpt_hdr_user_ns { + struct ckpt_hdr h; + __s32 creator_ref; +} __attribute__((aligned(8))); + +/* namespaces */ +struct ckpt_hdr_task_ns { + struct ckpt_hdr h; + __s32 ns_objref; +} __attribute__((aligned(8))); + +struct ckpt_hdr_ns { + struct ckpt_hdr h; + __s32 uts_objref; + __u32 ipc_objref; +} __attribute__((aligned(8))); + +/* task's shared resources */ +struct ckpt_hdr_task_objs { + struct ckpt_hdr h; + + __s32 files_objref; + __s32 mm_objref; + __s32 sighand_objref; +} __attribute__((aligned(8))); + +/* restart blocks */ +struct ckpt_hdr_restart_block { + struct ckpt_hdr h; + __u64 function_type; + __u64 arg_0; + __u64 arg_1; + __u64 arg_2; + __u64 arg_3; + __u64 arg_4; +} __attribute__((aligned(8))); + +enum restart_block_type { + CKPT_RESTART_BLOCK_NONE = 1, + CKPT_RESTART_BLOCK_HRTIMER_NANOSLEEP, + CKPT_RESTART_BLOCK_POSIX_CPU_NANOSLEEP, + CKPT_RESTART_BLOCK_COMPAT_NANOSLEEP, + CKPT_RESTART_BLOCK_COMPAT_CLOCK_NANOSLEEP, + CKPT_RESTART_BLOCK_POLL, + CKPT_RESTART_BLOCK_FUTEX +}; + +/* file system */ +struct ckpt_hdr_file_table { + struct ckpt_hdr h; + __s32 fdt_nfds; +} __attribute__((aligned(8))); + +/* file descriptors */ +struct ckpt_hdr_file_desc { + struct ckpt_hdr h; + __s32 fd_objref; + __s32 fd_descriptor; + __u32 fd_close_on_exec; +} __attribute__((aligned(8))); + +enum file_type { + CKPT_FILE_IGNORE = 0, + CKPT_FILE_GENERIC, + CKPT_FILE_PIPE, + CKPT_FILE_FIFO, + CKPT_FILE_SOCKET, + CKPT_FILE_MAX +}; + +/* file objects */ +struct ckpt_hdr_file { + struct ckpt_hdr h; + __u32 f_type; + __u32 f_mode; + __u32 f_flags; + __s32 f_credref; + __u64 f_pos; + __u64 f_version; +} __attribute__((aligned(8))); + +struct ckpt_hdr_file_generic { + struct ckpt_hdr_file common; +} __attribute__((aligned(8))); + +struct ckpt_hdr_file_pipe { + struct ckpt_hdr_file common; + __s32 pipe_objref; +} __attribute__((aligned(8))); + +struct ckpt_hdr_file_socket { + struct ckpt_hdr_file common; +} __attribute__((aligned(8))); + +struct ckpt_hdr_utsns { + struct ckpt_hdr h; + char sysname[__NEW_UTS_LEN + 1]; + char nodename[__NEW_UTS_LEN + 1]; + char release[__NEW_UTS_LEN + 1]; + char version[__NEW_UTS_LEN + 1]; + char machine[__NEW_UTS_LEN + 1]; + char domainname[__NEW_UTS_LEN + 1]; +} __attribute__((aligned(8))); + +/* memory layout */ +struct ckpt_hdr_mm { + struct ckpt_hdr h; + __u32 map_count; + __s32 exe_objref; + + __u64 def_flags; + __u64 flags; + + __u64 start_code, end_code, start_data, end_data; + __u64 start_brk, brk, start_stack; + __u64 arg_start, arg_end, env_start, env_end; +} __attribute__((aligned(8))); + +/* vma subtypes - index into restore_vma_dispatch[] */ +enum vma_type { + CKPT_VMA_IGNORE = 0, + CKPT_VMA_VDSO, /* special vdso vma */ + CKPT_VMA_ANON, /* private anonymous */ + CKPT_VMA_FILE, /* private mapped file */ + CKPT_VMA_SHM_ANON, /* shared anonymous */ + CKPT_VMA_SHM_ANON_SKIP, /* shared anonymous (skip contents) */ + CKPT_VMA_SHM_FILE, /* shared mapped file, only msync */ + CKPT_VMA_SHM_IPC, /* shared sysvipc */ + CKPT_VMA_SHM_IPC_SKIP, /* shared sysvipc (skip contents) */ + CKPT_VMA_MAX, +}; + +/* vma descriptor */ +struct ckpt_hdr_vma { + struct ckpt_hdr h; + __u32 vma_type; + __s32 vma_objref; /* objref of backing file */ + __s32 ino_objref; /* objref of shared segment */ + __u32 _padding; + __u64 ino_size; /* size of shared segment */ + + __u64 vm_start; + __u64 vm_end; + __u64 vm_page_prot; + __u64 vm_flags; + __u64 vm_pgoff; +} __attribute__((aligned(8))); + +/* page array */ +struct ckpt_hdr_pgarr { + struct ckpt_hdr h; + __u64 nr_pages; /* number of pages to saved */ +} __attribute__((aligned(8))); + +/* signals */ +struct ckpt_hdr_sigset { + __u8 sigset[CKPT_ARCH_NSIG / 8]; +} __attribute__((aligned(8))); + +struct ckpt_hdr_sigaction { + __u64 _sa_handler; + __u64 sa_flags; + __u64 sa_restorer; + struct ckpt_hdr_sigset sa_mask; +} __attribute__((aligned(8))); + +struct ckpt_hdr_sighand { + struct ckpt_hdr h; + struct ckpt_hdr_sigaction action[0]; +} __attribute__((aligned(8))); + +/* ipc commons */ +struct ckpt_hdr_ipcns { + struct ckpt_hdr h; + __u64 shm_ctlmax; + __u64 shm_ctlall; + __s32 shm_ctlmni; + + __s32 msg_ctlmax; + __s32 msg_ctlmnb; + __s32 msg_ctlmni; + + __s32 sem_ctl_msl; + __s32 sem_ctl_mns; + __s32 sem_ctl_opm; + __s32 sem_ctl_mni; +} __attribute__((aligned(8))); + +struct ckpt_hdr_ipc { + struct ckpt_hdr h; + __u32 ipc_type; + __u32 ipc_count; +} __attribute__((aligned(8))); + +struct ckpt_hdr_ipc_perms { + struct ckpt_hdr h; + __s32 id; + __u32 key; + __u32 uid; + __u32 gid; + __u32 cuid; + __u32 cgid; + __u32 mode; + __u32 _padding; + __u64 seq; +} __attribute__((aligned(8))); + +struct ckpt_hdr_ipc_shm { + struct ckpt_hdr h; + struct ckpt_hdr_ipc_perms perms; + __u64 shm_segsz; + __u64 shm_atim; + __u64 shm_dtim; + __u64 shm_ctim; + __s32 shm_cprid; + __s32 shm_lprid; + __u32 mlock_uid; + __u32 flags; + __u32 objref; +} __attribute__((aligned(8))); + +struct ckpt_hdr_ipc_msg { + struct ckpt_hdr h; + struct ckpt_hdr_ipc_perms perms; + __u64 q_stime; + __u64 q_rtime; + __u64 q_ctime; + __u64 q_cbytes; + __u64 q_qnum; + __u64 q_qbytes; + __s32 q_lspid; + __s32 q_lrpid; +} __attribute__((aligned(8))); + +struct ckpt_hdr_ipc_msg_msg { + struct ckpt_hdr h; + __s32 m_type; + __u32 m_ts; +} __attribute__((aligned(8))); + +struct ckpt_hdr_ipc_sem { + struct ckpt_hdr h; + struct ckpt_hdr_ipc_perms perms; + __u64 sem_otime; + __u64 sem_ctime; + __u32 sem_nsems; +} __attribute__((aligned(8))); + +#define CKPT_UNIX_LINKED 1 +struct ckpt_hdr_socket_unix { + struct ckpt_hdr h; + __s32 this; + __s32 peer; + __u32 flags; + __u32 laddr_len; + __u32 raddr_len; + struct sockaddr_un laddr; + struct sockaddr_un raddr; +} __attribute__ ((aligned(8))); + +struct ckpt_hdr_socket { + struct ckpt_hdr h; + + struct { /* struct socket */ + __u64 flags; + __u8 state; + } socket __attribute__ ((aligned(8))); + + struct { /* struct sock_common */ + __u32 bound_dev_if; + __u32 reuse; + __u16 family; + __u8 state; + } sock_common __attribute__ ((aligned(8))); + + struct { /* struct sock */ + __s64 rcvlowat; + __u64 flags; + + __u32 err; + __u32 err_soft; + __u32 priority; + __s32 rcvbuf; + __s32 sndbuf; + __u16 type; + __s16 backlog; + + __u8 protocol; + __u8 state; + __u8 shutdown; + __u8 userlocks; + __u8 no_check; + + struct linger linger; + struct timeval rcvtimeo; + struct timeval sndtimeo; + + } sock __attribute__ ((aligned(8))); + +} __attribute__ ((aligned(8))); + +struct ckpt_hdr_socket_queue { + struct ckpt_hdr h; + __u32 skb_count; + __u32 total_bytes; +} __attribute__ ((aligned(8))); + +#define CKPT_TST_OVERFLOW_16(a,b) ((sizeof(a) > sizeof(b)) && ((a) > SHORT_MAX)) + +#define CKPT_TST_OVERFLOW_32(a,b) ((sizeof(a) > sizeof(b)) && ((a) > INT_MAX)) + +#define CKPT_TST_OVERFLOW_64(a,b) ((sizeof(a) > sizeof(b)) && ((a) > LONG_MAX)) + + +#endif /* _CHECKPOINT_CKPT_HDR_H_ */ diff --git a/include/linux/checkpoint_syscalls.h b/include/linux/checkpoint_syscalls.h new file mode 100644 index 0000000..2374bbc --- /dev/null +++ b/include/linux/checkpoint_syscalls.h @@ -0,0 +1,30 @@ +#ifndef _CHECKPOINT_SYSCALLS_H_ +#define _CHECKPOINT_SYSCALLS_H_ +/* + * Generated by extract-headers.sh. + */ + +#if __s390x__ + +# ifndef __NR_checkpoint +# define __NR_checkpoint 332 +# endif + +# ifndef __NR_restart +# define __NR_restart 333 +# endif + +#elif __i386__ + +# ifndef __NR_checkpoint +# define __NR_checkpoint 338 +# endif + +# ifndef __NR_restart +# define __NR_restart 339 +# endif + +#else +#error "Architecture does not have definitons for __NR_(checkpoint|restart)" +#endif +#endif /* _CHECKPOINT_SYSCALLS_H_ */ diff --git a/mktree.c b/mktree.c index e42407f..1f9e3d3 100644 --- a/mktree.c +++ b/mktree.c @@ -29,8 +29,12 @@ #include <asm/unistd.h> #include <sys/syscall.h> #include <sys/prctl.h> +#include <sys/socket.h> +#include <sys/un.h> #include <linux/sched.h> + +#include <linux/checkpoint_syscalls.h> #include <linux/checkpoint.h> #include <linux/checkpoint_hdr.h> diff --git a/rstr.c b/rstr.c index 9199cfe..8cd7a49 100644 --- a/rstr.c +++ b/rstr.c @@ -18,6 +18,7 @@ #include <asm/unistd.h> #include <sys/syscall.h> +#include <linux/checkpoint_syscalls.h> #include <linux/checkpoint.h> int main(int argc, char *argv[]) diff --git a/scripts/extract-headers.sh b/scripts/extract-headers.sh new file mode 100755 index 0000000..9e6ea4a --- /dev/null +++ b/scripts/extract-headers.sh @@ -0,0 +1,194 @@ +#!/bin/bash +# +# Copyright (C) 2009 IBM Corp. +# Author: Matt Helsley <matthltc@xxxxxxxxxx> +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file COPYING in the main directory of the Linux +# distribution for more details. +# + +# +# Sanitize checkpoint/restart kernel headers for userspace. +# + +function usage() +{ + echo "Usage: $0 [-h|--help] -s|--kernel-src=DIR" +} + +OUTPUT_INCLUDES="include" +OPTIONS=`getopt -o s:o:h --long kernel-src:,output:,help -- "$@"` +eval set -- "${OPTIONS}" +while true ; do + case "$1" in + -s|--kernel-src) + KERNELSRC="$2" + shift 2 ;; + -o|--output) + OUTPUT_INCLUDES="$2" + shift 2 ;; + -h|--help) + usage + exit 0 ;; + --) + shift + break ;; + *) + echo "Unknown option: $1" + shift + echo "Unparsed options: $@" + usage 1>&2 + exit 2 ;; + esac +done + +if [ -z "${KERNELSRC}" -o '!' -d "${KERNELSRC}" ]; then + usage 1>&2 + exit 2 +fi + +# +# Run the kernel header through cpp to strip out __KERNEL__ sections but try +# to leave the rest untouched. +# +function do_cpp () +{ + local CPP_FILE="$1" + local START_DEFINE="$2" + shift 2 + + # + # Hide #include directives then run cpp. Make cpp keep comments, not + # insert line numbers, avoid system/gcc/std defines, and only expand + # directives. Strip cpp output until we get to #define START_DEFINE, + # and collapse the excessive number of blank lines that cpp outputas + # in place of directives. + # + sed -e 's/#[[:space:]]*include[[:space:]]*\([<"][^">]*[">]\)/\/*#include \1*\//g' \ + "${CPP_FILE}" | \ + cpp -CC -P -U__KERNEL__ -undef -nostdinc \ + -fdirectives-only -dDI "$@" | \ + awk 'BEGIN { x = 0; } + /#define '"${START_DEFINE}"'/ { x = 1; next; } + (x == 1) { print }' | cat -s | \ + sed -e 's|/\*#include \([<"][^">]*[">]\)\*/|#include \1|g' + echo '' +} + +# Map KARCH to something suitable for CPP e.g. __i386__ +function karch_to_cpparch () +{ + local KARCH="$1" + local WORDBITS="$2" + shift 2; + + case "${KARCH}" in + x86) [ "${WORDBITS}" == "32" ] && echo -n "i386" + [ "${WORDBITS}" == "64" ] && echo -n "x86_64" + [ -z "${WORDBITS}" ] && echo -n 'i386__ || __x86_64' # HACK + ;; + s390*) echo -n "s390x" ;; + *) echo -n "${KARCH}" ;; + esac + return 0 +} + +set -e + +mkdir -p "${OUTPUT_INCLUDES}/linux" +mkdir -p "${OUTPUT_INCLUDES}/asm" + +cat - > "${OUTPUT_INCLUDES}/linux/checkpoint.h" <<-EOFOFEE +/* + * Generated by $(basename "$0"). + */ +#ifndef _LINUX_CHECKPOINT_H_ +#define _LINUX_CHECKPOINT_H_ +EOFOFEE + +do_cpp "${KERNELSRC}/include/linux/checkpoint.h" "_LINUX_CHECKPOINT_H_" >> "${OUTPUT_INCLUDES}/linux/checkpoint.h" +echo '#endif /* _LINUX_CHECKPOINT_H_ */' >> "${OUTPUT_INCLUDES}/linux/checkpoint.h" + +cat - > "${OUTPUT_INCLUDES}/linux/checkpoint_hdr.h" <<-EOFOO +/* + * Generated by $(basename "$0"). + */ +#ifndef _CHECKPOINT_CKPT_HDR_H_ +#define _CHECKPOINT_CKPT_HDR_H_ +EOFOO + +do_cpp "${KERNELSRC}/include/linux/checkpoint_hdr.h" "_CHECKPOINT_CKPT_HDR_H_" >> "${OUTPUT_INCLUDES}/linux/checkpoint_hdr.h" +echo '#endif /* _CHECKPOINT_CKPT_HDR_H_ */' >> "${OUTPUT_INCLUDES}/linux/checkpoint_hdr.h" + +( +# +# We use ARCH_COND to break up architecture-specific sections of the header. +# +ARCH_COND='#if' +REGEX='[[:space:]]*#[[:space:]]*define[[:space:]]+__NR_(checkpoint|restart)[[:space:]]+[[:digit:]]+' + +cat - <<-EOFOE +#ifndef _CHECKPOINT_SYSCALLS_H_ +#define _CHECKPOINT_SYSCALLS_H_ +/* + * Generated by $(basename "$0"). + */ + +EOFOE + +find "${KERNELSRC}/arch" -name 'unistd*.h' -print | sort | \ +while read UNISTDH ; do + [ -n "${UNISTDH}" ] || continue + grep -q -E "${REGEX}" "${UNISTDH}" || continue + + KARCH=$(echo "${UNISTDH}" | sed -e 's|.*/arch/\([^/]\+\)/.*|\1|') + WORDBITS=$(basename "${UNISTDH}" | sed -e 's/unistd_*\([[:digit:]]\+\)\.h/\1/') + CPPARCH="$(karch_to_cpparch "${KARCH}" "${WORDBITS}")" + echo -e "${ARCH_COND} __${CPPARCH}__\\n" + grep -E "${REGEX}" "${UNISTDH}" | \ + sed -e 's/^[[:space:]]*#[[:space:]]*define[[:space:]]\+__NR_\([^[:space:]]\+\)[[:space:]]\+\([^[:space:]]\+\).*$/#\tifndef __NR_\1\n#\t\tdefine __NR_\1 \2\n#\tendif\n/' + ARCH_COND='#elif' +done + +cat - <<-EOFOFOE +#else +#error "Architecture does not have definitons for __NR_(checkpoint|restart)" +#endif +#endif /* _CHECKPOINT_SYSCALLS_H_ */ +EOFOFOE + +) > "${OUTPUT_INCLUDES}/linux/checkpoint_syscalls.h" + +( +ARCH_COND='#if' + +cat - <<-EOFOEOF +/* + * Generated by $(basename "$0"). + */ +#ifndef __ASM_CHECKPOINT_HDR_H_ +#define __ASM_CHECKPOINT_HDR_H_ +#include <sys/user.h> + +EOFOEOF + +find "${KERNELSRC}/arch" -name 'checkpoint_hdr.h' -print | sort | \ +while read ARCH_CHECKPOINT_HDR_H ; do + [ -n "${ARCH_CHECKPOINT_HDR_H}" ] || continue + + KARCH=$(echo "${ARCH_CHECKPOINT_HDR_H}" | sed -e 's|.*/arch/\([^/]\+\)/.*|\1|') + CPPARCH="$(karch_to_cpparch "${KARCH}" "")" + echo -e "${ARCH_COND} __${CPPARCH}__\\n" + do_cpp "${KERNELSRC}/arch/${KARCH}/include/asm/checkpoint_hdr.h" '__ASM.*_CKPT_HDR_H' -D_CHECKPOINT_CKPT_HDR_H_ + ARCH_COND='#elif' +done + +cat - <<-FOEOEOF +#else +#error "Architecture does not have definitons needed for checkpoint images." +#endif +#endif /* __ASM_CHECKPOINT_HDR_H_ */ +FOEOEOF + +) > "${OUTPUT_INCLUDES}/asm/checkpoint_hdr.h" diff --git a/self.c b/self.c index 546fa04..a2f2fb9 100644 --- a/self.c +++ b/self.c @@ -16,6 +16,7 @@ #include <math.h> #include <sys/syscall.h> +#include <linux/checkpoint_syscalls.h> #include <linux/checkpoint.h> #define OUTFILE "/tmp/cr-self.out" -- 1.5.6.3 _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/containers