[vz8,2/4] ia32: add 32-bit vdso virtualization.

Submitted by Andrey Ryabinin on Oct. 22, 2020, 3:02 p.m.

Details

Message ID 20201022150223.17756-2-aryabinin@virtuozzo.com
State New
Series "Series without cover letter"
Headers show

Commit Message

Andrey Ryabinin Oct. 22, 2020, 3:02 p.m.
Similarly to the 64-bit vdso, make 32-bit vdso mapping per-ve.
This will allow per container modification of the linux version
xin .note section of vdso and monotonic time.

https://jira.sw.ru/browse/PSBM-121668
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 arch/x86/entry/vdso/vma.c    |  4 ++--
 arch/x86/kernel/process_64.c |  2 +-
 include/linux/ve.h           |  1 +
 kernel/ve/ve.c               | 35 +++++++++++++++++++++--------------
 4 files changed, 25 insertions(+), 17 deletions(-)

Patch hide | download patch | download mbox

diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index c48deffc1473..538c6730f436 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -56,7 +56,7 @@  static void vdso_fix_landing(const struct vdso_image *image,
 		struct vm_area_struct *new_vma)
 {
 #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
-	if (in_ia32_syscall() && image == &vdso_image_32) {
+	if (in_ia32_syscall() && image == get_exec_env()->vdso_32) {
 		struct pt_regs *regs = current_pt_regs();
 		unsigned long vdso_land = image->sym_int80_landing_pad;
 		unsigned long old_land_addr = vdso_land +
@@ -281,7 +281,7 @@  static int load_vdso32(void)
 	if (vdso32_enabled != 1)  /* Other values all mean "disabled" */
 		return 0;
 
-	return map_vdso(&vdso_image_32, 0);
+	return map_vdso(get_exec_env()->vdso_32, 0);
 }
 #endif
 
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index a010d4b9d126..dddd22215141 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -686,7 +686,7 @@  long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2)
 # endif
 # if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
 	case ARCH_MAP_VDSO_32:
-		return prctl_map_vdso(&vdso_image_32, arg2);
+		return prctl_map_vdso(get_exec_env()->vdso_32, arg2);
 # endif
 	case ARCH_MAP_VDSO_64:
 		return prctl_map_vdso(get_exec_env()->vdso_64, arg2);
diff --git a/include/linux/ve.h b/include/linux/ve.h
index 0e85a4032c3a..5b1962ff4c66 100644
--- a/include/linux/ve.h
+++ b/include/linux/ve.h
@@ -95,6 +95,7 @@  struct ve_struct {
 	struct cn_private	*cn;
 #endif
 	struct vdso_image	*vdso_64;
+	struct vdso_image	*vdso_32;
 };
 
 #define VE_MEMINFO_DEFAULT	1	/* default behaviour */
diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c
index 186deb3f88f4..03b8d126a0ed 100644
--- a/kernel/ve/ve.c
+++ b/kernel/ve/ve.c
@@ -58,6 +58,7 @@  struct ve_struct ve0 = {
 	.netns_max_nr		= INT_MAX,
 	.meminfo_val		= VE_MEMINFO_SYSTEM,
 	.vdso_64		= (struct vdso_image*)&vdso_image_64,
+	.vdso_32		= (struct vdso_image*)&vdso_image_32,
 };
 EXPORT_SYMBOL(ve0);
 
@@ -540,13 +541,12 @@  static __u64 ve_setup_iptables_mask(__u64 init_mask)
 }
 #endif
 
-static int copy_vdso(struct ve_struct *ve)
+static int copy_vdso(struct vdso_image **vdso_dst, const struct vdso_image *vdso_src)
 {
-	const struct vdso_image *vdso_src = &vdso_image_64;
 	struct vdso_image *vdso;
 	void *vdso_data;
 
-	if (ve->vdso_64)
+	if (*vdso_dst)
 		return 0;
 
 	vdso = kmemdup(vdso_src, sizeof(*vdso), GFP_KERNEL);
@@ -563,10 +563,22 @@  static int copy_vdso(struct ve_struct *ve)
 
 	vdso->data = vdso_data;
 
-	ve->vdso_64 = vdso;
+	*vdso_dst = vdso;
 	return 0;
 }
 
+static void ve_free_vdso(struct ve_struct *ve)
+{
+	if (ve->vdso_64 && ve->vdso_64 != &vdso_image_64) {
+		kfree(ve->vdso_64->data);
+		kfree(ve->vdso_64);
+	}
+	if (ve->vdso_32 && ve->vdso_32 != &vdso_image_32) {
+		kfree(ve->vdso_32->data);
+		kfree(ve->vdso_32);
+	}
+}
+
 static struct cgroup_subsys_state *ve_create(struct cgroup_subsys_state *parent_css)
 {
 	struct ve_struct *ve = &ve0;
@@ -592,7 +604,10 @@  static struct cgroup_subsys_state *ve_create(struct cgroup_subsys_state *parent_
 	if (err)
 		goto err_log;
 
-	if (copy_vdso(ve))
+	if (copy_vdso(&ve->vdso_64, &vdso_image_64))
+		goto err_vdso;
+
+	if (copy_vdso(&ve->vdso_32, &vdso_image_32))
 		goto err_vdso;
 
 	ve->features = VE_FEATURES_DEF;
@@ -619,6 +634,7 @@  static struct cgroup_subsys_state *ve_create(struct cgroup_subsys_state *parent_
 	return &ve->css;
 
 err_vdso:
+	ve_free_vdso(ve);
 	ve_log_destroy(ve);
 err_log:
 	free_percpu(ve->sched_lat_ve.cur);
@@ -658,15 +674,6 @@  static void ve_offline(struct cgroup_subsys_state *css)
 	ve->ve_name = NULL;
 }
 
-static void ve_free_vdso(struct ve_struct *ve)
-{
-	if (ve->vdso_64 == &vdso_image_64)
-		return;
-
-	kfree(ve->vdso_64->data);
-	kfree(ve->vdso_64);
-}
-
 static void ve_destroy(struct cgroup_subsys_state *css)
 {
 	struct ve_struct *ve = css_to_ve(css);