[CRIU] [PATCH 1/4] vdso: Introduce vdso engine

Pavel Emelyanov xemul at parallels.com
Wed May 22 04:56:57 EDT 2013


Split the patch. It contains too many independent pieces of code.

> +++ b/arch/x86/vdso.c

> +static const char vdso_ident[] = {
> +	0x7f, 0x45, 0x4c, 0x46, 0x02, 0x01, 0x01, 0x00,
> +	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +};

What is this? Where did these numbers come from?

> +/*
> + * FIXME Usually vDSO memory area has predefined structure (ie section
> + *       indices, thus we can optimize this routine and don't walk
> + *       over all sections but probe predefined first and if fail do
> + *       a complete walk over sections, this will speedup procedure
> + *       significantly.
> + *
> + *       Also we need more strict checking for section sizes and addresses
> + *       we obtain here -- there is no guarantee that data is always valid
> + *       (as it's assumed now).
> + */
> +int arch_parse_vdso(char *mem, size_t size, symtable_t *t)
> +{

What does "parse" wrt VDSO mean?

> +#define PM_PSHIFT_BITS      (6)
> +#define PM_STATUS_BITS      (3)
> +#define PM_STATUS_OFFSET    (64 - PM_STATUS_BITS)
> +#define PM_PSHIFT_OFFSET    (PM_STATUS_OFFSET - PM_PSHIFT_BITS)
> +#define PM_PFRAME_MASK      ((1ULL << PM_PSHIFT_OFFSET) - 1)
> +#define PM_PFRAME(x)        ((x) & PM_PFRAME_MASK)

We already have pagemap-related constants in mem.c. All should be in one place.

> +++ b/include/vdso.h

> +enum {
> +	VDSO_SYMBOL_GETTIMEOFDAY	= 0,

Doesn't enum auto-assign zero to the 1st member?

> +	VDSO_SYMBOL_GETCPU,
> +	VDSO_SYMBOL_CLOCK_GETTIME,
> +	VDSO_SYMBOL_TIME,
> +
> +	VDSO_SYMBOL_MAX
> +};

> +static inline bool vdso_is_symtable_empty(symtable_t *s)
> +{

Make the name more English, please.


Now concerning the below flood of symbols:

> +typedef struct vdso_mark_s {
> +	union {
> +		unsigned char	mag[SELFMAG];
> +		u32		_mag;

Why do you need this union?

> +	};
> +	union {
> +		unsigned char	sig[VDSO_MARK_SIG_SIZE];
> +		u64		_sig;

And this? What if sizeof(sig) != sizeof(sig)? Will it crash?

> +	};
> +	unsigned long		ref;

What is this field for?

> +} __packed vdso_mark_t;
> +
> +#define VDSO_MARK_INIT						\
> +	{							\
> +		.mag	= {					\
> +			0x7f, 0x45, 0x4c, 0x46,			\
> +		},						\
> +								\
> +		/* This is VDSO_PROXY_SIG string */		\
> +		.sig	= {					\
> +			0x63, 0x72, 0x69, 0x75,			\
> +			0x76, 0x64, 0x73, 0x6f,			\

That's not nice to have the same string coded twice, one time in
letters, the other one in digits.

> +		},						\
> +		.ref	= VDSO_BAD_ADDR,			\
> +	}
> +
> +#define INIT_VDSO_MARK(m)					\
> +	*(m) = (vdso_mark_t)VDSO_MARK_INIT
> +
> +static inline int is_vdso_mark(void *addr)
> +{
> +	vdso_mark_t s = VDSO_MARK_INIT;
> +	vdso_mark_t *d = addr;
> +
> +	BUILD_BUG_ON(sizeof(s._mag) != sizeof(s.mag));
> +	BUILD_BUG_ON(sizeof(s._sig) != sizeof(s.sig));
> +
> +	return s._mag == d->_mag && s._sig == d->_sig;

So all of the above are just to compare two 64-bit integers?

> +}

Summary: This is horrible.


> +
> +int vdso_init(void)
> +{
> +	if (arch_parse_self_vdso(&vdso_proxy.sym_rt))
> +		return -1;
> +	if (arch_get_vdso_pfn(getpid(), vdso_proxy.sym_rt.vma_start, &vdso_pfn))
> +		return -1;
> +	return 0;
> +}
> +

The arch_get_vdso_pfn should be in kerndat. Parsing self-vdso presumably there as well.

> +int vdso_analyse_vmas(struct list_head *vma_list)
> +{

Analyze for what?

> +int vdso_analyse_vmas(struct list_head *vma_list)
> +{
> +	bool has_vdso = false;
> +	struct vma_area *vma;
> +	unsigned int i;
> +
> +	pr_debug("Analysing dumpee VMAs\n");
> +
> +	list_for_each_entry(vma, vma_list, list) {
> +		if (!vma_entry_is(&vma->vma, VMA_AREA_VDSO))
> +			continue;
> +
> +		if (has_vdso) {
> +			pr_err("Got second vDSO area while only one expected\n");
> +			return -1;
> +		} else
> +			has_vdso = true;

Obfuscating else.

> +
> +		INIT_SYMTABLE(&vdso_proxy.sym_dumpee);
> +		vdso_proxy.remap_rt_at = 0;
> +		vdso_proxy.proxify = false;

You set it to true several lines of code below.

> +		vdso_proxy.directly = true;
> +
> +		vdso_proxy.premmaped_at = (unsigned long)vma_premmaped_start(&(vma->vma));
> +		vdso_proxy.sym_dumpee.vma_start = vma->vma.start;
> +		vdso_proxy.sym_dumpee.vma_end = vma->vma.end;
> +
> +		if (arch_parse_vdso((void *)vdso_proxy.premmaped_at,
> +				    symtable_vma_size(&vdso_proxy.sym_dumpee),
> +				    &vdso_proxy.sym_dumpee))
> +			return -1;
> +
> +		if (symtable_vma_size(&vdso_proxy.sym_dumpee) ==
> +		    symtable_vma_size(&vdso_proxy.sym_rt)) {
> +			for (i = 0; i < ARRAY_SIZE(vdso_proxy.sym_dumpee.sym); i++) {
> +				if (vdso_proxy.sym_dumpee.sym[i].offset !=
> +				    vdso_proxy.sym_rt.sym[i].offset) {
> +					vdso_proxy.directly = false;
> +					break;
> +				}
> +			}
> +		}
> +
> +		vdso_proxy.proxify = true;
> +	}
> +
> +	return 0;
> +}



More information about the CRIU mailing list