Skip to content

Commit b8024ea

Browse files
Merge pull request #70 from douzzer/20250221-rwlock-overflow-guards
20250221-rwlock-overflow-guards
2 parents 7d8683e + d35978d commit b8024ea

File tree

5 files changed

+97
-10
lines changed

5 files changed

+97
-10
lines changed

Makefile.analyzers

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ endif
3333
# lock in the expected major versions of LLVM/clang/compiler-rt-sanitizers, in
3434
# order of preference:
3535
ifndef CLANG_PATH
36-
CLANG_PATH:=/usr/lib/llvm/20/bin:/usr/lib/llvm/19/bin:/usr/lib/llvm/18/bin:/usr/lib/llvm-18:/usr/lib/llvm/17/bin:/usr/lib/llvm-17:/usr/lib/llvm/16/bin:/usr/lib/llvm-16:/usr/lib/llvm/15/bin:/usr/lib/llvm-15:/usr/lib/llvm/14/bin:/usr/lib/llvm-14:/opt/homebrew/opt/llvm/bin
36+
CLANG_PATH:=/usr/lib/llvm/21/bin:/usr/lib/llvm/20/bin:/usr/lib/llvm/19/bin:/usr/lib/llvm/18/bin:/usr/lib/llvm-18:/usr/lib/llvm/17/bin:/usr/lib/llvm-17:/usr/lib/llvm/16/bin:/usr/lib/llvm-16:/usr/lib/llvm/15/bin:/usr/lib/llvm-15:/usr/lib/llvm/14/bin:/usr/lib/llvm-14:/opt/homebrew/opt/llvm/bin
3737
endif
3838

3939
valgrind-all-clang: PATH:=$(CLANG_PATH):$(PATH)

doc/wolfSentry_refman.pdf

744 Bytes
Binary file not shown.

src/wolfsentry_internal.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,11 @@ struct wolfsentry_table_ent_header
203203
#endif
204204
{
205205
struct wolfsentry_table_header *parent_table;
206-
struct wolfsentry_table_ent_header *prev, *next; /* these will be replaced by red-black table elements later. */
206+
struct wolfsentry_table_ent_header *prev, *next; /* these will be supplemented by red-black table elements later. */
207207
struct wolfsentry_table_ent_header *prev_by_id, *next_by_id; /* these will be replaced by red-black table elements later. */
208-
wolfsentry_hitcount_t hitcount;
209208
wolfsentry_ent_id_t id;
210-
uint32_t _pad1;
209+
uint32_t _pad1; /* this will later hold color bits for the red-black table elements */
210+
wolfsentry_hitcount_t hitcount;
211211
wolfsentry_refcount_t refcount;
212212
};
213213

src/wolfsentry_util.c

+88-6
Original file line numberDiff line numberDiff line change
@@ -1840,6 +1840,15 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_shared_abstimed(struct wolfs
18401840
WOLFSENTRY_ERROR_RETURN(BUSY);
18411841
}
18421842

1843+
if ((lock->read_waiter_count == WOLFSENTRY_RWLOCK_MAX_COUNT) ||
1844+
(thread->shared_count == WOLFSENTRY_RWLOCK_MAX_COUNT))
1845+
{
1846+
if (sem_post(&lock->sem) < 0)
1847+
WOLFSENTRY_ERROR_RETURN(SYS_OP_FATAL);
1848+
else
1849+
WOLFSENTRY_ERROR_RETURN(OVERFLOW_AVERTED);
1850+
}
1851+
18431852
++lock->read_waiter_count;
18441853

18451854
if (sem_post(&lock->sem) < 0)
@@ -1899,7 +1908,7 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_shared_abstimed(struct wolfs
18991908
thread->tracked_shared_lock = lock;
19001909
thread->recursion_of_tracked_lock = 1;
19011910
}
1902-
else if (thread->tracked_shared_lock == lock)
1911+
else if (thread->tracked_shared_lock == lock) /* can't happen */
19031912
++thread->recursion_of_tracked_lock;
19041913

19051914
if ((flags & (WOLFSENTRY_LOCK_FLAG_GET_RESERVATION_TOO | WOLFSENTRY_LOCK_FLAG_TRY_RESERVATION_TOO)) &&
@@ -1961,6 +1970,18 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_shared_abstimed(struct wolfs
19611970
store_reservation = 1;
19621971
}
19631972

1973+
if ((lock->read_waiter_count == WOLFSENTRY_RWLOCK_MAX_COUNT) ||
1974+
(thread->shared_count == WOLFSENTRY_RWLOCK_MAX_COUNT) ||
1975+
((thread->tracked_shared_lock == lock) && (thread->recursion_of_tracked_lock == WOLFSENTRY_RWLOCK_MAX_COUNT)) ||
1976+
(lock->holder_count.read >= WOLFSENTRY_RWLOCK_MAX_COUNT - store_reservation) ||
1977+
(store_reservation && (thread->mutex_and_reservation_count == WOLFSENTRY_RWLOCK_MAX_COUNT)))
1978+
{
1979+
if (sem_post(&lock->sem) < 0)
1980+
WOLFSENTRY_ERROR_RETURN(SYS_OP_FATAL);
1981+
else
1982+
WOLFSENTRY_ERROR_RETURN(OVERFLOW_AVERTED);
1983+
}
1984+
19641985
if (lock->state == WOLFSENTRY_LOCK_UNLOCKED)
19651986
WOLFSENTRY_ATOMIC_STORE(lock->state, WOLFSENTRY_LOCK_SHARED);
19661987

@@ -2031,6 +2052,11 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_mutex_abstimed(struct wolfse
20312052
case WOLFSENTRY_LOCK_EXCLUSIVE:
20322053
if (WOLFSENTRY_ATOMIC_LOAD(lock->write_lock_holder) == WOLFSENTRY_THREAD_GET_ID) {
20332054
if (! (flags & WOLFSENTRY_LOCK_FLAG_NONRECURSIVE_MUTEX)) {
2055+
if ((lock->holder_count.write == WOLFSENTRY_RWLOCK_MAX_COUNT) ||
2056+
(thread && (thread->mutex_and_reservation_count == WOLFSENTRY_RWLOCK_MAX_COUNT)))
2057+
{
2058+
WOLFSENTRY_ERROR_RETURN(OVERFLOW_AVERTED);
2059+
}
20342060
/* recursively locking while holding write is effectively uncontended. */
20352061
++lock->holder_count.write;
20362062
if (thread)
@@ -2047,18 +2073,22 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_mutex_abstimed(struct wolfse
20472073
if (flags & WOLFSENTRY_LOCK_FLAG_NONRECURSIVE_MUTEX)
20482074
WOLFSENTRY_ERROR_RETURN(INCOMPATIBLE_STATE);
20492075
else {
2076+
if (thread && (thread->mutex_and_reservation_count == WOLFSENTRY_RWLOCK_MAX_COUNT))
2077+
WOLFSENTRY_ERROR_RETURN(OVERFLOW_AVERTED);
20502078
ret = wolfsentry_lock_shared2mutex_redeem_abstimed(lock, thread, abs_timeout, flags);
20512079
WOLFSENTRY_RERETURN_IF_ERROR(ret);
2052-
++lock->holder_count.write;
2080+
++lock->holder_count.write; /* caller now holds the lock at least 2 deep. */
20532081
if (thread)
20542082
++thread->mutex_and_reservation_count;
20552083
WOLFSENTRY_RETURN_OK;
20562084
}
20572085
}
20582086
else if (thread && (thread->tracked_shared_lock == lock)) {
2087+
if (thread && (thread->mutex_and_reservation_count == WOLFSENTRY_RWLOCK_MAX_COUNT))
2088+
WOLFSENTRY_ERROR_RETURN(OVERFLOW_AVERTED);
20592089
ret = wolfsentry_lock_shared2mutex_abstimed(lock, thread, abs_timeout, flags);
20602090
WOLFSENTRY_RERETURN_IF_ERROR(ret);
2061-
++lock->holder_count.write;
2091+
++lock->holder_count.write; /* caller now holds the lock at least 2 deep. */
20622092
if (thread)
20632093
++thread->mutex_and_reservation_count;
20642094
WOLFSENTRY_RETURN_OK;
@@ -2125,6 +2155,14 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_mutex_abstimed(struct wolfse
21252155
WOLFSENTRY_ERROR_RETURN(BUSY);
21262156
}
21272157

2158+
if ((lock->write_waiter_count == WOLFSENTRY_RWLOCK_MAX_COUNT) ||
2159+
(thread && (thread->mutex_and_reservation_count == WOLFSENTRY_RWLOCK_MAX_COUNT)))
2160+
{
2161+
if (sem_post(&lock->sem) < 0)
2162+
WOLFSENTRY_ERROR_RETURN(SYS_OP_FATAL);
2163+
else
2164+
WOLFSENTRY_ERROR_RETURN(OVERFLOW_AVERTED);
2165+
}
21282166
++lock->write_waiter_count;
21292167

21302168
if (sem_post(&lock->sem) < 0)
@@ -2272,15 +2310,29 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_mutex2shared(struct wolfsent
22722310
WOLFSENTRY_ERROR_RETURN(INCOMPATIBLE_STATE);
22732311
}
22742312

2313+
if (thread->shared_count >= WOLFSENTRY_RWLOCK_MAX_COUNT - lock->holder_count.write) {
2314+
if (sem_post(&lock->sem) < 0)
2315+
WOLFSENTRY_ERROR_RETURN(SYS_OP_FATAL);
2316+
else
2317+
WOLFSENTRY_ERROR_RETURN(OVERFLOW_AVERTED);
2318+
}
2319+
22752320
if (flags & (WOLFSENTRY_LOCK_FLAG_GET_RESERVATION_TOO | WOLFSENTRY_LOCK_FLAG_TRY_RESERVATION_TOO)) {
2276-
/* can't happen, but be sure. */
2277-
if (lock->read2write_reservation_holder != WOLFSENTRY_THREAD_NO_ID) {
2321+
if (lock->read2write_reservation_holder != WOLFSENTRY_THREAD_NO_ID) /* can't happen, but be sure. */ {
22782322
if (sem_post(&lock->sem) < 0)
22792323
WOLFSENTRY_ERROR_RETURN(SYS_OP_FATAL);
22802324
WOLFSENTRY_ERROR_RETURN(INTERNAL_CHECK_FATAL);
22812325
}
2282-
WOLFSENTRY_ATOMIC_STORE(lock->read2write_reservation_holder, lock->write_lock_holder);
2326+
if ((thread->mutex_and_reservation_count == WOLFSENTRY_RWLOCK_MAX_COUNT) ||
2327+
(lock->holder_count.write == WOLFSENTRY_RWLOCK_MAX_COUNT))
2328+
{
2329+
if (sem_post(&lock->sem) < 0)
2330+
WOLFSENTRY_ERROR_RETURN(SYS_OP_FATAL);
2331+
else
2332+
WOLFSENTRY_ERROR_RETURN(OVERFLOW_AVERTED);
2333+
}
22832334
++thread->mutex_and_reservation_count;
2335+
WOLFSENTRY_ATOMIC_STORE(lock->read2write_reservation_holder, lock->write_lock_holder);
22842336
lock->read2write_waiter_read_count = lock->holder_count.write;
22852337
/* note, not incrementing write_waiter_count, to allow shared lockers to get locks until the redemption phase. */
22862338
}
@@ -2344,6 +2396,9 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_shared2mutex_reserve(struct
23442396
WOLFSENTRY_ERROR_RETURN(INCOMPATIBLE_STATE);
23452397
}
23462398

2399+
if (thread->mutex_and_reservation_count == WOLFSENTRY_RWLOCK_MAX_COUNT)
2400+
WOLFSENTRY_ERROR_RETURN(OVERFLOW_AVERTED);
2401+
23472402
for (;;) {
23482403
int ret = sem_wait(&lock->sem);
23492404
if (ret == 0)
@@ -2369,6 +2424,13 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_shared2mutex_reserve(struct
23692424
WOLFSENTRY_ERROR_RETURN(BUSY);
23702425
}
23712426

2427+
if (lock->holder_count.read == WOLFSENTRY_RWLOCK_MAX_COUNT) {
2428+
if (sem_post(&lock->sem) < 0)
2429+
WOLFSENTRY_ERROR_RETURN(SYS_OP_FATAL);
2430+
else
2431+
WOLFSENTRY_ERROR_RETURN(OVERFLOW_AVERTED);
2432+
}
2433+
23722434
WOLFSENTRY_ATOMIC_STORE(lock->read2write_reservation_holder, WOLFSENTRY_THREAD_GET_ID);
23732435
++thread->mutex_and_reservation_count;
23742436
/* note, not incrementing write_waiter_count, to allow shared lockers to get locks until the redemption phase. */
@@ -2457,6 +2519,15 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_shared2mutex_redeem_abstimed
24572519
WOLFSENTRY_ERROR_RETURN(INCOMPATIBLE_STATE);
24582520
}
24592521

2522+
if ((thread->mutex_and_reservation_count >= WOLFSENTRY_RWLOCK_MAX_COUNT - lock->read2write_waiter_read_count) ||
2523+
(lock->write_waiter_count == WOLFSENTRY_RWLOCK_MAX_COUNT))
2524+
{
2525+
if (sem_post(&lock->sem) < 0)
2526+
WOLFSENTRY_ERROR_RETURN(SYS_OP_FATAL);
2527+
else
2528+
WOLFSENTRY_ERROR_RETURN(OVERFLOW_AVERTED);
2529+
}
2530+
24602531
if (lock->holder_count.read == lock->read2write_waiter_read_count + 1) {
24612532
--lock->holder_count.read; /* remove extra count associated with the reservation. */
24622533
lock->promoted_at_count = lock->holder_count.read;
@@ -2713,6 +2784,17 @@ WOLFSENTRY_API wolfsentry_errcode_t wolfsentry_lock_shared2mutex_abstimed(struct
27132784
WOLFSENTRY_ERROR_RETURN(BUSY);
27142785
}
27152786

2787+
if ((thread->mutex_and_reservation_count
2788+
>=
2789+
((thread->tracked_shared_lock == lock) ? WOLFSENTRY_RWLOCK_MAX_COUNT : (WOLFSENTRY_RWLOCK_MAX_COUNT - thread->recursion_of_tracked_lock))) ||
2790+
(lock->write_waiter_count == WOLFSENTRY_RWLOCK_MAX_COUNT))
2791+
{
2792+
if (sem_post(&lock->sem) < 0)
2793+
WOLFSENTRY_ERROR_RETURN(SYS_OP_FATAL);
2794+
else
2795+
WOLFSENTRY_ERROR_RETURN(OVERFLOW_AVERTED);
2796+
}
2797+
27162798
if ((lock->holder_count.read == 1)
27172799
|| ((thread->tracked_shared_lock == lock)
27182800
&& (lock->holder_count.read == thread->recursion_of_tracked_lock)))

wolfsentry/wolfsentry_settings.h

+5
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,11 @@ typedef uint16_t wolfsentry_priority_t;
714714
/*!< \brief The maximum size allowed for scalar user-defined values. Can be overridden. */
715715
#endif
716716

717+
#ifndef WOLFSENTRY_RWLOCK_MAX_COUNT
718+
#define WOLFSENTRY_RWLOCK_MAX_COUNT ((int)MAX_SINT_OF(int))
719+
/*!< \brief The maximum count allowed for any internal lock-counting value, limiting recursion. Defaults to the maximum countable. Can be overridden. */
720+
#endif
721+
717722
#if defined(WOLFSENTRY_ENT_ID_TYPE) || \
718723
defined(WOLFSENTRY_HITCOUNT_TYPE) || \
719724
defined(WOLFSENTRY_TIME_TYPE) || \

0 commit comments

Comments
 (0)