Skip to content

Commit 0619b5a

Browse files
author
CKI KWF Bot
committed
Merge: CVE-2025-39881 kernel: kernfs: Fix UAF in polling when open file is released [rhel-9.8]
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/7571 kernfs: Fix UAF in polling when open file is released JIRA: https://issues.redhat.com/browse/RHEL-122088 Conflicts: Dropped llseek bits, as commit 0fedefd (kernfs: sysfs: support custom llseek method for sysfs entries) is not part of RHEL-9 CVE: CVE-2025-39881 Signed-off-by: Pavel Reichl <preichl@redhat.com> Approved-by: Carlos Maiolino <cmaiolino@redhat.com> Approved-by: Andrey Albershteyn <aalbersh@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
2 parents e2524ff + b14472d commit 0619b5a

File tree

1 file changed

+36
-18
lines changed

1 file changed

+36
-18
lines changed

fs/kernfs/file.c

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,24 @@ static struct kernfs_open_node *of_on(struct kernfs_open_file *of)
7070
!list_empty(&of->list));
7171
}
7272

73+
/* Get active reference to kernfs node for an open file */
74+
static struct kernfs_open_file *kernfs_get_active_of(struct kernfs_open_file *of)
75+
{
76+
/* Skip if file was already released */
77+
if (unlikely(of->released))
78+
return NULL;
79+
80+
if (!kernfs_get_active(of->kn))
81+
return NULL;
82+
83+
return of;
84+
}
85+
86+
static void kernfs_put_active_of(struct kernfs_open_file *of)
87+
{
88+
return kernfs_put_active(of->kn);
89+
}
90+
7391
/**
7492
* kernfs_deref_open_node_locked - Get kernfs_open_node corresponding to @kn
7593
*
@@ -139,7 +157,7 @@ static void kernfs_seq_stop_active(struct seq_file *sf, void *v)
139157

140158
if (ops->seq_stop)
141159
ops->seq_stop(sf, v);
142-
kernfs_put_active(of->kn);
160+
kernfs_put_active_of(of);
143161
}
144162

145163
static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos)
@@ -152,7 +170,7 @@ static void *kernfs_seq_start(struct seq_file *sf, loff_t *ppos)
152170
* the ops aren't called concurrently for the same open file.
153171
*/
154172
mutex_lock(&of->mutex);
155-
if (!kernfs_get_active(of->kn))
173+
if (!kernfs_get_active_of(of))
156174
return ERR_PTR(-ENODEV);
157175

158176
ops = kernfs_ops(of->kn);
@@ -243,7 +261,7 @@ static ssize_t kernfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
243261
* the ops aren't called concurrently for the same open file.
244262
*/
245263
mutex_lock(&of->mutex);
246-
if (!kernfs_get_active(of->kn)) {
264+
if (!kernfs_get_active_of(of)) {
247265
len = -ENODEV;
248266
mutex_unlock(&of->mutex);
249267
goto out_free;
@@ -257,7 +275,7 @@ static ssize_t kernfs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
257275
else
258276
len = -EINVAL;
259277

260-
kernfs_put_active(of->kn);
278+
kernfs_put_active_of(of);
261279
mutex_unlock(&of->mutex);
262280

263281
if (len < 0)
@@ -328,7 +346,7 @@ static ssize_t kernfs_fop_write_iter(struct kiocb *iocb, struct iov_iter *iter)
328346
* the ops aren't called concurrently for the same open file.
329347
*/
330348
mutex_lock(&of->mutex);
331-
if (!kernfs_get_active(of->kn)) {
349+
if (!kernfs_get_active_of(of)) {
332350
mutex_unlock(&of->mutex);
333351
len = -ENODEV;
334352
goto out_free;
@@ -340,7 +358,7 @@ static ssize_t kernfs_fop_write_iter(struct kiocb *iocb, struct iov_iter *iter)
340358
else
341359
len = -EINVAL;
342360

343-
kernfs_put_active(of->kn);
361+
kernfs_put_active_of(of);
344362
mutex_unlock(&of->mutex);
345363

346364
if (len > 0)
@@ -362,13 +380,13 @@ static void kernfs_vma_open(struct vm_area_struct *vma)
362380
if (!of->vm_ops)
363381
return;
364382

365-
if (!kernfs_get_active(of->kn))
383+
if (!kernfs_get_active_of(of))
366384
return;
367385

368386
if (of->vm_ops->open)
369387
of->vm_ops->open(vma);
370388

371-
kernfs_put_active(of->kn);
389+
kernfs_put_active_of(of);
372390
}
373391

374392
static vm_fault_t kernfs_vma_fault(struct vm_fault *vmf)
@@ -380,14 +398,14 @@ static vm_fault_t kernfs_vma_fault(struct vm_fault *vmf)
380398
if (!of->vm_ops)
381399
return VM_FAULT_SIGBUS;
382400

383-
if (!kernfs_get_active(of->kn))
401+
if (!kernfs_get_active_of(of))
384402
return VM_FAULT_SIGBUS;
385403

386404
ret = VM_FAULT_SIGBUS;
387405
if (of->vm_ops->fault)
388406
ret = of->vm_ops->fault(vmf);
389407

390-
kernfs_put_active(of->kn);
408+
kernfs_put_active_of(of);
391409
return ret;
392410
}
393411

@@ -400,7 +418,7 @@ static vm_fault_t kernfs_vma_page_mkwrite(struct vm_fault *vmf)
400418
if (!of->vm_ops)
401419
return VM_FAULT_SIGBUS;
402420

403-
if (!kernfs_get_active(of->kn))
421+
if (!kernfs_get_active_of(of))
404422
return VM_FAULT_SIGBUS;
405423

406424
ret = 0;
@@ -409,7 +427,7 @@ static vm_fault_t kernfs_vma_page_mkwrite(struct vm_fault *vmf)
409427
else
410428
file_update_time(file);
411429

412-
kernfs_put_active(of->kn);
430+
kernfs_put_active_of(of);
413431
return ret;
414432
}
415433

@@ -423,14 +441,14 @@ static int kernfs_vma_access(struct vm_area_struct *vma, unsigned long addr,
423441
if (!of->vm_ops)
424442
return -EINVAL;
425443

426-
if (!kernfs_get_active(of->kn))
444+
if (!kernfs_get_active_of(of))
427445
return -EINVAL;
428446

429447
ret = -EINVAL;
430448
if (of->vm_ops->access)
431449
ret = of->vm_ops->access(vma, addr, buf, len, write);
432450

433-
kernfs_put_active(of->kn);
451+
kernfs_put_active_of(of);
434452
return ret;
435453
}
436454

@@ -460,7 +478,7 @@ static int kernfs_fop_mmap(struct file *file, struct vm_area_struct *vma)
460478
mutex_lock(&of->mutex);
461479

462480
rc = -ENODEV;
463-
if (!kernfs_get_active(of->kn))
481+
if (!kernfs_get_active_of(of))
464482
goto out_unlock;
465483

466484
ops = kernfs_ops(of->kn);
@@ -493,7 +511,7 @@ static int kernfs_fop_mmap(struct file *file, struct vm_area_struct *vma)
493511
of->vm_ops = vma->vm_ops;
494512
vma->vm_ops = &kernfs_vm_ops;
495513
out_put:
496-
kernfs_put_active(of->kn);
514+
kernfs_put_active_of(of);
497515
out_unlock:
498516
mutex_unlock(&of->mutex);
499517

@@ -847,15 +865,15 @@ static __poll_t kernfs_fop_poll(struct file *filp, poll_table *wait)
847865
struct kernfs_node *kn = kernfs_dentry_node(filp->f_path.dentry);
848866
__poll_t ret;
849867

850-
if (!kernfs_get_active(kn))
868+
if (!kernfs_get_active_of(of))
851869
return DEFAULT_POLLMASK|EPOLLERR|EPOLLPRI;
852870

853871
if (kn->attr.ops->poll)
854872
ret = kn->attr.ops->poll(of, wait);
855873
else
856874
ret = kernfs_generic_poll(of, wait);
857875

858-
kernfs_put_active(kn);
876+
kernfs_put_active_of(of);
859877
return ret;
860878
}
861879

0 commit comments

Comments
 (0)