[RHEL8,COMMIT] ve: patch linux_version_code in vdso

Submitted by Konstantin Khorenko on Oct. 29, 2020, 11:17 a.m.

Details

Message ID 202010291117.09TBHARt1545738@finist-co8.sw.ru
State New
Series "Series without cover letter"
Headers show

Commit Message

Konstantin Khorenko Oct. 29, 2020, 11:17 a.m.
The commit is pushed to "branch-rh8-4.18.0-193.6.3.vz8.4.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-193.6.3.vz8.4.14
------>
commit d2dddf67715a3f3e9bd39e5074a9e9471c78e6ab
Author: Andrey Ryabinin <aryabinin@virtuozzo.com>
Date:   Thu Oct 29 14:17:10 2020 +0300

    ve: patch linux_version_code in vdso
    
    On the write to ve.os_release file patch the linux_version_code
    in the .note section of vdso.
    
    https://jira.sw.ru/browse/PSBM-121668
    Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 arch/x86/entry/vdso/vdso-note.S   | 2 ++
 arch/x86/entry/vdso/vdso2c.c      | 1 +
 arch/x86/entry/vdso/vdso32/note.S | 2 ++
 arch/x86/include/asm/vdso.h       | 1 +
 kernel/ve/ve.c                    | 7 +++++++
 5 files changed, 13 insertions(+)

Patch hide | download patch | download mbox

diff --git a/arch/x86/entry/vdso/vdso-note.S b/arch/x86/entry/vdso/vdso-note.S
index 79a071e4357e..c0e6e65f9fec 100644
--- a/arch/x86/entry/vdso/vdso-note.S
+++ b/arch/x86/entry/vdso/vdso-note.S
@@ -7,6 +7,8 @@ 
 #include <linux/version.h>
 #include <linux/elfnote.h>
 
+	.globl linux_version_code
 ELFNOTE_START(Linux, 0, "a")
+linux_version_code:
 	.long LINUX_VERSION_CODE
 ELFNOTE_END
diff --git a/arch/x86/entry/vdso/vdso2c.c b/arch/x86/entry/vdso/vdso2c.c
index 4674f58581a1..7fab0bd96ac1 100644
--- a/arch/x86/entry/vdso/vdso2c.c
+++ b/arch/x86/entry/vdso/vdso2c.c
@@ -109,6 +109,7 @@  struct vdso_sym required_syms[] = {
 	{"__kernel_sigreturn", true},
 	{"__kernel_rt_sigreturn", true},
 	{"int80_landing_pad", true},
+	{"linux_version_code", true},
 };
 
 __attribute__((format(printf, 1, 2))) __attribute__((noreturn))
diff --git a/arch/x86/entry/vdso/vdso32/note.S b/arch/x86/entry/vdso/vdso32/note.S
index 9fd51f206314..096b62f14863 100644
--- a/arch/x86/entry/vdso/vdso32/note.S
+++ b/arch/x86/entry/vdso/vdso32/note.S
@@ -10,7 +10,9 @@ 
 /* Ideally this would use UTS_NAME, but using a quoted string here
    doesn't work. Remember to change this when changing the
    kernel's name. */
+	.globl linux_version_code
 ELFNOTE_START(Linux, 0, "a")
+linux_version_code:
 	.long LINUX_VERSION_CODE
 ELFNOTE_END
 
diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h
index 27566e57e87d..92c7ac06828e 100644
--- a/arch/x86/include/asm/vdso.h
+++ b/arch/x86/include/asm/vdso.h
@@ -27,6 +27,7 @@  struct vdso_image {
 	long sym___kernel_rt_sigreturn;
 	long sym___kernel_vsyscall;
 	long sym_int80_landing_pad;
+	long sym_linux_version_code;
 };
 
 #ifdef CONFIG_X86_64
diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c
index 9bf1515a6c3a..060f9ecc477e 100644
--- a/kernel/ve/ve.c
+++ b/kernel/ve/ve.c
@@ -954,6 +954,7 @@  static ssize_t ve_os_release_write(struct kernfs_open_file *of, char *buf,
 {
 	struct cgroup_subsys_state *css = of_css(of);
 	struct ve_struct *ve = css_to_ve(css);
+	int n1, n2, n3, new_version;
 	char *release;
 	int ret = 0;
 
@@ -964,6 +965,12 @@  static ssize_t ve_os_release_write(struct kernfs_open_file *of, char *buf,
 		goto up_opsem;
 	}
 
+	if (sscanf(buf, "%d.%d.%d", &n1, &n2, &n3) == 3) {
+		new_version = ((n1 << 16) + (n2 << 8)) + n3;
+		*((int *)(ve->vdso_64->data + ve->vdso_64->sym_linux_version_code)) = new_version;
+		*((int *)(ve->vdso_32->data + ve->vdso_32->sym_linux_version_code)) = new_version;
+	}
+
 	down_write(&uts_sem);
 	release = ve->ve_ns->uts_ns->name.release;
 	strncpy(release, buf, __NEW_UTS_LEN);