<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<span style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">kernfs_add_one() does not always set it. There are two ways it can end up NULL.</span>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
One: kernfs_add_one() adds the node to the tree (kernfs_link_sibling) before it</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
sets the map (kernfs_get_ve_perms), both under the sysfs root rwsem. So for a</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
short window the node is in the tree but its map is still NULL. The old</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
kernfs_perms_start() took the wrong rwsem (kernfs_root(of-&gt;kn), the cgroup root,</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
not the sysfs one), so it did not lock against kernfs_add_one() and could hit the</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
node in that window. Patch 3 takes the right rwsem and fixes this.</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Two, separate from the lock: as Vasileios noted, kernfs_get_ve_perms() returns</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
void and only sets the map if kmapset_new() worked, so if that alloc fails the</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
node is left with a NULL map for good. Rare in practice (small GFP_KERNEL alloc)</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
but it can happen, and the NULL check in this patch handles it.</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
I cannot tell from the oops which of the two hit us, but both can happen, and</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
these are the two I found, not necessarily the only ways the map can be NULL. It</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
was crashing repeatedly and consistently under load (a cat storm on</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
ve.sysfs_permissions while the sysfs tree churned), and it reproduced the same</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
way on a stock kernel with no patches. With both the lock fix and this NULL check</div>
<div class="elementToProof" style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
in place it stopped. I will also explain why the map can be NULL in the commit</div>
<div style="font-family: Aptos, Aptos_EmbeddedFont, Aptos_MSFontService, Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
message in v2.</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> Pavel Tikhomirov &lt;ptikhomirov@virtuozzo.com&gt;<br>
<b>Sent:</b> Monday, June 29, 2026 9:14 PM<br>
<b>To:</b> Mirian Shilakadze &lt;mirian.shilakadze@virtuozzo.com&gt;; Konstantin Khorenko &lt;khorenko@virtuozzo.com&gt;<br>
<b>Cc:</b> devel@openvz.org &lt;devel@openvz.org&gt;; den@openvz.org &lt;den@openvz.org&gt;<br>
<b>Subject:</b> Re: [PATCH vz10 2/7] fs/kernfs, ve: skip NULL ve_perms_map in kernfs_perms_shown</font>
<div>&nbsp;</div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">Maybe there something specific about this kn with NULL ve_perms_map? Why didn't<br>
we crash all other the place before?<br>
<br>
AFAICS, kernfs_add_one -&gt; kernfs_get_ve_perms always sets non-NULL ve_perms_map for each kn.<br>
<br>
On 6/28/26 11:26, Mirian Shilakadze wrote:<br>
&gt; The seq read of ve.sysfs_permissions walks every sysfs node and calls<br>
&gt; kernfs_perms_shown(), which feeds kn-&gt;ve_perms_map to kmapset_lookup() and<br>
&gt; reads -&gt;default_value with no NULL check. A node whose ve_perms_map is NULL<br>
&gt; crashes the read (RDI and CR2 are 0, kmapset_lookup() derefs the NULL map<br>
&gt; at offset 0x20):<br>
&gt; <br>
&gt;&nbsp;&nbsp; BUG: kernel NULL pointer dereference, address: 0000000000000020<br>
&gt;&nbsp;&nbsp; #PF: supervisor read access in kernel mode<br>
&gt;&nbsp;&nbsp; #PF: error_code(0x0000) - not-present page<br>
&gt;&nbsp;&nbsp; Oops: 0000 [#1] SMP NOPTI<br>
&gt;&nbsp;&nbsp; CPU: 82 UID: 0 PID: 10796 Comm: cat ve: 0 Tainted: G W 12.7 PREEMPT(full)<br>
&gt;&nbsp;&nbsp; RIP: 0010:kmapset_lookup+0x4/0x40<br>
&gt;&nbsp;&nbsp; RDX: 0000000000000000 RSI: ff2eb351033adf88 RDI: 0000000000000000<br>
&gt;&nbsp;&nbsp; CR2: 0000000000000020 CR3: 0000000c09658001 CR4: 0000000000f71ef0<br>
&gt;&nbsp;&nbsp; Call Trace:<br>
&gt;&nbsp;&nbsp;&nbsp; &lt;TASK&gt;<br>
&gt;&nbsp;&nbsp;&nbsp; ? kernfs_perms_start+0x60/0xd0<br>
&gt;&nbsp;&nbsp;&nbsp; ? page_fault_oops+0xbb/0x110<br>
&gt;&nbsp;&nbsp;&nbsp; ? exc_page_fault+0x8e/0x100<br>
&gt;&nbsp;&nbsp;&nbsp; ? asm_exc_page_fault+0x26/0x30<br>
&gt;&nbsp;&nbsp;&nbsp; ? kmapset_lookup+0x4/0x40<br>
&gt;&nbsp;&nbsp;&nbsp; kernfs_perms_start+0x60/0xd0<br>
&gt;&nbsp;&nbsp;&nbsp; kernfs_seq_start+0x74/0x110<br>
&gt;&nbsp;&nbsp;&nbsp; seq_read_iter+0xfe/0x480<br>
&gt;&nbsp;&nbsp;&nbsp; vfs_read+0x29f/0x370<br>
&gt;&nbsp;&nbsp;&nbsp; ksys_read+0x73/0xf0<br>
&gt;&nbsp;&nbsp;&nbsp; do_syscall_64+0x92/0x180<br>
&gt;&nbsp;&nbsp;&nbsp; entry_SYSCALL_64_after_hwframe+0x76/0x7e<br>
&gt;&nbsp;&nbsp;&nbsp; &lt;/TASK&gt;<br>
&gt; <br>
&gt; Return false for such nodes. kernfs_perms_show() only ever sees nodes that<br>
&gt; kernfs_perms_shown() accepted, so guarding it here is enough.<br>
&gt; <br>
&gt; <a href="https://virtuozzo.atlassian.net/browse/VSTOR-136541">https://virtuozzo.atlassian.net/browse/VSTOR-136541</a><br>
&gt; Fixes: 008aa8b6ff0b (&quot;ve/kernfs: add new interface to control per-VE nodes visibility&quot;)<br>
&gt; Signed-off-by: Mirian Shilakadze &lt;mirian.shilakadze@virtuozzo.com&gt;<br>
&gt; ---<br>
&gt;&nbsp; fs/kernfs/ve.c | 2 ++<br>
&gt;&nbsp; 1 file changed, 2 insertions(+)<br>
&gt; <br>
&gt; diff --git a/fs/kernfs/ve.c b/fs/kernfs/ve.c<br>
&gt; index beaa278b014e..f357ebb907f1 100644<br>
&gt; --- a/fs/kernfs/ve.c<br>
&gt; +++ b/fs/kernfs/ve.c<br>
&gt; @@ -146,6 +146,8 @@ static struct kernfs_node *kernfs_next_recursive(struct kernfs_node *kn)<br>
&gt;&nbsp; static bool kernfs_perms_shown(struct ve_struct *ve, struct kernfs_node *kn,<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct kmapset_key *key)<br>
&gt;&nbsp; {<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp; if (!kn-&gt;ve_perms_map)<br>
&gt; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ve_is_super(ve))<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return kn-&gt;ve_perms_map-&gt;default_value != 0;<br>
&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return kmapset_lookup(kn-&gt;ve_perms_map, key) != NULL;<br>
<br>
-- <br>
Best regards, Pavel Tikhomirov<br>
Senior Software Developer, Virtuozzo.<br>
<br>
</div>
</span></font></div>
</body>
</html>