From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
alan@lxorguk.ukuu.org.uk,
Thomas Betker <thomas.betker@rohde-schwarz.com>,
Joakim Tjernlund <Joakim.Tjernlund@transmode.se>,
Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Subject: [ 19/54] jffs2: Fix lock acquisition order bug in jffs2_write_begin
Date: Fri, 30 Nov 2012 10:55:50 -0800 [thread overview]
Message-ID: <20121130185209.823961507@linuxfoundation.org> (raw)
In-Reply-To: <20121130185207.894301294@linuxfoundation.org>
3.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Betker <thomas.betker@freenet.de>
commit 5ffd3412ae5536a4c57469cb8ea31887121dcb2e upstream.
jffs2_write_begin() first acquires the page lock, then f->sem. This
causes an AB-BA deadlock with jffs2_garbage_collect_live(), which first
acquires f->sem, then the page lock:
jffs2_garbage_collect_live
mutex_lock(&f->sem) (A)
jffs2_garbage_collect_dnode
jffs2_gc_fetch_page
read_cache_page_async
do_read_cache_page
lock_page(page) (B)
jffs2_write_begin
grab_cache_page_write_begin
find_lock_page
lock_page(page) (B)
mutex_lock(&f->sem) (A)
We fix this by restructuring jffs2_write_begin() to take f->sem before
the page lock. However, we make sure that f->sem is not held when
calling jffs2_reserve_space(), as this is not permitted by the locking
rules.
The deadlock above was observed multiple times on an SoC with a dual
ARMv7 (Cortex-A9), running the long-term 3.4.11 kernel; it occurred
when using scp to copy files from a host system to the ARM target
system. The fix was heavily tested on the same target system.
Signed-off-by: Thomas Betker <thomas.betker@rohde-schwarz.com>
Acked-by: Joakim Tjernlund <Joakim.Tjernlund@transmode.se>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/jffs2/file.c | 39 +++++++++++++++++++++------------------
1 file changed, 21 insertions(+), 18 deletions(-)
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -138,33 +138,39 @@ static int jffs2_write_begin(struct file
struct page *pg;
struct inode *inode = mapping->host;
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+ struct jffs2_raw_inode ri;
+ uint32_t alloc_len = 0;
pgoff_t index = pos >> PAGE_CACHE_SHIFT;
uint32_t pageofs = index << PAGE_CACHE_SHIFT;
int ret = 0;
+ jffs2_dbg(1, "%s()\n", __func__);
+
+ if (pageofs > inode->i_size) {
+ ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
+ ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+ if (ret)
+ return ret;
+ }
+
+ mutex_lock(&f->sem);
pg = grab_cache_page_write_begin(mapping, index, flags);
- if (!pg)
+ if (!pg) {
+ if (alloc_len)
+ jffs2_complete_reservation(c);
+ mutex_unlock(&f->sem);
return -ENOMEM;
+ }
*pagep = pg;
- jffs2_dbg(1, "%s()\n", __func__);
-
- if (pageofs > inode->i_size) {
+ if (alloc_len) {
/* Make new hole frag from old EOF to new page */
- struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
- struct jffs2_raw_inode ri;
struct jffs2_full_dnode *fn;
- uint32_t alloc_len;
jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
(unsigned int)inode->i_size, pageofs);
- ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
- ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
- if (ret)
- goto out_page;
-
- mutex_lock(&f->sem);
memset(&ri, 0, sizeof(ri));
ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -191,7 +197,6 @@ static int jffs2_write_begin(struct file
if (IS_ERR(fn)) {
ret = PTR_ERR(fn);
jffs2_complete_reservation(c);
- mutex_unlock(&f->sem);
goto out_page;
}
ret = jffs2_add_full_dnode_to_inode(c, f, fn);
@@ -206,12 +211,10 @@ static int jffs2_write_begin(struct file
jffs2_mark_node_obsolete(c, fn->raw);
jffs2_free_full_dnode(fn);
jffs2_complete_reservation(c);
- mutex_unlock(&f->sem);
goto out_page;
}
jffs2_complete_reservation(c);
inode->i_size = pageofs;
- mutex_unlock(&f->sem);
}
/*
@@ -220,18 +223,18 @@ static int jffs2_write_begin(struct file
* case of a short-copy.
*/
if (!PageUptodate(pg)) {
- mutex_lock(&f->sem);
ret = jffs2_do_readpage_nolock(inode, pg);
- mutex_unlock(&f->sem);
if (ret)
goto out_page;
}
+ mutex_unlock(&f->sem);
jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);
return ret;
out_page:
unlock_page(pg);
page_cache_release(pg);
+ mutex_unlock(&f->sem);
return ret;
}
next prev parent reply other threads:[~2012-11-30 19:15 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-11-30 18:55 [ 00/54] 3.6.9-stable review Greg Kroah-Hartman
2012-11-30 18:55 ` [ 01/54] wireless: add back sysfs directory Greg Kroah-Hartman
2012-11-30 18:55 ` [ 02/54] x86-32: Fix invalid stack address while in softirq Greg Kroah-Hartman
2012-11-30 18:55 ` [ 03/54] x86, efi: Fix processor-specific memcpy() build error Greg Kroah-Hartman
2012-11-30 18:55 ` [ 04/54] x86, microcode, AMD: Add support for family 16h processors Greg Kroah-Hartman
2012-11-30 18:55 ` [ 05/54] x86-32: Export kernel_stack_pointer() for modules Greg Kroah-Hartman
2012-11-30 18:55 ` [ 06/54] iwlwifi: dont WARN when a non empty queue is disabled Greg Kroah-Hartman
2012-11-30 18:55 ` [ 07/54] iwlwifi: fix monitor mode FCS flag Greg Kroah-Hartman
2012-11-30 18:55 ` [ 08/54] rtlwifi: rtl8192cu: Add new USB ID Greg Kroah-Hartman
2012-11-30 18:55 ` [ 09/54] mwifiex: report error to MMC core if we cannot suspend Greg Kroah-Hartman
2012-11-30 18:55 ` [ 10/54] mwifiex: fix system hang issue in cmd timeout error case Greg Kroah-Hartman
2012-11-30 18:55 ` [ 11/54] SCSI: isci: copy fis 0x34 response into proper buffer Greg Kroah-Hartman
2012-11-30 18:55 ` [ 12/54] drm/radeon: add new SI pci id Greg Kroah-Hartman
2012-11-30 18:55 ` [ 13/54] ALSA: ua101, usx2y: fix broken MIDI output Greg Kroah-Hartman
2012-11-30 18:55 ` [ 14/54] ALSA: hda - Cirrus: Correctly clear line_out_pins when moving to speaker Greg Kroah-Hartman
2012-11-30 18:55 ` [ 15/54] PARISC: fix virtual aliasing issue in get_shared_area() Greg Kroah-Hartman
2012-11-30 18:55 ` [ 16/54] PARISC: fix user-triggerable panic on parisc Greg Kroah-Hartman
2012-11-30 18:55 ` [ 17/54] mtd: slram: invalid checking of absolute end address Greg Kroah-Hartman
2012-11-30 18:55 ` [ 18/54] mtd: ofpart: Fix incorrect NULL check in parse_ofoldpart_partitions() Greg Kroah-Hartman
2012-11-30 18:55 ` Greg Kroah-Hartman [this message]
2012-11-30 18:55 ` [ 20/54] md: Reassigned the parameters if read_seqretry returned true in func md_is_badblock Greg Kroah-Hartman
2012-11-30 18:55 ` [ 21/54] md: Avoid write invalid address if read_seqretry returned true Greg Kroah-Hartman
2012-11-30 18:55 ` [ 22/54] md/raid10: decrement correct pending counter when writing to replacement Greg Kroah-Hartman
2012-11-30 18:55 ` [ 23/54] block: Dont access request after it might be freed Greg Kroah-Hartman
2012-11-30 18:55 ` [ 24/54] dm: fix deadlock with request based dm and queue request_fn recursion Greg Kroah-Hartman
2012-11-30 18:55 ` [ 25/54] futex: avoid wake_futex() for a PI futex_q Greg Kroah-Hartman
2012-11-30 18:55 ` [ 26/54] mac80211: deinitialize ibss-internals after emptiness check Greg Kroah-Hartman
2012-11-30 18:55 ` [ 27/54] radeon: add AGPMode 1 quirk for RV250 Greg Kroah-Hartman
2012-11-30 18:55 ` [ 28/54] can: peak_usb: fix hwtstamp assignment Greg Kroah-Hartman
2012-11-30 18:56 ` [ 29/54] can: bcm: initialize ifindex for timeouts without previous frame reception Greg Kroah-Hartman
2012-11-30 18:56 ` [ 30/54] jbd: Fix lock ordering bug in journal_unmap_buffer() Greg Kroah-Hartman
2012-11-30 18:56 ` [ 31/54] sparc64: not any error from do_sigaltstack() should fail rt_sigreturn() Greg Kroah-Hartman
2012-11-30 18:56 ` [ 32/54] PM / QoS: fix wrong error-checking condition Greg Kroah-Hartman
2012-11-30 18:56 ` [ 33/54] writeback: put unused inodes to LRU after writeback completion Greg Kroah-Hartman
2012-11-30 18:56 ` [ 34/54] ALSA: hda - Add new codec ALC283 ALC290 support Greg Kroah-Hartman
2012-11-30 18:56 ` [ 35/54] ALSA: hda - Fix missing beep on ASUS X43U notebook Greg Kroah-Hartman
2012-11-30 18:56 ` [ 36/54] ALSA: hda - Add support for Realtek ALC292 Greg Kroah-Hartman
2012-11-30 18:56 ` [ 37/54] bas_gigaset: fix pre_reset handling Greg Kroah-Hartman
2012-11-30 18:56 ` [ 38/54] pstore/ram: Fix printk format warning Greg Kroah-Hartman
2012-11-30 18:56 ` [ 39/54] HID: add quirk for Freescale i.MX28 ROM recovery Greg Kroah-Hartman
2012-11-30 18:56 ` [ 40/54] KVM: x86: invalid opcode oops on SET_SREGS with OSXSAVE bit set (CVE-2012-4461) Greg Kroah-Hartman
2012-11-30 18:56 ` [ 41/54] ixgbe: add support for X540-AT1 Greg Kroah-Hartman
2012-11-30 18:56 ` [ 42/54] sata_svw: check DMA start bit before reset Greg Kroah-Hartman
2012-11-30 18:56 ` [ 43/54] get_dvb_firmware: fix download site for tda10046 firmware Greg Kroah-Hartman
2012-11-30 18:56 ` [ 44/54] NFC: pn533: Fix use after free Greg Kroah-Hartman
2012-11-30 18:56 ` [ 45/54] NFC: Fix pn533 target mode memory leak Greg Kroah-Hartman
2012-11-30 18:56 ` [ 46/54] NFC: pn533: Fix mem leak in pn533_in_dep_link_up Greg Kroah-Hartman
2012-11-30 18:56 ` [ 47/54] NFC: Fix nfc_llcp_local chained list insertion Greg Kroah-Hartman
2012-11-30 18:56 ` [ 48/54] mm: vmscan: check for fatal signals iff the process was throttled Greg Kroah-Hartman
2012-11-30 18:56 ` [ 49/54] watchdog: using u64 in get_sample_period() Greg Kroah-Hartman
2012-11-30 18:56 ` [ 50/54] MPI: Fix compilation on MIPS with GCC 4.4 and newer Greg Kroah-Hartman
2012-11-30 18:56 ` [ 51/54] ext4: remove erroneous ext4_superblock_csum_set() in update_backups() Greg Kroah-Hartman
2012-11-30 18:56 ` [ 52/54] powerpc/eeh: Lock module while handling EEH event Greg Kroah-Hartman
2012-11-30 18:56 ` [ 53/54] mmc: sdhci-s3c: fix the wrong number of max bus clocks Greg Kroah-Hartman
2012-11-30 18:56 ` [ 54/54] md/raid10: close race that lose writes lost when replacement completes Greg Kroah-Hartman
2012-12-01 14:58 ` [ 00/54] 3.6.9-stable review Satoru Takeuchi
2012-12-01 16:50 ` Greg Kroah-Hartman
2012-12-02 2:11 ` Shuah Khan
2012-12-02 17:01 ` Greg Kroah-Hartman
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=20121130185209.823961507@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=Joakim.Tjernlund@transmode.se \
--cc=alan@lxorguk.ukuu.org.uk \
--cc=artem.bityutskiy@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=stable@vger.kernel.org \
--cc=thomas.betker@rohde-schwarz.com \
/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: link
Be 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.