summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Bugaev <bugaevc@gmail.com>2021-05-24 18:43:40 +0300
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2021-05-24 17:55:34 +0200
commitd9f93a335f230fe018747c075734646db70bdb7a (patch)
treebc3c78ae4988382b050ec0a7cddab4a1fabf9314
parent4c6ad5705584f9d76a67b0688ba66aef2eca66dc (diff)
procfs: Fix use-after-free
Fix several issues with reference counting in rootdir_make_translated_node (): * Grab an additional reference while still holding the lock. * Give the node an additional reference for being pointed to by the ops. * Reference the existing node if we find it on the second try, not only if we find it on the first try. * Dereference, not just clean, the created node if it turns out to be unneeded. Fixes a crash with the following backtrace: #2 0x010855c8 in __assert_fail_backtrace ( assertion=0x1051148 "! (r.hard == 1 && r.weak == 0) || !\"refcount detected use-after-free!\"", file=0x1050cec "../../libshouldbeinlibc/refcount.h", line=170, function=0x1051220 <__PRETTY_FUNCTION__.3> "refcounts_ref") at ../../libshouldbeinlibc/assert-backtrace.c:64 #3 0x01050358 in refcounts_ref (result=0x0, ref=0x15009a0) at ../../libshouldbeinlibc/refcount.h:170 #4 netfs_nref (np=0x15008f0) at ../../libnetfs/nref.c:26 #5 0x0804c9f4 in rootdir_make_translated_node (dir_hook=0x10001990, entry_hook=0x8055180 <__compound_literal.8>) at ../../procfs/rootdir.c:674 #6 0x0804ace3 in procfs_dir_lookup (hook=0x10001c10, name=0x2857efc "mounts", np=0x2855d68) at ../../procfs/procfs_dir.c:88 #7 0x0804a410 in procfs_lookup (np=0x10001c40, name=0x2857efc "mounts", npp=0x2855d68) at ../../procfs/procfs.c:185 #8 0x0804cae5 in dircat_lookup (hook=0x10001d50, name=0x2857efc "mounts", np=0x2855d68) at ../../procfs/dircat.c:76 #9 0x0804a410 in procfs_lookup (np=0x10001d80, name=0x2857efc "mounts", npp=0x2855d68) at ../../procfs/procfs.c:185 #10 0x0804a96f in netfs_attempt_lookup (user=0x1401c60, dir=0x10001d80, name=0x2857efc "mounts", np=0x2855d68) at ../../procfs/netfs.c:212 #11 0x0103fd5b in netfs_S_dir_lookup (dircred=<optimized out>, filename=<optimized out>, flags=<optimized out>, mode=<optimized out>, do_retry=<optimized out>, retry_name=<optimized out>, retry_port=<optimized out>, retry_port_type=<optimized out>) at ../../libnetfs/dir-lookup.c:175 Message-Id: <20210524154340.264885-2-bugaevc@gmail.com>
-rw-r--r--procfs/rootdir.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/procfs/rootdir.c b/procfs/rootdir.c
index 9f860a91..0e7c05c0 100644
--- a/procfs/rootdir.c
+++ b/procfs/rootdir.c
@@ -667,13 +667,12 @@ rootdir_make_translated_node (void *dir_hook, const void *entry_hook)
pthread_spin_lock (&rootdir_translated_node_lock);
np = *ops->npp;
+ if (np != NULL)
+ netfs_nref (np);
pthread_spin_unlock (&rootdir_translated_node_lock);
if (np != NULL)
- {
- netfs_nref (np);
- return np;
- }
+ return np;
np = procfs_make_node (entry_hook, (void *) entry_hook);
if (np == NULL)
@@ -686,11 +685,12 @@ rootdir_make_translated_node (void *dir_hook, const void *entry_hook)
prev = *ops->npp;
if (*ops->npp == NULL)
*ops->npp = np;
+ netfs_nref (*ops->npp);
pthread_spin_unlock (&rootdir_translated_node_lock);
if (prev != NULL)
{
- procfs_cleanup (np);
+ netfs_nrele (np);
np = prev;
}