* [Devel] [PATCH hci-8.1 v2 0/4] mempolicy: prohibit mbind and set_mempolicy_home_node in VE
@ 2026-11-06 14:01 Konstantin Khorenko
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 1/4] " Konstantin Khorenko
` (4 more replies)
0 siblings, 5 replies; 10+ messages in thread
From: Konstantin Khorenko @ 2026-11-06 14:01 UTC (permalink / raw)
To: Pavel Tikhomirov, Vasileios Almpanis; +Cc: devel
A CT is meant to see a kernel without NUMA, so the NUMA API syscalls
return -ENOSYS in a non-super VE.
mbind(2) was blocked in vz7, but the vz8 port put its check into the
compat entry point only, and the compat entry points were dropped on
the rebase to RHEL9. Since then a CT task can bind its pages to nodes
and migrate them with mbind(2), while get_mempolicy(2) tells it there
is no NUMA.
set_mempolicy_home_node(2) appeared after vz7 and was never blocked. It
only sets the home node of a policy installed by mbind(2), so it goes
with it.
The tmpfs mpol= mount option sets such a policy for all files of a
mount, and a kernel without CONFIG_NUMA rejects it. It was never
blocked in a VE either.
- Patch 1 returns -ENOSYS from both in a non-super VE.
- Patch 2 adds a ve selftest: all six NUMA API syscalls, with arguments
that succeed on the host, must return -ENOSYS in a VE.
- Patch 3 rejects mpol= in a non-super VE the way a kernel without
CONFIG_NUMA does.
- Patch 4 adds a ve selftest: a tmpfs with mpol= is created on the
host and fails with -EINVAL in a VE.
The unmerged selftests series for VSTOR-137234 carries an older
ve_numa_syscalls_prohibited_test that covers four of the syscalls with
arguments that fail on the host anyway; this version replaces it.
Tested on a 4-node host, ve_numa_syscalls_prohibited_test:
+----------------------------+--------------+--------------------------+
| kernel | host calls | calls in a VE |
+----------------------------+--------------+--------------------------+
| vz10 without patch 1 | PASS | FAIL: mbind and |
| | | set_mempolicy_home_node |
| | | return 0 |
+----------------------------+--------------+--------------------------+
| vz10 with the series | PASS | PASS |
+----------------------------+--------------+--------------------------+
ve_numa_migrate_test still passes with the series.
Tested on a 1-node VM, ve_tmpfs_mpol_test:
+----------------------------+--------------+--------------------------+
| kernel | host mpol= | mpol= in a VE |
+----------------------------+--------------+--------------------------+
| vz10 without the series | PASS | FAIL: mpol= accepted |
+----------------------------+--------------+--------------------------+
| vz10 with the series | PASS | PASS |
+----------------------------+--------------+--------------------------+
Assisted-by: LLM
Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
Changes in v2:
- Patch 2: skip instead of failing when the host has no NUMA API
(Sashiko).
- New patches 3-4: reject the tmpfs mpol= mount option in a VE.
- Link to v1: http://lore.virtuozzo.com/20261105-b4-prep-khorenko-vstor-153679-mbind-ve-v1-0-b4fcd27c8001@virtuozzo.com
---
Konstantin Khorenko (4):
mempolicy: prohibit mbind and set_mempolicy_home_node in VE
selftests/ve: check that the NUMA API syscalls return ENOSYS in a VE
shmem: reject the mpol= mount option in VE
selftests/ve: check that tmpfs rejects mpol= in a VE
mm/mempolicy.c | 6 +
mm/shmem.c | 2 +-
tools/testing/selftests/ve/.gitignore | 2 +
tools/testing/selftests/ve/Makefile | 2 +
.../ve/ve_numa_syscalls_prohibited_test.c | 196 +++++++++++++++++++++
tools/testing/selftests/ve/ve_tmpfs_mpol_test.c | 123 +++++++++++++
6 files changed, 330 insertions(+), 1 deletion(-)
---
base-commit: 1f21db982845109040d1feb279e9ee34f8e6f065
change-id: 20261105-b4-prep-khorenko-vstor-153679-mbind-ve-bd811ea9be42
Best regards,
--
Konstantin Khorenko,
Virtuozzo Linux Kernel Team
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Devel] [PATCH hci-8.1 v2 1/4] mempolicy: prohibit mbind and set_mempolicy_home_node in VE
2026-11-06 14:01 [Devel] [PATCH hci-8.1 v2 0/4] mempolicy: prohibit mbind and set_mempolicy_home_node in VE Konstantin Khorenko
@ 2026-11-06 14:01 ` Konstantin Khorenko
2026-11-06 14:05 ` no-reply
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 2/4] selftests/ve: check that the NUMA API syscalls return ENOSYS in a VE Konstantin Khorenko
` (3 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Konstantin Khorenko @ 2026-11-06 14:01 UTC (permalink / raw)
To: Pavel Tikhomirov, Vasileios Almpanis; +Cc: devel
A CT is meant to see a kernel without NUMA support: in a non-super VE
the NUMA API syscalls return -ENOSYS, as they do in a kernel built
without CONFIG_NUMA.
Return -ENOSYS from mbind(2) and set_mempolicy_home_node(2) at the
start of the handler, before any argument check, as the other NUMA API
syscalls do.
Fixes: a803a5b2ea97 ("mempolicy: prohibit all NUMA API syscalls in VE")
https://virtuozzo.atlassian.net/browse/VSTOR-153679
Feature: mm: prohibit NUMA API inside CT
Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
mm/mempolicy.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 3255d3e987180..9b2a32ef92949 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1584,6 +1584,9 @@ SYSCALL_DEFINE4(set_mempolicy_home_node, unsigned long, start, unsigned long, le
int err = -ENOENT;
VMA_ITERATOR(vmi, mm, start);
+ if (!ve_is_super(get_exec_env()))
+ return -ENOSYS;
+
start = untagged_addr(start);
if (start & ~PAGE_MASK)
return -EINVAL;
@@ -1645,6 +1648,9 @@ SYSCALL_DEFINE6(mbind, unsigned long, start, unsigned long, len,
unsigned long, mode, const unsigned long __user *, nmask,
unsigned long, maxnode, unsigned int, flags)
{
+ if (!ve_is_super(get_exec_env()))
+ return -ENOSYS;
+
return kernel_mbind(start, len, mode, nmask, maxnode, flags);
}
--
2.43.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Devel] [PATCH hci-8.1 v2 2/4] selftests/ve: check that the NUMA API syscalls return ENOSYS in a VE
2026-11-06 14:01 [Devel] [PATCH hci-8.1 v2 0/4] mempolicy: prohibit mbind and set_mempolicy_home_node in VE Konstantin Khorenko
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 1/4] " Konstantin Khorenko
@ 2026-11-06 14:01 ` Konstantin Khorenko
2026-11-06 14:06 ` no-reply
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 3/4] shmem: reject the mpol= mount option in VE Konstantin Khorenko
` (2 subsequent siblings)
4 siblings, 1 reply; 10+ messages in thread
From: Konstantin Khorenko @ 2026-11-06 14:01 UTC (permalink / raw)
To: Pavel Tikhomirov, Vasileios Almpanis; +Cc: devel
A CT must see a kernel without NUMA, so all six NUMA API syscalls
return -ENOSYS in a non-super VE.
The test makes each call with arguments that succeed on the host and
checks that the host gets 0, while a task in a VE gets -ENOSYS. The
host result shows that the ENOSYS can only come from the VE check, not
from a bad argument.
https://virtuozzo.atlassian.net/browse/VSTOR-153679
Feature: mm: prohibit NUMA API inside CT
Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
tools/testing/selftests/ve/.gitignore | 1 +
tools/testing/selftests/ve/Makefile | 1 +
.../ve/ve_numa_syscalls_prohibited_test.c | 196 +++++++++++++++++++++
3 files changed, 198 insertions(+)
diff --git a/tools/testing/selftests/ve/.gitignore b/tools/testing/selftests/ve/.gitignore
index 3d1179bd2c5f4..5e07985c8fed3 100644
--- a/tools/testing/selftests/ve/.gitignore
+++ b/tools/testing/selftests/ve/.gitignore
@@ -4,3 +4,4 @@ ve_mount_accounting_test
ve_cpuid_override_test
ve_vtty_stress
ve_numa_migrate_test
+ve_numa_syscalls_prohibited_test
diff --git a/tools/testing/selftests/ve/Makefile b/tools/testing/selftests/ve/Makefile
index e96320a183844..451a7e1cc17d1 100644
--- a/tools/testing/selftests/ve/Makefile
+++ b/tools/testing/selftests/ve/Makefile
@@ -7,6 +7,7 @@ TEST_GEN_PROGS += ve_perms_test
TEST_GEN_PROGS += ve_mount_accounting_test
TEST_GEN_PROGS += ve_vtty_stress
TEST_GEN_PROGS += ve_numa_migrate_test
+TEST_GEN_PROGS += ve_numa_syscalls_prohibited_test
# CPUID faulting is x86-64 only. ARCH says "x86" for 32-bit too and lib.mk
# picks the clang target by its emptiness, so decide by the compiler.
diff --git a/tools/testing/selftests/ve/ve_numa_syscalls_prohibited_test.c b/tools/testing/selftests/ve/ve_numa_syscalls_prohibited_test.c
new file mode 100644
index 0000000000000..c76fcb1c79ff7
--- /dev/null
+++ b/tools/testing/selftests/ve/ve_numa_syscalls_prohibited_test.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Every NUMA API syscall works on the host and returns ENOSYS in a VE. */
+#define _GNU_SOURCE
+#include <errno.h>
+#include <sched.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <linux/mempolicy.h>
+
+#include "../kselftest_harness.h"
+#include "ve_selftest.h"
+
+#define NODE_BITS 1024
+#define LONG_BITS (8 * sizeof(unsigned long))
+
+static unsigned long node_mask[NODE_BITS / LONG_BITS];
+static void *page;
+static size_t page_size;
+
+static long call_get_mempolicy(void)
+{
+ int mode;
+
+ return syscall(__NR_get_mempolicy, &mode, NULL, 0UL, 0UL, 0UL);
+}
+
+static long call_set_mempolicy(void)
+{
+ return syscall(__NR_set_mempolicy, MPOL_DEFAULT, NULL, 0UL);
+}
+
+static long call_mbind(void)
+{
+ return syscall(__NR_mbind, page, page_size, MPOL_BIND, node_mask,
+ NODE_BITS + 1UL, 0U);
+}
+
+static long call_set_mempolicy_home_node(void)
+{
+ unsigned long node;
+
+ for (node = 0; node < NODE_BITS; node++)
+ if (node_mask[node / LONG_BITS] & (1UL << (node % LONG_BITS)))
+ break;
+ return syscall(__NR_set_mempolicy_home_node, page, page_size, node, 0UL);
+}
+
+static long call_migrate_pages(void)
+{
+ unsigned long none[NODE_BITS / LONG_BITS] = { 0 };
+
+ return syscall(__NR_migrate_pages, 0, NODE_BITS + 1UL, none, node_mask);
+}
+
+static long call_move_pages(void)
+{
+ return syscall(__NR_move_pages, 0, 0UL, NULL, NULL, NULL, 0);
+}
+
+/* set_mempolicy_home_node() needs the MPOL_BIND policy mbind() installs. */
+static const struct numa_call {
+ const char *name;
+ long (*call)(void);
+} numa_calls[] = {
+ { "get_mempolicy", call_get_mempolicy },
+ { "set_mempolicy", call_set_mempolicy },
+ { "mbind", call_mbind },
+ { "set_mempolicy_home_node", call_set_mempolicy_home_node },
+ { "migrate_pages", call_migrate_pages },
+ { "move_pages", call_move_pages },
+};
+
+#define NR_CALLS ARRAY_SIZE(numa_calls)
+
+struct call_result {
+ long ret;
+ int err;
+};
+
+static void run_calls(struct call_result *res)
+{
+ unsigned int i;
+
+ for (i = 0; i < NR_CALLS; i++) {
+ errno = 0;
+ res[i].ret = numa_calls[i].call();
+ res[i].err = errno;
+ }
+}
+
+FIXTURE(numa_syscalls)
+{
+ int cgv2_fd;
+ int ctid;
+};
+
+FIXTURE_SETUP(numa_syscalls)
+{
+ unsigned long allowed[NODE_BITS / LONG_BITS] = { 0 };
+ unsigned int i;
+ long ret;
+
+ self->cgv2_fd = -1;
+
+ if (geteuid() != 0)
+ SKIP(return, "creating a ve cgroup needs root");
+
+ page_size = getpagesize();
+ page = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ ASSERT_NE(page, MAP_FAILED);
+
+ ret = syscall(__NR_get_mempolicy, NULL, allowed, NODE_BITS + 1UL, 0UL,
+ MPOL_F_MEMS_ALLOWED);
+ if (ret == -1 && errno == ENOSYS)
+ SKIP(return, "no NUMA API on the host");
+ ASSERT_EQ(ret, 0);
+ for (i = 0; i < NODE_BITS; i++) {
+ if (allowed[i / LONG_BITS] & (1UL << (i % LONG_BITS))) {
+ node_mask[i / LONG_BITS] = 1UL << (i % LONG_BITS);
+ break;
+ }
+ }
+ ASSERT_LT(i, NODE_BITS);
+
+ self->cgv2_fd = mount_cg2_fd();
+ ASSERT_GE(self->cgv2_fd, 0);
+ ASSERT_EQ(write_file_at(self->cgv2_fd, "cgroup.subtree_control",
+ VE_CONTROLLERS), 0);
+
+ self->ctid = make_ve(self->cgv2_fd, CTID_MIN);
+ ASSERT_GE(self->ctid, 0);
+}
+
+FIXTURE_TEARDOWN(numa_syscalls)
+{
+ if (self->cgv2_fd >= 0) {
+ destroy_ve(self->cgv2_fd, self->ctid);
+ close(self->cgv2_fd);
+ }
+}
+
+TEST_F(numa_syscalls, host_calls_succeed)
+{
+ struct call_result res[NR_CALLS];
+ unsigned int i;
+
+ run_calls(res);
+ for (i = 0; i < NR_CALLS; i++) {
+ EXPECT_EQ(res[i].ret, 0)
+ TH_LOG("%s on the host: %s", numa_calls[i].name,
+ strerror(res[i].err));
+ }
+}
+
+TEST_F(numa_syscalls, ve_calls_return_enosys)
+{
+ struct call_result res[NR_CALLS];
+ int pipefd[2], status;
+ unsigned int i;
+ pid_t pid;
+
+ ASSERT_EQ(pipe(pipefd), 0);
+ pid = fork();
+ ASSERT_GE(pid, 0);
+ if (pid == 0) {
+ close(pipefd[0]);
+ if (enter_cgroup(self->cgv2_fd, self->ctid) < 0)
+ _exit(1);
+ if (unshare(CLONE_NEWVE) < 0)
+ _exit(2);
+ run_calls(res);
+ if (write(pipefd[1], res, sizeof(res)) != sizeof(res))
+ _exit(3);
+ _exit(0);
+ }
+ close(pipefd[1]);
+ ASSERT_EQ(waitpid(pid, &status, 0), pid);
+ ASSERT_TRUE(WIFEXITED(status));
+ ASSERT_EQ(WEXITSTATUS(status), 0)
+ TH_LOG("VE child setup failed at step %d", WEXITSTATUS(status));
+ ASSERT_EQ(read(pipefd[0], res, sizeof(res)), sizeof(res));
+ close(pipefd[0]);
+
+ for (i = 0; i < NR_CALLS; i++) {
+ EXPECT_TRUE(res[i].ret == -1 && res[i].err == ENOSYS)
+ TH_LOG("%s in a VE: returned %ld (%s), expected ENOSYS",
+ numa_calls[i].name, res[i].ret,
+ strerror(res[i].err));
+ }
+}
+
+TEST_HARNESS_MAIN
--
2.43.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Devel] [PATCH hci-8.1 v2 3/4] shmem: reject the mpol= mount option in VE
2026-11-06 14:01 [Devel] [PATCH hci-8.1 v2 0/4] mempolicy: prohibit mbind and set_mempolicy_home_node in VE Konstantin Khorenko
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 1/4] " Konstantin Khorenko
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 2/4] selftests/ve: check that the NUMA API syscalls return ENOSYS in a VE Konstantin Khorenko
@ 2026-11-06 14:01 ` Konstantin Khorenko
2026-11-06 14:05 ` no-reply
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 4/4] selftests/ve: check that tmpfs rejects mpol= in a VE Konstantin Khorenko
2026-11-06 14:19 ` [Devel] [PATCH hci-8.1 v2 0/4] mempolicy: prohibit mbind and set_mempolicy_home_node in VE Vasileios Almpanis
4 siblings, 1 reply; 10+ messages in thread
From: Konstantin Khorenko @ 2026-11-06 14:01 UTC (permalink / raw)
To: Pavel Tikhomirov, Vasileios Almpanis; +Cc: devel
A CT is meant to see a kernel without NUMA support, so the NUMA API
syscalls return -ENOSYS in a non-super VE. The tmpfs mpol= mount option
still lets a CT set a NUMA memory policy for all files of a tmpfs
mount.
Reject mpol= in a non-super VE the way a kernel built without
CONFIG_NUMA does: the mount fails with -EINVAL and "Unsupported
parameter 'mpol'".
https://virtuozzo.atlassian.net/browse/VSTOR-153679
Feature: mm: prohibit NUMA API inside CT
Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
mm/shmem.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/shmem.c b/mm/shmem.c
index f8cea7e5de88d..8862723003fb0 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -4378,7 +4378,7 @@ static int shmem_parse_one(struct fs_context *fc, struct fs_parameter *param)
ctx->seen |= SHMEM_SEEN_HUGE;
break;
case Opt_mpol:
- if (IS_ENABLED(CONFIG_NUMA)) {
+ if (IS_ENABLED(CONFIG_NUMA) && ve_is_super(get_exec_env())) {
mpol_put(ctx->mpol);
ctx->mpol = NULL;
if (mpol_parse_str(param->string, &ctx->mpol))
--
2.43.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Devel] [PATCH hci-8.1 v2 4/4] selftests/ve: check that tmpfs rejects mpol= in a VE
2026-11-06 14:01 [Devel] [PATCH hci-8.1 v2 0/4] mempolicy: prohibit mbind and set_mempolicy_home_node in VE Konstantin Khorenko
` (2 preceding siblings ...)
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 3/4] shmem: reject the mpol= mount option in VE Konstantin Khorenko
@ 2026-11-06 14:01 ` Konstantin Khorenko
2026-11-06 14:07 ` no-reply
2026-11-06 14:19 ` [Devel] [PATCH hci-8.1 v2 0/4] mempolicy: prohibit mbind and set_mempolicy_home_node in VE Vasileios Almpanis
4 siblings, 1 reply; 10+ messages in thread
From: Konstantin Khorenko @ 2026-11-06 14:01 UTC (permalink / raw)
To: Pavel Tikhomirov, Vasileios Almpanis; +Cc: devel
The test creates a tmpfs superblock with mpol=local and expects it to
succeed on the host and to fail with -EINVAL in a VE. A tmpfs with
size= is created in the VE as well, so the EINVAL can only come from
the mpol= check, not from tmpfs being unavailable in the VE.
https://virtuozzo.atlassian.net/browse/VSTOR-153679
Feature: mm: prohibit NUMA API inside CT
Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
tools/testing/selftests/ve/.gitignore | 1 +
tools/testing/selftests/ve/Makefile | 1 +
tools/testing/selftests/ve/ve_tmpfs_mpol_test.c | 123 ++++++++++++++++++++++++
3 files changed, 125 insertions(+)
diff --git a/tools/testing/selftests/ve/.gitignore b/tools/testing/selftests/ve/.gitignore
index 5e07985c8fed3..2ff7669a393aa 100644
--- a/tools/testing/selftests/ve/.gitignore
+++ b/tools/testing/selftests/ve/.gitignore
@@ -5,3 +5,4 @@ ve_cpuid_override_test
ve_vtty_stress
ve_numa_migrate_test
ve_numa_syscalls_prohibited_test
+ve_tmpfs_mpol_test
diff --git a/tools/testing/selftests/ve/Makefile b/tools/testing/selftests/ve/Makefile
index 451a7e1cc17d1..cff4fc2a7639f 100644
--- a/tools/testing/selftests/ve/Makefile
+++ b/tools/testing/selftests/ve/Makefile
@@ -8,6 +8,7 @@ TEST_GEN_PROGS += ve_mount_accounting_test
TEST_GEN_PROGS += ve_vtty_stress
TEST_GEN_PROGS += ve_numa_migrate_test
TEST_GEN_PROGS += ve_numa_syscalls_prohibited_test
+TEST_GEN_PROGS += ve_tmpfs_mpol_test
# CPUID faulting is x86-64 only. ARCH says "x86" for 32-bit too and lib.mk
# picks the clang target by its emptiness, so decide by the compiler.
diff --git a/tools/testing/selftests/ve/ve_tmpfs_mpol_test.c b/tools/testing/selftests/ve/ve_tmpfs_mpol_test.c
new file mode 100644
index 0000000000000..6254f95fadece
--- /dev/null
+++ b/tools/testing/selftests/ve/ve_tmpfs_mpol_test.c
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: GPL-2.0
+/* The tmpfs mpol= mount option works on the host and is rejected in a VE. */
+#define _GNU_SOURCE
+#include <errno.h>
+#include <sched.h>
+#include <sys/mount.h>
+#include <sys/syscall.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include "../kselftest_harness.h"
+#include "ve_selftest.h"
+
+/* Create a tmpfs superblock with one option set: 0 or the errno. */
+static int tmpfs_create(const char *key, const char *val)
+{
+ int fd, err = 0;
+
+ fd = fsopen("tmpfs", FSOPEN_CLOEXEC);
+ if (fd < 0)
+ return errno;
+ if (fsconfig(fd, FSCONFIG_SET_STRING, key, val, 0) < 0 ||
+ fsconfig(fd, FSCONFIG_CMD_CREATE, NULL, NULL, 0) < 0)
+ err = errno;
+ close(fd);
+ return err;
+}
+
+struct tmpfs_result {
+ int size_err;
+ int mpol_err;
+};
+
+static void run_tmpfs(struct tmpfs_result *res)
+{
+ res->size_err = tmpfs_create("size", "1M");
+ res->mpol_err = tmpfs_create("mpol", "local");
+}
+
+FIXTURE(tmpfs_mpol)
+{
+ int cgv2_fd;
+ int ctid;
+};
+
+FIXTURE_SETUP(tmpfs_mpol)
+{
+ long ret;
+
+ self->cgv2_fd = -1;
+
+ if (geteuid() != 0)
+ SKIP(return, "creating a ve cgroup needs root");
+
+ ret = syscall(__NR_get_mempolicy, NULL, NULL, 0UL, 0UL, 0UL);
+ if (ret == -1 && errno == ENOSYS)
+ SKIP(return, "no NUMA API on the host");
+ ASSERT_EQ(ret, 0);
+
+ self->cgv2_fd = mount_cg2_fd();
+ ASSERT_GE(self->cgv2_fd, 0);
+ ASSERT_EQ(write_file_at(self->cgv2_fd, "cgroup.subtree_control",
+ VE_CONTROLLERS), 0);
+
+ self->ctid = make_ve(self->cgv2_fd, CTID_MIN);
+ ASSERT_GE(self->ctid, 0);
+}
+
+FIXTURE_TEARDOWN(tmpfs_mpol)
+{
+ if (self->cgv2_fd >= 0) {
+ destroy_ve(self->cgv2_fd, self->ctid);
+ close(self->cgv2_fd);
+ }
+}
+
+TEST_F(tmpfs_mpol, host_mpol_accepted)
+{
+ struct tmpfs_result res;
+
+ run_tmpfs(&res);
+ EXPECT_EQ(res.size_err, 0)
+ TH_LOG("tmpfs size= on the host: %s", strerror(res.size_err));
+ EXPECT_EQ(res.mpol_err, 0)
+ TH_LOG("tmpfs mpol= on the host: %s", strerror(res.mpol_err));
+}
+
+TEST_F(tmpfs_mpol, ve_mpol_rejected)
+{
+ struct tmpfs_result res;
+ int pipefd[2], status;
+ pid_t pid;
+
+ ASSERT_EQ(pipe(pipefd), 0);
+ pid = fork();
+ ASSERT_GE(pid, 0);
+ if (pid == 0) {
+ close(pipefd[0]);
+ if (enter_cgroup(self->cgv2_fd, self->ctid) < 0)
+ _exit(1);
+ if (unshare(CLONE_NEWVE) < 0)
+ _exit(2);
+ run_tmpfs(&res);
+ if (write(pipefd[1], &res, sizeof(res)) != sizeof(res))
+ _exit(3);
+ _exit(0);
+ }
+ close(pipefd[1]);
+ ASSERT_EQ(waitpid(pid, &status, 0), pid);
+ ASSERT_TRUE(WIFEXITED(status));
+ ASSERT_EQ(WEXITSTATUS(status), 0)
+ TH_LOG("VE child setup failed at step %d", WEXITSTATUS(status));
+ ASSERT_EQ(read(pipefd[0], &res, sizeof(res)), sizeof(res));
+ close(pipefd[0]);
+
+ EXPECT_EQ(res.size_err, 0)
+ TH_LOG("tmpfs size= in a VE: %s", strerror(res.size_err));
+ EXPECT_EQ(res.mpol_err, EINVAL)
+ TH_LOG("tmpfs mpol= in a VE: %s, expected EINVAL",
+ strerror(res.mpol_err));
+}
+
+TEST_HARNESS_MAIN
--
2.43.0
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Devel] [PATCH hci-8.1 v2 1/4] mempolicy: prohibit mbind and set_mempolicy_home_node in VE
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 1/4] " Konstantin Khorenko
@ 2026-11-06 14:05 ` no-reply
0 siblings, 0 replies; 10+ messages in thread
From: no-reply @ 2026-11-06 14:05 UTC (permalink / raw)
To: Konstantin Khorenko, Vasileios Almpanis, Pavel Tikhomirov; +Cc: devel
> A CT is meant to see a kernel without NUMA support: in a non-super VE
> the NUMA API syscalls return -ENOSYS, as they do in a kernel built
> without CONFIG_NUMA.
>
> Return -ENOSYS from mbind(2) and set_mempolicy_home_node(2) at the
> start of the handler, before any argument check, as the other NUMA API
> syscalls do.
>
> Fixes: a803a5b2ea97 ("mempolicy: prohibit all NUMA API syscalls in VE")
> https://virtuozzo.atlassian.net/browse/VSTOR-153679
>
> Feature: mm: prohibit NUMA API inside CT
> Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261106-b4-prep-khorenko-vstor-153679-mbind-ve-v2-0-6327b23a2d93@virtuozzo.com?part=1
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Devel] [PATCH hci-8.1 v2 3/4] shmem: reject the mpol= mount option in VE
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 3/4] shmem: reject the mpol= mount option in VE Konstantin Khorenko
@ 2026-11-06 14:05 ` no-reply
0 siblings, 0 replies; 10+ messages in thread
From: no-reply @ 2026-11-06 14:05 UTC (permalink / raw)
To: Pavel Tikhomirov, Vasileios Almpanis, Konstantin Khorenko; +Cc: devel
> A CT is meant to see a kernel without NUMA support, so the NUMA API
> syscalls return -ENOSYS in a non-super VE. The tmpfs mpol= mount option
> still lets a CT set a NUMA memory policy for all files of a tmpfs
> mount.
>
> Reject mpol= in a non-super VE the way a kernel built without
> CONFIG_NUMA does: the mount fails with -EINVAL and "Unsupported
> parameter 'mpol'".
>
> https://virtuozzo.atlassian.net/browse/VSTOR-153679
>
> Feature: mm: prohibit NUMA API inside CT
> Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261106-b4-prep-khorenko-vstor-153679-mbind-ve-v2-0-6327b23a2d93@virtuozzo.com?part=3
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Devel] [PATCH hci-8.1 v2 2/4] selftests/ve: check that the NUMA API syscalls return ENOSYS in a VE
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 2/4] selftests/ve: check that the NUMA API syscalls return ENOSYS in a VE Konstantin Khorenko
@ 2026-11-06 14:06 ` no-reply
0 siblings, 0 replies; 10+ messages in thread
From: no-reply @ 2026-11-06 14:06 UTC (permalink / raw)
To: Pavel Tikhomirov, Konstantin Khorenko, Vasileios Almpanis; +Cc: devel
> A CT must see a kernel without NUMA, so all six NUMA API syscalls
> return -ENOSYS in a non-super VE.
>
> The test makes each call with arguments that succeed on the host and
> checks that the host gets 0, while a task in a VE gets -ENOSYS. The
> host result shows that the ENOSYS can only come from the VE check, not
> from a bad argument.
>
> https://virtuozzo.atlassian.net/browse/VSTOR-153679
>
> Feature: mm: prohibit NUMA API inside CT
> Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261106-b4-prep-khorenko-vstor-153679-mbind-ve-v2-0-6327b23a2d93@virtuozzo.com?part=2
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Devel] [PATCH hci-8.1 v2 4/4] selftests/ve: check that tmpfs rejects mpol= in a VE
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 4/4] selftests/ve: check that tmpfs rejects mpol= in a VE Konstantin Khorenko
@ 2026-11-06 14:07 ` no-reply
0 siblings, 0 replies; 10+ messages in thread
From: no-reply @ 2026-11-06 14:07 UTC (permalink / raw)
To: Vasileios Almpanis, Pavel Tikhomirov, Konstantin Khorenko; +Cc: devel
> The test creates a tmpfs superblock with mpol=local and expects it to
> succeed on the host and to fail with -EINVAL in a VE. A tmpfs with
> size= is created in the VE as well, so the EINVAL can only come from
> the mpol= check, not from tmpfs being unavailable in the VE.
>
> https://virtuozzo.atlassian.net/browse/VSTOR-153679
>
> Feature: mm: prohibit NUMA API inside CT
> Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261106-b4-prep-khorenko-vstor-153679-mbind-ve-v2-0-6327b23a2d93@virtuozzo.com?part=4
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Devel] [PATCH hci-8.1 v2 0/4] mempolicy: prohibit mbind and set_mempolicy_home_node in VE
2026-11-06 14:01 [Devel] [PATCH hci-8.1 v2 0/4] mempolicy: prohibit mbind and set_mempolicy_home_node in VE Konstantin Khorenko
` (3 preceding siblings ...)
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 4/4] selftests/ve: check that tmpfs rejects mpol= in a VE Konstantin Khorenko
@ 2026-11-06 14:19 ` Vasileios Almpanis
4 siblings, 0 replies; 10+ messages in thread
From: Vasileios Almpanis @ 2026-11-06 14:19 UTC (permalink / raw)
To: Konstantin Khorenko; +Cc: devel
On Fri, 06 Nov 2026 15:01:31 +0100, Konstantin Khorenko <khorenko@virtuozzo.com> wrote:
> mempolicy: prohibit mbind and set_mempolicy_home_node in VE
>
> A CT is meant to see a kernel without NUMA, so the NUMA API syscalls
> return -ENOSYS in a non-super VE.
>
> mbind(2) was blocked in vz7, but the vz8 port put its check into the
> compat entry point only, and the compat entry points were dropped on
> the rebase to RHEL9. Since then a CT task can bind its pages to nodes
> and migrate them with mbind(2), while get_mempolicy(2) tells it there
> is no NUMA.
>
> [...]
Reviewed-by: Vasileios Almpanis <vasileios.almpanis@virtuozzo.com>
--
Vasileios Almpanis <vasileios.almpanis@virtuozzo.com>
_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-11-06 14:20 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-06 14:01 [Devel] [PATCH hci-8.1 v2 0/4] mempolicy: prohibit mbind and set_mempolicy_home_node in VE Konstantin Khorenko
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 1/4] " Konstantin Khorenko
2026-11-06 14:05 ` no-reply
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 2/4] selftests/ve: check that the NUMA API syscalls return ENOSYS in a VE Konstantin Khorenko
2026-11-06 14:06 ` no-reply
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 3/4] shmem: reject the mpol= mount option in VE Konstantin Khorenko
2026-11-06 14:05 ` no-reply
2026-11-06 14:01 ` [Devel] [PATCH hci-8.1 v2 4/4] selftests/ve: check that tmpfs rejects mpol= in a VE Konstantin Khorenko
2026-11-06 14:07 ` no-reply
2026-11-06 14:19 ` [Devel] [PATCH hci-8.1 v2 0/4] mempolicy: prohibit mbind and set_mempolicy_home_node in VE Vasileios Almpanis
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox