commit-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[hurd] 57/87: include: detect use-after-free errors using the reference


From: Samuel Thibault
Subject: [hurd] 57/87: include: detect use-after-free errors using the reference counts
Date: Sun, 09 Nov 2014 11:05:04 +0000

This is an automated email from the git hooks/post-receive script.

sthibault pushed a commit to branch upstream
in repository hurd.

commit 5f1011ac0ad676d1e7eaba14d1384180e98fb93e
Author: Justus Winter <address@hidden>
Date:   Fri Jun 20 14:27:59 2014 +0200

    include: detect use-after-free errors using the reference counts
    
    * include/refcount.h (refcount_init): There must be at least one
    reference at initialization time.
    (refcounts_init): Likewise.
    (refcount_unsafe_ref): New function retaining the previous
    functionality of refcount_ref.  It is occasionally useful to raise the
    reference count again after it dropped to zero.
    (refcounts_unsafe_ref): Likewise.
    (refcounts_unsafe_weak_ref): Likewise.
    (refcount_ref): Detect use-after-free errors.
    (refcounts_ref): Likewise.
    (refcounts_ref_weak): Likewise.
    * libtrivfs/protid-clean.c (trivfs_clean_protid): Use refcount_unsafe_ref.
---
 include/refcount.h       | 73 ++++++++++++++++++++++++++++++++++++++++++------
 libtrivfs/protid-clean.c |  2 +-
 2 files changed, 66 insertions(+), 9 deletions(-)

diff --git a/include/refcount.h b/include/refcount.h
index 785b052..ebde42d 100644
--- a/include/refcount.h
+++ b/include/refcount.h
@@ -31,18 +31,23 @@
 /* An opaque type.  You must not access these values directly.  */
 typedef unsigned int refcount_t;
 
-/* Initialize REF with REFERENCES.  */
+/* Initialize REF with REFERENCES.  REFERENCES must not be zero.  */
 static inline void
 refcount_init (refcount_t *ref, unsigned int references)
 {
+  assert (references > 0 || !"references must not be zero!");
   *ref = references;
 }
 
 /* Increment REF.  Return the result of the operation.  This function
    uses atomic operations.  It is not required to serialize calls to
-   this function.  */
+   this function.
+
+   This is the unsafe version of refcount_ref.  refcount_ref also
+   checks for use-after-free errors.  When in doubt, use that one
+   instead.  */
 static inline unsigned int
-refcount_ref (refcount_t *ref)
+refcount_unsafe_ref (refcount_t *ref)
 {
   unsigned int r;
   r = __atomic_add_fetch (ref, 1, __ATOMIC_RELAXED);
@@ -50,6 +55,18 @@ refcount_ref (refcount_t *ref)
   return r;
 }
 
+/* Increment REF.  Return the result of the operation.  This function
+   uses atomic operations.  It is not required to serialize calls to
+   this function.  */
+static inline unsigned int
+refcount_ref (refcount_t *ref)
+{
+  unsigned int r;
+  r = refcount_unsafe_ref (ref);
+  assert (r != 1 || !"refcount detected use-after-free!");
+  return r;
+}
+
 /* Decrement REF.  Return the result of the operation.  This function
    uses atomic operations.  It is not required to serialize calls to
    this function.  */
@@ -101,19 +118,25 @@ union _references {
   uint64_t value;
 };
 
-/* Initialize REF with HARD and WEAK references.  */
+/* Initialize REF with HARD and WEAK references.  HARD and WEAK must
+   not both be zero.  */
 static inline void
 refcounts_init (refcounts_t *ref, uint32_t hard, uint32_t weak)
 {
+  assert ((hard != 0 || weak != 0) || !"references must not both be zero!");
   ref->references = (struct references) { .hard = hard, .weak = weak };
 }
 
 /* Increment the hard reference count of REF.  If RESULT is not NULL,
    the result of the operation is written there.  This function uses
    atomic operations.  It is not required to serialize calls to this
-   function.  */
+   function.
+
+   This is the unsafe version of refcounts_ref.  refcounts_ref also
+   checks for use-after-free errors.  When in doubt, use that one
+   instead.  */
 static inline void
-refcounts_ref (refcounts_t *ref, struct references *result)
+refcounts_unsafe_ref (refcounts_t *ref, struct references *result)
 {
   const union _references op = { .references = { .hard = 1 } };
   union _references r;
@@ -123,6 +146,21 @@ refcounts_ref (refcounts_t *ref, struct references *result)
     *result = r.references;
 }
 
+/* Increment the hard reference count of REF.  If RESULT is not NULL,
+   the result of the operation is written there.  This function uses
+   atomic operations.  It is not required to serialize calls to this
+   function.  */
+static inline void
+refcounts_ref (refcounts_t *ref, struct references *result)
+{
+  struct references r;
+  refcounts_unsafe_ref (ref, &r);
+  assert (! (r.hard == 1 && r.weak == 0)
+          || !"refcount detected use-after-free!");
+  if (result)
+    *result = r;
+}
+
 /* Decrement the hard reference count of REF.  If RESULT is not NULL,
    the result of the operation is written there.  This function uses
    atomic operations.  It is not required to serialize calls to this
@@ -200,9 +238,13 @@ refcounts_demote (refcounts_t *ref, struct references 
*result)
 /* Increment the weak reference count of REF.  If RESULT is not NULL,
    the result of the operation is written there.  This function uses
    atomic operations.  It is not required to serialize calls to this
-   function.  */
+   function.
+
+   This is the unsafe version of refcounts_ref_weak.
+   refcounts_ref_weak also checks for use-after-free errors.  When in
+   doubt, use that one instead.  */
 static inline void
-refcounts_ref_weak (refcounts_t *ref, struct references *result)
+refcounts_unsafe_ref_weak (refcounts_t *ref, struct references *result)
 {
   const union _references op = { .references = { .weak = 1 } };
   union _references r;
@@ -212,6 +254,21 @@ refcounts_ref_weak (refcounts_t *ref, struct references 
*result)
     *result = r.references;
 }
 
+/* Increment the weak reference count of REF.  If RESULT is not NULL,
+   the result of the operation is written there.  This function uses
+   atomic operations.  It is not required to serialize calls to this
+   function.  */
+static inline void
+refcounts_ref_weak (refcounts_t *ref, struct references *result)
+{
+  struct references r;
+  refcounts_unsafe_ref_weak (ref, &r);
+  assert (! (r.hard == 0 && r.weak == 1)
+          || !"refcount detected use-after-free!");
+  if (result)
+    *result = r;
+}
+
 /* Decrement the weak reference count of REF.  If RESULT is not NULL,
    the result of the operation is written there.  This function uses
    atomic operations.  It is not required to serialize calls to this
diff --git a/libtrivfs/protid-clean.c b/libtrivfs/protid-clean.c
index adc5e98..ff6cc16 100644
--- a/libtrivfs/protid-clean.c
+++ b/libtrivfs/protid-clean.c
@@ -36,7 +36,7 @@ trivfs_clean_protid (void *arg)
       if (refcount_deref (&cred->po->refcnt) == 0)
         {
           /* Reacquire a reference while we call the hook.  */
-          refcount_ref (&cred->po->refcnt);
+          refcount_unsafe_ref (&cred->po->refcnt);
           (*trivfs_peropen_destroy_hook) (cred->po);
           if (refcount_deref (&cred->po->refcnt) == 0)
             {

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-hurd/hurd.git



reply via email to

[Prev in Thread] Current Thread [Next in Thread]