mirror of
https://https.git.savannah.gnu.org/git/patch.git
synced 2026-01-27 01:44:34 +00:00
Invalidate child dirfd cache entries when their parent goes away
If we don't do that, a directory could be removed from the cache, a new directory with the same dirfd could be created, and the entries from the old directory would appear in the new directory. * src/safe.c (struct cached_dirfd): Keep track of the children of each dirfd cache entry. (remove_cached_dirfd): Remove all the entry's children from the lookup hash, take them off the list of children, and initialize the children's children_link. Then, remove the entry itself from its parent. This has no effect if the entry doesn't have a parent because then, children_link is empty. (openat_cached): Add new dirfd cache entries to their parent's list of children and initialize the entry's list of children. (traverse_another_path): Also initialize cwd's list of children.
This commit is contained in:
parent
c5705fd476
commit
914d06b7c3
13
src/safe.c
13
src/safe.c
@ -55,6 +55,7 @@ unsigned long dirfd_cache_misses;
|
||||
|
||||
struct cached_dirfd {
|
||||
struct list_head lru_link;
|
||||
struct list_head children_link, children;
|
||||
struct cached_dirfd *parent;
|
||||
|
||||
char *name;
|
||||
@ -124,6 +125,14 @@ static struct cached_dirfd *lookup_cached_dirfd (struct cached_dirfd *dir, const
|
||||
|
||||
static void remove_cached_dirfd (struct cached_dirfd *entry)
|
||||
{
|
||||
while (! list_empty (&entry->children))
|
||||
{
|
||||
struct cached_dirfd *child =
|
||||
list_entry (entry->children.next, struct cached_dirfd, children_link);
|
||||
list_del_init (&child->children_link);
|
||||
hash_delete (cached_dirfds, child);
|
||||
}
|
||||
list_del (&entry->children_link);
|
||||
list_del (&entry->lru_link);
|
||||
hash_delete (cached_dirfds, entry);
|
||||
free_cached_dirfd (entry);
|
||||
@ -208,6 +217,8 @@ static struct cached_dirfd *openat_cached (struct cached_dirfd *dir, const char
|
||||
/* Store new cache entry */
|
||||
entry = xmalloc (sizeof (struct cached_dirfd));
|
||||
INIT_LIST_HEAD (&entry->lru_link);
|
||||
list_add (&entry->children_link, &dir->children);
|
||||
INIT_LIST_HEAD (&entry->children);
|
||||
entry->parent = dir;
|
||||
entry->name = xstrdup (name);
|
||||
entry->fd = fd;
|
||||
@ -358,6 +369,8 @@ static int traverse_another_path (const char **pathname, int keepfd)
|
||||
struct symlink *stack = NULL;
|
||||
unsigned int steps = count_path_components (path);
|
||||
|
||||
INIT_LIST_HEAD (&cwd.children);
|
||||
|
||||
if (steps > MAX_PATH_COMPONENTS)
|
||||
{
|
||||
errno = ELOOP;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user