The Samba-Bugzilla – Attachment 3000 Details for
Bug 5105
corrupted gencache.tdb causes an infinite loop in libsmbclient
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
proposed patch
0001-Add-upper-limits-to-hash-chain-and-freelist-lengths.patch (text/plain), 4.53 KB, created by
Volker Lendecke
on 2007-11-25 03:42:19 UTC
(
hide
)
Description:
proposed patch
Filename:
MIME Type:
Creator:
Volker Lendecke
Created:
2007-11-25 03:42:19 UTC
Size:
4.53 KB
patch
obsolete
>From 14d706b796c379e2347aed6a5103e2b0af6c839d Mon Sep 17 00:00:00 2001 >From: Volker Lendecke <vl@sernet.de> >Date: Sun, 25 Nov 2007 10:36:51 +0100 >Subject: [PATCH] Add upper limits to hash chain and freelist lengths > >This prevents completely endless loops, but it also might render some valid >tdb's as invalid. >--- > source/lib/tdb/common/freelist.c | 14 ++++++++++++++ > source/lib/tdb/common/tdb.c | 7 +++++++ > source/lib/tdb/common/tdb_private.h | 2 ++ > source/lib/tdb/common/traverse.c | 7 +++++++ > 4 files changed, 30 insertions(+), 0 deletions(-) > >diff --git a/source/lib/tdb/common/freelist.c b/source/lib/tdb/common/freelist.c >index b109643..078f5e9 100644 >--- a/source/lib/tdb/common/freelist.c >+++ b/source/lib/tdb/common/freelist.c >@@ -61,6 +61,7 @@ int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off, struct list_struct > static int remove_from_freelist(struct tdb_context *tdb, tdb_off_t off, tdb_off_t next) > { > tdb_off_t last_ptr, i; >+ int freelist_length = 0; > > /* read in the freelist top */ > last_ptr = FREELIST_TOP; >@@ -71,6 +72,12 @@ static int remove_from_freelist(struct tdb_context *tdb, tdb_off_t off, tdb_off_ > } > /* Follow chain (next offset is at start of record) */ > last_ptr = i; >+ >+ if (freelist_length++ > TDB_MAX_FREELIST_LENGTH) { >+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "remove_from_freelist: " >+ "cyclic freelist")); >+ return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); >+ } > } > TDB_LOG((tdb, TDB_DEBUG_FATAL,"remove_from_freelist: not on list at off=%d\n", off)); > return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); >@@ -261,6 +268,7 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_st > tdb_off_t rec_ptr, last_ptr; > tdb_len_t rec_len; > } bestfit; >+ int freelist_length = 0; > > if (tdb_lock(tdb, -1, F_WRLCK) == -1) > return 0; >@@ -307,6 +315,12 @@ tdb_off_t tdb_allocate(struct tdb_context *tdb, tdb_len_t length, struct list_st > /* move to the next record */ > last_ptr = rec_ptr; > rec_ptr = rec->next; >+ >+ if (freelist_length++ > TDB_MAX_FREELIST_LENGTH) { >+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_allocate: " >+ "cyclic freelist")); >+ goto fail; >+ } > } > > if (bestfit.rec_ptr != 0) { >diff --git a/source/lib/tdb/common/tdb.c b/source/lib/tdb/common/tdb.c >index 0e9d1db..dc4a82e 100644 >--- a/source/lib/tdb/common/tdb.c >+++ b/source/lib/tdb/common/tdb.c >@@ -79,6 +79,7 @@ static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, > struct list_struct *r) > { > tdb_off_t rec_ptr; >+ int chain_length = 0; > > /* read in the hash top */ > if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1) >@@ -97,6 +98,12 @@ static tdb_off_t tdb_find(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, > return rec_ptr; > } > rec_ptr = r->next; >+ >+ if (chain_length++ > TDB_MAX_HASHCHAIN_LENGTH) { >+ TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_find: " >+ "cyclic chain")); >+ return TDB_ERRCODE(TDB_ERR_CORRUPT, -1); >+ } > } > return TDB_ERRCODE(TDB_ERR_NOEXIST, 0); > } >diff --git a/source/lib/tdb/common/tdb_private.h b/source/lib/tdb/common/tdb_private.h >index 58c30c1..bd04c95 100644 >--- a/source/lib/tdb/common/tdb_private.h >+++ b/source/lib/tdb/common/tdb_private.h >@@ -59,6 +59,8 @@ typedef uint32_t tdb_off_t; > #define TDB_SEQNUM_OFS offsetof(struct tdb_header, sequence_number) > #define TDB_PAD_BYTE 0x42 > #define TDB_PAD_U32 0x42424242 >+#define TDB_MAX_HASHCHAIN_LENGTH (1000000) >+#define TDB_MAX_FREELIST_LENGTH (10000000) > > /* NB assumes there is a local variable called "tdb" that is the > * current context, also takes doubly-parenthesized print-style >diff --git a/source/lib/tdb/common/traverse.c b/source/lib/tdb/common/traverse.c >index 6fc576a..2b9a4a2 100644 >--- a/source/lib/tdb/common/traverse.c >+++ b/source/lib/tdb/common/traverse.c >@@ -35,6 +35,7 @@ static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tloc > > /* Lock each chain from the start one. */ > for (; tlock->hash < tdb->header.hash_size; tlock->hash++) { >+ int chain_length = 0; > if (!tlock->off && tlock->hash != 0) { > /* this is an optimisation for the common case where > the hash chain is empty, which is particularly >@@ -116,6 +117,12 @@ static int tdb_next_lock(struct tdb_context *tdb, struct tdb_traverse_lock *tloc > if (!(tdb->read_only || tdb->traverse_read) && > tdb_do_delete(tdb, current, rec) != 0) > goto fail; >+ >+ if (chain_length++ > TDB_MAX_HASHCHAIN_LENGTH) { >+ TDB_LOG((tdb, TDB_DEBUG_FATAL, >+ "tdb_next_lock: cyclic chain")); >+ goto fail; >+ } > } > tdb_unlock(tdb, tlock->hash, tlock->lock_rw); > want_next = 0; >-- >1.5.3.4 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 5105
:
2997
|
2998
|
2999
| 3000