diff options
| author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-08-31 18:23:51 +0200 |
|---|---|---|
| committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2014-08-31 18:23:51 +0200 |
| commit | 4c61c7c157581cd3d9cb89d1bc8ddf23bbffda4a (patch) | |
| tree | 25cc7727f4f07c372e47cdd5768a6903d73c32b4 /debian/patches/0001-include-detect-use-after-free-errors-using-the-refer.patch | |
| parent | f5e1f18a41e2d56542515b26c30d43b04295740a (diff) | |
add patch series
Diffstat (limited to 'debian/patches/0001-include-detect-use-after-free-errors-using-the-refer.patch')
| -rw-r--r-- | debian/patches/0001-include-detect-use-after-free-errors-using-the-refer.patch | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/debian/patches/0001-include-detect-use-after-free-errors-using-the-refer.patch b/debian/patches/0001-include-detect-use-after-free-errors-using-the-refer.patch new file mode 100644 index 00000000..49121824 --- /dev/null +++ b/debian/patches/0001-include-detect-use-after-free-errors-using-the-refer.patch @@ -0,0 +1,116 @@ +From 940c8c530cb0070d1a2a68c9564d660d1bdd0a22 Mon Sep 17 00:00:00 2001 +From: Justus Winter <4winter@informatik.uni-hamburg.de> +Date: Fri, 20 Jun 2014 14:27:59 +0200 +Subject: [PATCH] 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. +(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 | 30 ++++++++++++++++++++++++++---- + libtrivfs/protid-clean.c | 2 +- + 2 files changed, 27 insertions(+), 5 deletions(-) + +diff --git a/include/refcount.h b/include/refcount.h +index 785b052..1db50e7 100644 +--- a/include/refcount.h ++++ b/include/refcount.h +@@ -31,18 +31,22 @@ + /* 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, which 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 +54,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,10 +117,12 @@ 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 }; + } + +@@ -119,6 +137,8 @@ refcounts_ref (refcounts_t *ref, struct references *result) + union _references r; + r.value = __atomic_add_fetch (&ref->value, op.value, __ATOMIC_RELAXED); + assert (r.references.hard != UINT32_MAX || !"refcount overflowed!"); ++ assert (! (r.references.hard == 1 && r.references.weak == 0) ++ || !"refcount detected use after free!"); + if (result) + *result = r.references; + } +@@ -208,6 +228,8 @@ refcounts_ref_weak (refcounts_t *ref, struct references *result) + union _references r; + r.value = __atomic_add_fetch (&ref->value, op.value, __ATOMIC_RELAXED); + assert (r.references.weak != UINT32_MAX || !"refcount overflowed!"); ++ assert (! (r.references.hard == 0 && r.references.weak == 1) ++ || !"refcount detected use after free!"); + if (result) + *result = r.references; + } +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) + { +-- +2.1.0 + |
