All Virtuozzo development lists (kernel + QEMU)
 help / color / mirror / Atom feed
From: Vladimir Riabchun <vladimir.riabchun@virtuozzo.com>
To: Konstantin Khorenko <khorenko@virtuozzo.com>
Cc: devel@openvz.org
Subject: [Devel] [PATCH hci-8.1 2/2] ovl: Keep creator VE in overlayfs superblock
Date: Sun, 20 Sep 2026 17:45:43 +0000	[thread overview]
Message-ID: <20260920-ovl-use-orig-ve-v1-2-b3e63f6ff80d@virtuozzo.com> (raw)
In-Reply-To: <20260920-ovl-use-orig-ve-v1-0-b3e63f6ff80d@virtuozzo.com>

We observed a crash in overlayfs when checkpointing a container
with docker running inside:

[ 2300.870181] BUG: kernel NULL pointer dereference, address: 0000000000000005
[ 2300.871537] #PF: supervisor read access in kernel mode
[ 2300.872577] #PF: error_code(0x0000) - not-present page
[ 2300.873595] PGD 800000010a18f067 P4D 800000010a18f067 PUD 10730c067 PMD 0
[ 2300.874900] Oops: Oops: 0000 [#1] SMP PTI
[ 2300.875742] CPU: 1 UID: 0 PID: 5419 Comm: criu ve: 0 Kdump: loaded Not tainted 6.12.0-211.39.1.16.6.vz10.x86_64 #1 16.6 PREEMPT(voluntary)
[ 2300.878057] Hardware name: Acronis OpenStack Compute/Virtuozzo, BIOS 1.16.1-1.vz9.2 04/01/2014
[ 2300.879684] RIP: 0010:ovl_get_index_name_fh+0x18/0x70 [overlay]
[ 2300.880859] Code: ...
[ 2300.884128] RSP: 0018:ffffd32582e0f7c0 EFLAGS: 00010246
[ 2300.885153] RAX: 0000000000000010 RBX: 0000000000000000 RCX: ffff8ba4497480a8
[ 2300.886480] RDX: ffff8ba45535dc00 RSI: 0000000000000dc0 RDI: 0000000000000000
[ 2300.887824] RBP: ffff8ba68f9daa80 R08: ffff8ba4497480a8 R09: 000000000000030e
[ 2300.889139] R10: 0000000000000000 R11: ffff8ba44862d6d0 R12: ffffd32582e0f800
[ 2300.890498] R13: 0000000000000000 R14: ffff8ba497cb0110 R15: ffff8ba517548cc0
[ 2300.891838] FS:  00007f5a2f492880(0000) GS:ffff8bab9fc80000(0000) knlGS:0000000000000000
[ 2300.893376] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 2300.894476] CR2: 0000000000000005 CR3: 000000033403a005 CR4: 00000000003726f0
[ 2300.895807] Call Trace:
[ 2300.896397]  <TASK>
[ 2300.896938]  ? show_trace_log_lvl+0x1b0/0x2f0
[ 2300.897854]  ? show_trace_log_lvl+0x1b0/0x2f0
[ 2300.898748]  ? ovl_create_index+0x82/0x260 [overlay]
[ 2300.899766]  ? __die_body.cold+0x8/0x12
[ 2300.900582]  ? page_fault_oops+0x148/0x160
[ 2300.901562]  ? exc_page_fault+0x7f/0x150
[ 2300.902406]  ? asm_exc_page_fault+0x26/0x30
[ 2300.903298]  ? ovl_get_index_name_fh+0x18/0x70 [overlay]
[ 2300.904435]  ovl_create_index+0x82/0x260 [overlay]
[ 2300.905406]  ovl_copy_up_workdir+0x30a/0x330 [overlay]
[ 2300.906427]  ovl_do_copy_up+0x10d/0x2e0 [overlay]
[ 2300.907387]  ovl_copy_up_one+0x456/0x720 [overlay]
[ 2300.908376]  ? xa_load+0x7b/0xb0
[ 2300.909090]  ? _raw_spin_unlock+0xe/0x30
[ 2300.909913]  ? list_lru_add+0x11b/0x160
[ 2300.910736]  ovl_copy_up_flags+0x81/0x110 [overlay]
[ 2300.911740]  ovl_create_object+0x51/0x130 [overlay]
[ 2300.912719]  vfs_mkdir+0x194/0x250
[ 2300.913470]  do_mkdirat+0x14c/0x180
[ 2300.914223]  __x64_sys_mkdir+0x46/0x70
[ 2300.915019]  do_syscall_64+0x7d/0x160
[ 2300.915798]  ? do_sys_openat2+0x9c/0xe0
[ 2300.916672]  ? syscall_exit_work+0xf3/0x120
[ 2300.917540]  ? syscall_exit_to_user_mode+0x32/0x190
[ 2300.918518]  ? do_syscall_64+0x89/0x160
[ 2300.919316]  ? syscall_exit_work+0xf3/0x120
[ 2300.920181]  ? syscall_exit_to_user_mode+0x32/0x190
[ 2300.921173]  ? do_syscall_64+0x89/0x160
[ 2300.921991]  ? exc_page_fault+0x7f/0x150
[ 2300.922814]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[ 2300.923823] RIP: 0033:0x7f5a2f8de3eb

The root cause is VE namespace mismatch. Overlayfs was created
inside CT, so ovl_fill_super stored in-container credentials
to ofs->creator_cred.
Those creds are later used in ovl_override_creds to temporarily
swich creds and perform checks using them.

One of these checks happened in ovl_get_origin_fh/ovl_can_decode_fh.
On fs creation this check passed because we had container VE
and container creds, so overlayfs thought that we support
file handles (ovl_can_decode_fh call in ovl_make_workdir).

When we tried to do something with the overlayfs from host VE,
ve_capable check was performed with credentials from CT
and with host VE.
ovl_get_origin_fh returned unexpected NULL and all exploded.

Store creator VE next to creator creds, so we can perform all
ve_capable checks with the correct VE.

https://virtuozzo.atlassian.net/browse/VSTOR-142405

Signed-off-by: Vladimir Riabchun <vladimir.riabchun@virtuozzo.com>
---
 fs/overlayfs/copy_up.c   | 2 +-
 fs/overlayfs/namei.c     | 2 +-
 fs/overlayfs/overlayfs.h | 2 +-
 fs/overlayfs/ovl_entry.h | 1 +
 fs/overlayfs/params.c    | 3 +++
 fs/overlayfs/super.c     | 7 +++++--
 fs/overlayfs/util.c      | 4 ++--
 7 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 4388004a319d..b7c06ae4beb4 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -478,7 +478,7 @@ struct ovl_fh *ovl_get_origin_fh(struct ovl_fs *ofs, struct dentry *origin)
 	 * so we can use the overlay.origin xattr to distignuish between a copy
 	 * up and a pure upper inode.
 	 */
-	if (!ovl_can_decode_fh(origin->d_sb))
+	if (!ovl_can_decode_fh(origin->d_sb, ofs))
 		return NULL;
 
 	return ovl_encode_real_fh(ofs, d_inode(origin), false);
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index efa2a072aa69..e33debf8b1ed 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -166,7 +166,7 @@ struct dentry *ovl_decode_real_fh(struct ovl_fs *ofs, struct ovl_fh *fh,
 	struct dentry *real;
 	int bytes;
 
-	if (!ve_capable(CAP_DAC_READ_SEARCH))
+	if (!__ve_capable(ofs->creator_ve, CAP_DAC_READ_SEARCH))
 		return NULL;
 
 	/*
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 8577c7884fb9..9c8dd2f9cac6 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -427,7 +427,7 @@ static inline const struct cred *ovl_creds(struct super_block *sb)
 	return OVL_FS(sb)->creator_cred;
 }
 
-int ovl_can_decode_fh(struct super_block *sb);
+int ovl_can_decode_fh(struct super_block *sb, struct ovl_fs *ofs);
 struct dentry *ovl_indexdir(struct super_block *sb);
 bool ovl_index_all(struct super_block *sb);
 bool ovl_verify_lower(struct super_block *sb);
diff --git a/fs/overlayfs/ovl_entry.h b/fs/overlayfs/ovl_entry.h
index ab78001635e7..a6ad8b8de48c 100644
--- a/fs/overlayfs/ovl_entry.h
+++ b/fs/overlayfs/ovl_entry.h
@@ -77,6 +77,7 @@ struct ovl_fs {
 	struct ovl_config config;
 	/* creds of process who forced instantiation of super block */
 	const struct cred *creator_cred;
+	struct ve_struct *creator_ve;
 	bool tmpfile;
 	bool noxattr;
 	bool nofh;
diff --git a/fs/overlayfs/params.c b/fs/overlayfs/params.c
index 32c58fcfe52f..c047f1265b8e 100644
--- a/fs/overlayfs/params.c
+++ b/fs/overlayfs/params.c
@@ -8,6 +8,7 @@
 #include <linux/posix_acl_xattr.h>
 #include <linux/seq_file.h>
 #include <linux/xattr.h>
+#include <linux/ve.h>
 #include "overlayfs.h"
 #include "params.h"
 
@@ -761,6 +762,8 @@ void ovl_free_fs(struct ovl_fs *ofs)
 	kfree(ofs->config.workdir);
 	if (ofs->creator_cred)
 		put_cred(ofs->creator_cred);
+	if (ofs->creator_ve)
+		put_ve(ofs->creator_ve);
 	kfree(ofs);
 }
 
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index fb47711c8fb9..e87b6684ec70 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -18,6 +18,7 @@
 #include <linux/file.h>
 #include <linux/fs_context.h>
 #include <linux/fs_parser.h>
+#include <linux/ve.h>
 #include "overlayfs.h"
 #include "params.h"
 
@@ -393,7 +394,7 @@ static int ovl_lower_dir(const char *name, struct path *path,
 	 * The inodes index feature and NFS export need to encode and decode
 	 * file handles, so they require that all layers support them.
 	 */
-	fh_type = ovl_can_decode_fh(path->dentry->d_sb);
+	fh_type = ovl_can_decode_fh(path->dentry->d_sb, ofs);
 	if ((ofs->config.nfs_export ||
 	     (ofs->config.index && ofs->config.upperdir)) && !fh_type) {
 		ofs->config.index = false;
@@ -757,7 +758,7 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
 	}
 
 	/* Check if upper/work fs supports file handles */
-	fh_type = ovl_can_decode_fh(ofs->workdir->d_sb);
+	fh_type = ovl_can_decode_fh(ofs->workdir->d_sb, ofs);
 	if (ofs->config.index && !fh_type) {
 		ofs->config.index = false;
 		pr_warn("upper fs does not support file handles, falling back to index=off.\n");
@@ -1328,6 +1329,8 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc)
 
 	sb->s_d_op = &ovl_dentry_operations;
 
+	ofs->creator_ve = get_ve(get_exec_env());
+
 	err = -ENOMEM;
 	ofs->creator_cred = cred = prepare_creds();
 	if (!cred)
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index f95090f0d29c..047b618ad296 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -78,9 +78,9 @@ const struct cred *ovl_override_creds(struct super_block *sb)
  * Return 1 (FILEID_INO32_GEN) if fs uses the default 32bit inode encoding.
  * Return -1 if fs uses a non default encoding with unknown inode size.
  */
-int ovl_can_decode_fh(struct super_block *sb)
+int ovl_can_decode_fh(struct super_block *sb, struct ovl_fs *ofs)
 {
-	if (!ve_capable(CAP_DAC_READ_SEARCH))
+	if (!__ve_capable(ofs->creator_ve, CAP_DAC_READ_SEARCH))
 		return 0;
 
 	if (!exportfs_can_decode_fh(sb->s_export_op))

-- 
2.47.1

_______________________________________________
Devel mailing list
Devel@openvz.org
https://lists.openvz.org/mailman/listinfo/devel

  parent reply	other threads:[~2026-09-20 17:47 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-20 17:45 [Devel] [PATCH hci-8.1 0/2] Fix kernel crash in overlayfs Vladimir Riabchun
2026-09-20 17:45 ` [Devel] [PATCH hci-8.1 1/2] capability: Add new helper to check specific VE capabilities Vladimir Riabchun
2026-09-20 17:45 ` Vladimir Riabchun [this message]
2026-09-25 17:58   ` [Devel] [PATCH hci-8.1 2/2] ovl: Keep creator VE in overlayfs superblock Konstantin Khorenko
2026-10-19  9:00     ` Pavel Tikhomirov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260920-ovl-use-orig-ve-v1-2-b3e63f6ff80d@virtuozzo.com \
    --to=vladimir.riabchun@virtuozzo.com \
    --cc=devel@openvz.org \
    --cc=khorenko@virtuozzo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.