diff options
author | Ken Raeburn <raeburn@mit.edu> | 2004-12-15 03:02:43 +0000 |
---|---|---|
committer | Ken Raeburn <raeburn@mit.edu> | 2004-12-15 03:02:43 +0000 |
commit | a16e6f12ea8191addbd261bb0d56684a58bdf46d (patch) | |
tree | 3316ec710771d9fa84b7b3ed32c4241471dfa8bc /src/util/profile/prof_tree.c | |
parent | 398f4520c2a9357d6ab5aff8be6dec89846674bf (diff) | |
download | krb5-a16e6f12ea8191addbd261bb0d56684a58bdf46d.tar.gz krb5-a16e6f12ea8191addbd261bb0d56684a58bdf46d.tar.xz krb5-a16e6f12ea8191addbd261bb0d56684a58bdf46d.zip |
insufficient locking in profile re-reading case
If profiles are open and iterators in use while the on-disk file is being
modified (see tests/threads/prof1.c), the re-reading of the file can cause data
to be freed up. The iterator code does no locking and assumes that the profile
node tree won't be touched.
During our Monday meeting we discussed changing the iterator code to "snapshot"
the current state of the file if it were modified, so that a more consistent
picture could be returned, essentially by bumping a reference count for the
life of the iterator object. The reference count I was thinking of turns out
to be used for a different purpose; we'd have to add another layer of
indirection, another ref count, and another mutex to accomplish this. There
might be a more reasonable way to go about it, but I don't want to tackle it
for 1.4 when we're already shipping beta releases.
This patch just adds locking to the current iterator code so that the file data
can't be replaced while the iterator is being processed. The inconsistent-view
issue remains.
* prof_tree.c (profile_node_iterator): When the iterator has a current file,
lock it, and unlock it before changing it or returning.
ticket: new
status: resolved
target_version: 1.4
tags: pullup
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@16932 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/util/profile/prof_tree.c')
-rw-r--r-- | src/util/profile/prof_tree.c | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/src/util/profile/prof_tree.c b/src/util/profile/prof_tree.c index 1d96ffbb82..eea34f60b6 100644 --- a/src/util/profile/prof_tree.c +++ b/src/util/profile/prof_tree.c @@ -466,17 +466,27 @@ errcode_t profile_node_iterator(void **iter_p, struct profile_node **ret_node, * If the file has changed, then the node pointer is invalid, * so we'll have search the file again looking for it. */ + if (iter->file) { + retval = k5_mutex_lock(&iter->file->data->lock); + if (retval) + return retval; + } if (iter->node && (iter->file->data->upd_serial != iter->file_serial)) { iter->flags &= ~PROFILE_ITER_FINAL_SEEN; skip_num = iter->num; iter->node = 0; } - if (iter->node && iter->node->magic != PROF_MAGIC_NODE) + if (iter->node && iter->node->magic != PROF_MAGIC_NODE) { + if (iter->file) + k5_mutex_unlock(&iter->file->data->lock); return PROF_MAGIC_NODE; + } get_new_file: if (iter->node == 0) { if (iter->file == 0 || (iter->flags & PROFILE_ITER_FINAL_SEEN)) { + if (iter->file) + k5_mutex_unlock(&iter->file->data->lock); profile_node_iterator_free(iter_p); if (ret_node) *ret_node = 0; @@ -486,10 +496,18 @@ get_new_file: *ret_value =0; return 0; } + k5_mutex_unlock(&iter->file->data->lock); if ((retval = profile_update_file(iter->file))) { if (retval == ENOENT || retval == EACCES) { /* XXX memory leak? */ iter->file = iter->file->next; + if (iter->file) { + retval = k5_mutex_lock(&iter->file->data->lock); + if (retval) { + profile_node_iterator_free(iter_p); + return retval; + } + } skip_num = 0; retval = 0; goto get_new_file; @@ -498,6 +516,11 @@ get_new_file: return retval; } } + retval = k5_mutex_lock(&iter->file->data->lock); + if (retval) { + profile_node_iterator_free(iter_p); + return retval; + } iter->file_serial = iter->file->data->upd_serial; /* * Find the section to list if we are a LIST_SECTION, @@ -518,7 +541,15 @@ get_new_file: iter->flags |= PROFILE_ITER_FINAL_SEEN; } if (!section) { + k5_mutex_unlock(&iter->file->data->lock); iter->file = iter->file->next; + if (iter->file) { + retval = k5_mutex_lock(&iter->file->data->lock); + if (retval) { + profile_node_iterator_free(iter_p); + return retval; + } + } skip_num = 0; goto get_new_file; } @@ -546,11 +577,20 @@ get_new_file: } iter->num++; if (!p) { + k5_mutex_unlock(&iter->file->data->lock); iter->file = iter->file->next; + if (iter->file) { + retval = k5_mutex_lock(&iter->file->data->lock); + if (retval) { + profile_node_iterator_free(iter_p); + return retval; + } + } iter->node = 0; skip_num = 0; goto get_new_file; } + k5_mutex_unlock(&iter->file->data->lock); if ((iter->node = p->next) == NULL) iter->file = iter->file->next; if (ret_node) |