From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.openvz.org (unknown [69.168.225.77]) by lore.virtuozzo.com (Postfix) with ESMTPS id 8579380024 for ; Wed, 26 Aug 2026 16:17:07 +0000 (UTC) Received: from mail.openvz.org (localhost [127.0.0.1]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 67QGFn7q010654; Wed, 26 Aug 2026 19:15:50 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 67QGFn7q010654 Authentication-Results: mail.openvz.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=virtuozzo.com header.i=@virtuozzo.com header.b="LTHtVqIW" Received: from mail-ej1-f71.google.com (mail-ej1-f71.google.com [209.85.218.71]) by mail.openvz.org (8.14.4/8.14.4) with ESMTP id 67QGFldo010650 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=FAIL) for ; Wed, 26 Aug 2026 19:15:48 +0300 DKIM-Filter: OpenDKIM Filter v2.11.0 mail.openvz.org 67QGFldo010650 Received: by mail-ej1-f71.google.com with SMTP id a640c23a62f3a-c1f3117bc6bso101406866b.0 for ; Wed, 26 Aug 2026 09:15:47 -0700 (PDT) X-Gm-Message-State: AFuF++kQFn4UfkoGXc6579K+fHmCj7g1hJYvZpYo2GvjYs4rsxhpt2Kw MIgcI02SWrCSg+7xlKkSLlRDuaNJ1+n+ilT79hZY2/Ch6+Yl6+FlZL5WLJfEtCTSF3HmM/at5AO fdnWdDjXqZ4+ABbhBFRN4tWrsLqFDNFmqoCmZP/lIiO4AbePB1lQk3g== X-Gm-Gg: AR+sD11NF6Y9dZMlR00ozgfbdWAmicJeuGSN+oyeblnveAifRfLi0lXVir6YlP0T8Ok mQVs91dA700mcI3dPIoO2h6aH4XWTE6Zpf861Cvl9xHup9B+NtJ9nC+DjpCudVIq+JXWVD97KeQ egwEXWOARR5dJGR3ySCXHrcaBVZsrfipuSfHWcZMa7yS4kLpSBwubhyprpnxxPZkFJkTkH/s1f9 v5sGtSzH0PjDM5IQnCR38eRHouIhZczR8QKExD60RAnZbwoE1QGFDN9asd6Rh+zTa7ZFsoK5ZSF 3AXUK2QhsV0KZpY8WjJvkWvyuwM7gqC77B5xR8SkaFYFGe/kroDTzBeoeupXi4+YHZmMn4NbZG/ X+iremhR6vtlbLMx1Sg== X-Received: by 2002:a17:907:d08f:b0:c24:adf4:5c73 with SMTP id a640c23a62f3a-c250baf7e8amr1064697866b.1.1787760947501; Wed, 26 Aug 2026 09:15:47 -0700 (PDT) X-Received: by 2002:a17:907:d08f:b0:c24:adf4:5c73 with SMTP id a640c23a62f3a-c250baf7e8amr1064687266b.1.1787760947004; Wed, 26 Aug 2026 09:15:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1787760946; cv=none; d=google.com; s=arc-20260327; b=o7/kVGfjnvD+Ujzg6hNkJzixlx8FWaK/zB0CftXV4kSuJwNEL7vdqY2cDsnUuOyWeV VRzbaXtmmc2y0CzvsNDfEjQP9K4AnXXlgQ23Bt2c2bAun1oc7vgEz1wXBBduEnZ2zxyS xBE1GU8PVmtYmGzGcyXTJd67gmqmazXUfzQ12PKC9Mb7xo0Ty62FyheMQ3m7LceTdA5q vDsUpff3p6vth0jAbhFS0QqsmHP5vFGPse2oSgMJyWd8H4k9f7sVY6f5arTyrF/Tcimv 97lwnUHEOGjKJuU9YeBaxxJurUVYrYY9XLsqDP0CIZMHJiy/utdtnWvg4Gt42OmSgyah 01zw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=subject:in-reply-to:cc:to:from:message-id:date:dkim-signature; bh=vFksIpOrl77UGcbpA7oK/YOM/pBpFpegLCFSX+q1hts=; fh=6WaLqqjLrnoBYT6o6L3rXzHBtCCDnrtj0IcE19DsjNk=; b=bLIyWfgMLhjlwszcJFXqsPibz90uz7ejuOSFB7Bf8ruY7EHj6a4ngfiK1GuF5AKYWD TyJDF8UOLFFFnsDZkg7+xq3FoyOTBHhwEOeSKxES5OkIpOJMg50+/1I+wLNPlWDO/VNE PmPv9XHOwZk46W4fuVa4eaib2mA8/BFqw9djytGjvRF9DU1KmCrKZv+HjVZixwTix5+O zWunnSeV+H9K49Sx80rvYh/uQzU4fv2MaK5pVN3YteOIhEhbv8tH/l6KXpiF3Wb2NoHQ LV/UM7G7I1ebh0yv2LkzgNwf9rWp4TU3Rd1eTHz0CNsj/KnG0juAbeIhfMfXNrNj+9oH FYPg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=LTHtVqIW; spf=pass (google.com: domain of khorenko@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=khorenko@virtuozzo.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=virtuozzo.com Received: from relay.virtuozzo.com (relay.virtuozzo.com. [130.117.225.111]) by mx.google.com with ESMTPS id a640c23a62f3a-c25364dff01si6437866b.231.2026.08.26.09.15.46 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 26 Aug 2026 09:15:46 -0700 (PDT) Received-SPF: pass (google.com: domain of khorenko@virtuozzo.com designates 130.117.225.111 as permitted sender) client-ip=130.117.225.111; Authentication-Results: mx.google.com; dkim=pass header.i=@virtuozzo.com header.s=relay header.b=LTHtVqIW; spf=pass (google.com: domain of khorenko@virtuozzo.com designates 130.117.225.111 as permitted sender) smtp.mailfrom=khorenko@virtuozzo.com; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=virtuozzo.com DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=virtuozzo.com; s=relay; h=Subject:From:Message-Id:Date:Content-Type: MIME-Version; bh=vFksIpOrl77UGcbpA7oK/YOM/pBpFpegLCFSX+q1hts=; b=LTHtVqIWpTkp puZWiiuRCQXYuY/R3xITjlAXys/OCEG0ULeUUcn7HOof2jPZhch+BG1DBHp4F7+3c57XmF8zOn088 AZhsM07YEv1S2cSOaH9qIv8Ui4UHMqCFaAiCjhATZwrVj1u908MA4zxmvpQ6HyLN8hEKAIfRJqK3z dxP6r44ntUdJrwPwgFdAG+pJ3Vmt6g8bxaQMxNaxPtC3fj4spH2wfurL8L5L8v5cbsE3E0DOWnLU1 utoHWuWi5+EzjqPSI2/4lpfXC8vn2KhalgM6GcLtFO381gsxwMTOHmxvvOz+EoecXVhmJmKupEfjE 3PXjLolMD9q7u24QmBTCzg==; Received: from ch-demo-asa.virtuozzo.com ([130.117.225.8] helo=f0.sw.ru) by relay.virtuozzo.com with esmtps (TLS1.3) tls TLS_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wzGFj-005QQp-2a; Wed, 26 Aug 2026 18:15:45 +0200 Received: from f0.sw.ru (localhost [127.0.0.1]) by f0.sw.ru (8.18.1/8.18.1/Debian-2) with ESMTP id 67QGFj8T913650; Wed, 26 Aug 2026 18:15:45 +0200 Received: (from kostja@localhost) by f0.sw.ru (8.18.1/8.18.1/Submit) id 67QGFjKd913648; Wed, 26 Aug 2026 18:15:45 +0200 Date: Wed, 26 Aug 2026 18:15:45 +0200 Message-Id: <202608261615.67QGFjKd913648@f0.sw.ru> X-Authentication-Warning: f0.sw.ru: kostja set sender to khorenko@virtuozzo.com using -f From: Konstantin Khorenko To: Mirian Shilakadze In-Reply-to: <20260826110415.41119-3-mirian.shilakadze@virtuozzo.com> X-OZ-Fwd: true Cc: OpenVZ devel Subject: Re: [Devel] [PATCH RHEL10 COMMIT] selftests/ve: check that hiding an entry does not unmount it X-BeenThere: devel@openvz.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: OpenVZ development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: devel-bounces@openvz.org Errors-To: devel-bounces@openvz.org The commit is pushed to "branch-rh10-6.12.0-211.39.1.16.x.vz10-ovz" and will appear at git@bitbucket.org:openvz/vzkernel.git after rh10-6.12.0-211.39.1.16.10.vz10 ------> commit e6d9a8ea97c1933241869f60ac5677865d848dab Author: Mirian Shilakadze Date: Wed Aug 26 15:04:11 2026 +0400 selftests/ve: check that hiding an entry does not unmount it kernfs_dop_revalidate() answered the per VE visibility check with the same "return 0" the staleness checks use, and the VFS reads 0 as a global fact: d_invalidate() hands every mountpoint under that dentry to __detach_mounts(), whose mountpoint hash is not scoped to a mount namespace. A single lookup from inside a Container unmounted the host's bpffs, and libvzctl needs bpffs for the cgroup v2 device controller, so the whole node stopped being manageable. Mount a tmpfs on the entry the variant already keeps host only, look it up from inside a VE, and require both that the VE is told ENOENT and that the mount is still there afterwards. The mount is made in the test's own mount namespace so the machine running the test cannot lose a mount it needs, while the dentry the mount hangs on is still the shared one the bug worked through. The mount check uses openat2() with RESOLVE_NO_XDEV, which fails with EXDEV when the final component is a mount point, rather than reading /proc/self/mountinfo. Fails without the preceding fix, on both the sysfs and the proc variant. Feature: kernfs: per-CT entries visibility and permissions configuration https://virtuozzo.atlassian.net/browse/VSTOR-142552 Signed-off-by: Mirian Shilakadze Reviewed-by: Pavel Tikhomirov Reviewed-by: Konstantin Khorenko --- tools/testing/selftests/ve/ve_perms_test.c | 52 ++++++++++++++++++++++++++++++ tools/testing/selftests/ve/ve_selftest.h | 40 +++++++++++++++++++++-- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/ve/ve_perms_test.c b/tools/testing/selftests/ve/ve_perms_test.c index 4522950c17f2f..25ffbd42c3802 100644 --- a/tools/testing/selftests/ve/ve_perms_test.c +++ b/tools/testing/selftests/ve/ve_perms_test.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -412,4 +413,55 @@ TEST_F(ve_perms, enforce_denies) absent, O_RDONLY), EACCES); } +/* + * Looking up an entry that a VE cannot see must not disturb a mount that + * sits on it. + * + * The lookup used to answer "this dentry is stale" where it meant "this name + * is not here for you", and the VFS acts on stale globally: d_invalidate() + * detaches every mount on that dentry in every mount namespace. One lookup + * from inside a Container took the host's bpffs and tracefs with it. + * + * The tmpfs is mounted in the test's own mount namespace, so the machine + * running this cannot lose a mount it needs, while the dentry the mount hangs + * on is still the shared one the bug worked through. + */ +TEST_F(ve_perms, hidden_entry_keeps_its_mount) +{ + char path[PATH_MAX]; + int status; + pid_t pid; + + if (!entry_present(variant->dir_prefix, variant->dir)) + SKIP(return, "%s/%s absent", variant->dir_prefix, variant->dir); + snprintf(path, sizeof(path), "%s/%s", variant->dir_prefix, variant->dir); + + pid = fork(); + ASSERT_GE(pid, 0); + if (pid == 0) { + if (unshare(CLONE_NEWNS) != 0 || + mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL) != 0 || + mount("ve_selftest", path, "tmpfs", 0, NULL) != 0) + _exit(255); + if (is_mounted(path) != 1) + _exit(254); + + /* + * The lookup that used to unmount it. What the VE is told + * depends on the filesystem and on the mount now covering the + * entry, and enforce_denies() already covers that. Here only + * the mount surviving the lookup is the point. + */ + ve_open_rel(self->cgv2_fd, self->ctid_a, variant->dir_prefix, + variant->dir, O_RDONLY | O_DIRECTORY); + + _exit(is_mounted(path) == 1 ? 0 : 2); + } + ASSERT_EQ(waitpid(pid, &status, 0), pid); + ASSERT_TRUE(WIFEXITED(status)); + if (WEXITSTATUS(status) == 2) + TH_LOG("the VE lookup unmounted %s", path); + EXPECT_EQ(WEXITSTATUS(status), 0); +} + TEST_HARNESS_MAIN diff --git a/tools/testing/selftests/ve/ve_selftest.h b/tools/testing/selftests/ve/ve_selftest.h index 69c0a52dd7ef0..c53bf7900d208 100644 --- a/tools/testing/selftests/ve/ve_selftest.h +++ b/tools/testing/selftests/ve/ve_selftest.h @@ -1,8 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* * Shared helpers for the ve selftests: a private cgroup2 mount, small file and - * cgroup helpers, and VE cgroup create and destroy, used across the tests in - * this directory. + * cgroup helpers, VE cgroup create and destroy, and a mount point query, used + * across the tests in this directory. */ #ifndef __SELFTESTS_VE_VE_SELFTEST_H #define __SELFTESTS_VE_VE_SELFTEST_H @@ -16,6 +16,8 @@ #include #include #include +#include +#include #ifndef CLONE_NEWVE #define CLONE_NEWVE 0x00000040 @@ -180,4 +182,38 @@ static inline void destroy_ve(int cgv2_fd, int id) __func__, id, strerror(errno)); } +/* + * Is @path a mount point? RESOLVE_NO_XDEV makes openat2() fail with EXDEV + * when the final component is a mount point, which answers the question + * without reading the mount table. + */ +static inline int is_mounted(const char *path) +{ + struct open_how how = { + .flags = O_PATH | O_CLOEXEC, + .resolve = RESOLVE_NO_XDEV, + }; + char buf[PATH_MAX], *dir, *base; + int dfd, fd; + + if (snprintf(buf, sizeof(buf), "%s", path) >= (int)sizeof(buf)) + return -1; + base = strrchr(buf, '/'); + if (!base) + return -1; + *base++ = '\0'; + dir = buf[0] ? buf : "/"; + + dfd = open(dir, O_PATH | O_DIRECTORY | O_CLOEXEC); + if (dfd < 0) + return -1; + fd = syscall(__NR_openat2, dfd, base, &how, sizeof(how)); + close(dfd); + if (fd >= 0) { + close(fd); + return 0; + } + return errno == EXDEV ? 1 : -1; +} + #endif /* __SELFTESTS_VE_VE_SELFTEST_H */ _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel