From: Jan Kara <jack@suse.cz> To: Paul Moore <paul@paul-moore.com> Cc: Al Viro <viro@ZenIV.linux.org.uk>, linux-audit@redhat.com, <linux-fsdevel@vger.kernel.org>, rgb@redhat.com, Amir Goldstein <amir73il@gmail.com>, Jan Kara <jack@suse.cz> Subject: [PATCH 02/11] audit: Fix possible spurious -ENOSPC error Date: Tue, 4 Sep 2018 18:06:22 +0200 [thread overview] Message-ID: <20180904160632.21210-3-jack@suse.cz> (raw) In-Reply-To: <20180904160632.21210-1-jack@suse.cz> When an inode is tagged with a tree, tag_chunk() checks whether there is audit_tree_group mark attached to the inode and adds one if not. However nothing protects another tag_chunk() to add the mark between we've checked and try to add the fsnotify mark thus resulting in an error from fsnotify_add_mark() and consequently an ENOSPC error from tag_chunk(). Fix the problem by holding mark_mutex over the whole check-insert code sequence. Signed-off-by: Jan Kara <jack@suse.cz> --- kernel/audit_tree.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 1b55b1026a36..8a74b468b666 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -342,25 +342,29 @@ static void untag_chunk(struct node *p) spin_lock(&hash_lock); } +/* Call with group->mark_mutex held, releases it */ static int create_chunk(struct inode *inode, struct audit_tree *tree) { struct fsnotify_mark *entry; struct audit_chunk *chunk = alloc_chunk(1); - if (!chunk) + + if (!chunk) { + mutex_unlock(&audit_tree_group->mark_mutex); return -ENOMEM; + } entry = &chunk->mark; - if (fsnotify_add_inode_mark(entry, inode, 0)) { + if (fsnotify_add_inode_mark_locked(entry, inode, 0)) { + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_put_mark(entry); return -ENOSPC; } - mutex_lock(&entry->group->mark_mutex); spin_lock(&hash_lock); if (tree->goner) { spin_unlock(&hash_lock); chunk->dead = 1; - mutex_unlock(&entry->group->mark_mutex); + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_destroy_mark(entry, audit_tree_group); fsnotify_put_mark(entry); return 0; @@ -375,7 +379,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) } insert_hash(chunk); spin_unlock(&hash_lock); - mutex_unlock(&entry->group->mark_mutex); + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_put_mark(entry); /* drop initial reference */ return 0; } @@ -389,6 +393,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) struct node *p; int n; + mutex_lock(&audit_tree_group->mark_mutex); old_entry = fsnotify_find_mark(&inode->i_fsnotify_marks, audit_tree_group); if (!old_entry) @@ -401,6 +406,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) for (n = 0; n < old->count; n++) { if (old->owners[n].owner == tree) { spin_unlock(&hash_lock); + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_put_mark(old_entry); return 0; } @@ -409,20 +415,20 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) chunk = alloc_chunk(old->count + 1); if (!chunk) { + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_put_mark(old_entry); return -ENOMEM; } chunk_entry = &chunk->mark; - mutex_lock(&old_entry->group->mark_mutex); /* * mark_mutex protects mark from getting detached and thus also from * mark->connector->obj getting NULL. */ if (!(old_entry->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) { /* old_entry is being shot, lets just lie */ - mutex_unlock(&old_entry->group->mark_mutex); + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_put_mark(old_entry); fsnotify_put_mark(&chunk->mark); return -ENOENT; @@ -430,7 +436,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) if (fsnotify_add_mark_locked(chunk_entry, old_entry->connector->obj, FSNOTIFY_OBJ_TYPE_INODE, 1)) { - mutex_unlock(&old_entry->group->mark_mutex); + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_put_mark(chunk_entry); fsnotify_put_mark(old_entry); return -ENOSPC; @@ -440,7 +446,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) if (tree->goner) { spin_unlock(&hash_lock); chunk->dead = 1; - mutex_unlock(&old_entry->group->mark_mutex); + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_destroy_mark(chunk_entry, audit_tree_group); @@ -471,7 +477,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) list_add(&tree->same_root, &chunk->trees); } spin_unlock(&hash_lock); - mutex_unlock(&old_entry->group->mark_mutex); + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_destroy_mark(old_entry, audit_tree_group); fsnotify_put_mark(chunk_entry); /* drop initial reference */ fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */ -- 2.16.4
WARNING: multiple messages have this Message-ID (diff)
From: Jan Kara <jack@suse.cz> To: Paul Moore <paul@paul-moore.com> Cc: Jan Kara <jack@suse.cz>, rgb@redhat.com, Amir Goldstein <amir73il@gmail.com>, linux-audit@redhat.com, Al Viro <viro@ZenIV.linux.org.uk>, linux-fsdevel@vger.kernel.org Subject: [PATCH 02/11] audit: Fix possible spurious -ENOSPC error Date: Tue, 4 Sep 2018 18:06:22 +0200 [thread overview] Message-ID: <20180904160632.21210-3-jack@suse.cz> (raw) In-Reply-To: <20180904160632.21210-1-jack@suse.cz> When an inode is tagged with a tree, tag_chunk() checks whether there is audit_tree_group mark attached to the inode and adds one if not. However nothing protects another tag_chunk() to add the mark between we've checked and try to add the fsnotify mark thus resulting in an error from fsnotify_add_mark() and consequently an ENOSPC error from tag_chunk(). Fix the problem by holding mark_mutex over the whole check-insert code sequence. Signed-off-by: Jan Kara <jack@suse.cz> --- kernel/audit_tree.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 1b55b1026a36..8a74b468b666 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -342,25 +342,29 @@ static void untag_chunk(struct node *p) spin_lock(&hash_lock); } +/* Call with group->mark_mutex held, releases it */ static int create_chunk(struct inode *inode, struct audit_tree *tree) { struct fsnotify_mark *entry; struct audit_chunk *chunk = alloc_chunk(1); - if (!chunk) + + if (!chunk) { + mutex_unlock(&audit_tree_group->mark_mutex); return -ENOMEM; + } entry = &chunk->mark; - if (fsnotify_add_inode_mark(entry, inode, 0)) { + if (fsnotify_add_inode_mark_locked(entry, inode, 0)) { + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_put_mark(entry); return -ENOSPC; } - mutex_lock(&entry->group->mark_mutex); spin_lock(&hash_lock); if (tree->goner) { spin_unlock(&hash_lock); chunk->dead = 1; - mutex_unlock(&entry->group->mark_mutex); + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_destroy_mark(entry, audit_tree_group); fsnotify_put_mark(entry); return 0; @@ -375,7 +379,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) } insert_hash(chunk); spin_unlock(&hash_lock); - mutex_unlock(&entry->group->mark_mutex); + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_put_mark(entry); /* drop initial reference */ return 0; } @@ -389,6 +393,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) struct node *p; int n; + mutex_lock(&audit_tree_group->mark_mutex); old_entry = fsnotify_find_mark(&inode->i_fsnotify_marks, audit_tree_group); if (!old_entry) @@ -401,6 +406,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) for (n = 0; n < old->count; n++) { if (old->owners[n].owner == tree) { spin_unlock(&hash_lock); + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_put_mark(old_entry); return 0; } @@ -409,20 +415,20 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) chunk = alloc_chunk(old->count + 1); if (!chunk) { + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_put_mark(old_entry); return -ENOMEM; } chunk_entry = &chunk->mark; - mutex_lock(&old_entry->group->mark_mutex); /* * mark_mutex protects mark from getting detached and thus also from * mark->connector->obj getting NULL. */ if (!(old_entry->flags & FSNOTIFY_MARK_FLAG_ATTACHED)) { /* old_entry is being shot, lets just lie */ - mutex_unlock(&old_entry->group->mark_mutex); + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_put_mark(old_entry); fsnotify_put_mark(&chunk->mark); return -ENOENT; @@ -430,7 +436,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) if (fsnotify_add_mark_locked(chunk_entry, old_entry->connector->obj, FSNOTIFY_OBJ_TYPE_INODE, 1)) { - mutex_unlock(&old_entry->group->mark_mutex); + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_put_mark(chunk_entry); fsnotify_put_mark(old_entry); return -ENOSPC; @@ -440,7 +446,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) if (tree->goner) { spin_unlock(&hash_lock); chunk->dead = 1; - mutex_unlock(&old_entry->group->mark_mutex); + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_destroy_mark(chunk_entry, audit_tree_group); @@ -471,7 +477,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) list_add(&tree->same_root, &chunk->trees); } spin_unlock(&hash_lock); - mutex_unlock(&old_entry->group->mark_mutex); + mutex_unlock(&audit_tree_group->mark_mutex); fsnotify_destroy_mark(old_entry, audit_tree_group); fsnotify_put_mark(chunk_entry); /* drop initial reference */ fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */ -- 2.16.4
next prev parent reply other threads:[~2018-09-04 20:32 UTC|newest] Thread overview: 80+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-09-04 16:06 [PATCH 0/11 v3] audit: Fix various races when tagging and untagging mounts Jan Kara 2018-09-04 16:06 ` Jan Kara 2018-09-04 16:06 ` [PATCH 01/11] audit_tree: Remove mark->lock locking Jan Kara 2018-09-04 16:06 ` Jan Kara 2018-09-04 16:06 ` Jan Kara [this message] 2018-09-04 16:06 ` [PATCH 02/11] audit: Fix possible spurious -ENOSPC error Jan Kara 2018-09-04 16:06 ` [PATCH 03/11] audit: Fix possible tagging failures Jan Kara 2018-09-04 16:06 ` Jan Kara 2018-09-04 16:06 ` [PATCH 04/11] audit: Embed key into chunk Jan Kara 2018-09-04 16:06 ` Jan Kara 2018-09-13 20:06 ` Richard Guy Briggs 2018-09-13 20:06 ` Richard Guy Briggs 2018-09-04 16:06 ` [PATCH 05/11] audit: Make hash table insertion safe against concurrent lookups Jan Kara 2018-09-04 16:06 ` Jan Kara 2018-09-04 16:06 ` [PATCH 06/11] audit: Factor out chunk replacement code Jan Kara 2018-09-04 16:06 ` Jan Kara 2018-09-04 16:06 ` [PATCH 07/11] audit: Remove pointless check in insert_hash() Jan Kara 2018-09-04 16:06 ` Jan Kara 2018-09-04 16:06 ` [PATCH 08/11] audit: Provide helper for dropping mark's chunk reference Jan Kara 2018-09-04 16:06 ` Jan Kara 2018-09-04 16:06 ` [PATCH 09/11] audit: Allocate fsnotify mark independently of chunk Jan Kara 2018-09-04 16:06 ` Jan Kara 2018-09-14 14:09 ` Richard Guy Briggs 2018-09-14 14:09 ` Richard Guy Briggs 2018-09-17 16:46 ` Jan Kara 2018-09-17 16:46 ` Jan Kara 2018-10-03 22:11 ` Paul Moore 2018-10-03 22:11 ` Paul Moore 2018-10-03 22:08 ` Paul Moore 2018-10-03 22:08 ` Paul Moore 2018-10-03 22:39 ` Richard Guy Briggs 2018-10-03 22:39 ` Richard Guy Briggs 2018-10-04 6:57 ` Jan Kara 2018-10-04 6:57 ` Jan Kara 2018-09-04 16:06 ` [PATCH 10/11] audit: Replace chunk attached to mark instead of replacing mark Jan Kara 2018-09-04 16:06 ` Jan Kara 2018-09-04 16:06 ` [PATCH 11/11] audit: Use 'mark' name for fsnotify_mark variables Jan Kara 2018-09-04 16:06 ` Jan Kara 2018-09-14 18:29 ` Richard Guy Briggs 2018-09-14 18:29 ` Richard Guy Briggs 2018-09-17 16:44 ` Jan Kara 2018-09-17 16:44 ` Jan Kara 2018-09-17 18:13 ` Richard Guy Briggs 2018-09-17 18:13 ` Richard Guy Briggs 2018-09-04 16:06 ` [PATCH 12/11 TESTSUITE] audit_testsuite: Add stress test for tree watches Jan Kara 2018-09-04 16:06 ` Jan Kara 2018-09-14 18:21 ` Richard Guy Briggs 2018-09-14 18:21 ` Richard Guy Briggs 2018-09-17 16:56 ` Jan Kara 2018-09-17 16:56 ` Jan Kara 2018-10-05 21:06 ` Paul Moore 2018-10-05 21:06 ` Paul Moore 2018-10-09 7:40 ` Jan Kara 2018-10-09 7:40 ` Jan Kara 2018-10-10 6:43 ` Paul Moore 2018-10-10 6:43 ` Paul Moore 2018-10-11 11:39 ` Jan Kara 2018-10-11 11:39 ` Jan Kara 2018-10-11 23:03 ` Paul Moore 2018-10-11 23:03 ` Paul Moore 2018-10-15 10:04 ` Jan Kara 2018-10-15 10:04 ` Jan Kara 2018-10-15 15:39 ` Paul Moore 2018-10-15 15:39 ` Paul Moore 2018-10-17 10:09 ` Jan Kara 2018-10-17 10:09 ` Jan Kara 2018-11-14 0:34 ` Paul Moore 2018-11-14 0:34 ` Paul Moore 2018-11-14 12:16 ` Jan Kara 2018-11-14 12:16 ` Jan Kara 2018-11-19 15:19 ` Paul Moore 2018-11-19 15:19 ` Paul Moore 2018-09-14 19:13 ` [PATCH 0/11 v3] audit: Fix various races when tagging and untagging mounts Richard Guy Briggs 2018-09-14 19:13 ` Richard Guy Briggs 2018-09-17 16:57 ` Jan Kara 2018-09-17 16:57 ` Jan Kara 2018-10-04 1:20 ` Paul Moore 2018-10-04 1:20 ` Paul Moore 2018-10-04 6:59 ` Jan Kara 2018-10-04 6:59 ` Jan Kara
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20180904160632.21210-3-jack@suse.cz \ --to=jack@suse.cz \ --cc=amir73il@gmail.com \ --cc=linux-audit@redhat.com \ --cc=linux-fsdevel@vger.kernel.org \ --cc=paul@paul-moore.com \ --cc=rgb@redhat.com \ --cc=viro@ZenIV.linux.org.uk \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.