@@ -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
@@ -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))
@@ -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
@@ -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
@@ -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);
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(+)