Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1600474 > unrolled thread
| Started by | Jiri Slaby <jslaby@suse.cz> |
|---|---|
| First post | 2017-03-14 15:30 +0100 |
| Last post | 2017-03-14 15:30 +0100 |
| Articles | 2 — 1 participant |
Back to article view | Back to linux.kernel
[PATCH 3.12 00/60] 3.12.72-stable review Jiri Slaby <jslaby@suse.cz> - 2017-03-14 15:30 +0100
[PATCH 3.12 01/60] md linear: fix a race between linear_add() and linear_congested() Jiri Slaby <jslaby@suse.cz> - 2017-03-14 15:30 +0100
| From | Jiri Slaby <jslaby@suse.cz> |
|---|---|
| Date | 2017-03-14 15:30 +0100 |
| Subject | [PATCH 3.12 00/60] 3.12.72-stable review |
| Message-ID | <tkUGu-Hf-33@gated-at.bofh.it> |
This is the start of the stable review cycle for the 3.12.72 release.
There are 60 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Thu Mar 16 14:14:28 CET 2017.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
http://kernel.org/pub/linux/kernel/people/jirislaby/stable-review/patch-3.12.72-rc1.xz
and the diffstat can be found below.
thanks,
js
===============
Alexander Popov (1):
tty: n_hdlc: get rid of racy n_hdlc.tbuf
Arnaldo Carvalho de Melo (1):
perf trace: Use the syscall raw_syscalls:sys_enter timestamp
Arnd Bergmann (1):
staging: rtl: fix possible NULL pointer dereference
Chao Peng (1):
KVM: VMX: use correct vmcs_read/write for guest segment selector/base
Christian Lamparter (1):
ath9k: use correct OTP register offsets for the AR9340 and AR9550
Davidlohr Bueso (1):
ipc/shm: Fix shmat mmap nil-page protection
Dmitry Tunin (1):
Bluetooth: Add another AR3012 04ca:3018 device
Felix Fietkau (1):
ath5k: drop bogus warning on drv_set_key with unsupported cipher
Feras Daoud (1):
IB/ipoib: Fix deadlock between rmmod and set_mode
Guennadi Liakhovetski (1):
uvcvideo: Fix a wrong macro
Hannes Reinecke (1):
sd: get disk reference in sd_check_events()
Ian Abbott (1):
serial: 8250_pci: Add MKS Tenta SCOM-0800 and SCOM-0801 cards
J. Bruce Fields (1):
NFSv4: fix getacl head length estimation
James Cowgill (1):
MIPS: OCTEON: Fix copy_from_user fault handling for large buffers
James Smart (1):
scsi: lpfc: Correct WQ creation for pagesize
Jan Kara (1):
ext4: trim allocation requests to group size
Jaroslav Kysela (1):
ALSA: hda - fix Lewisburg audio issue
Jason Gunthorpe (1):
RDMA/core: Fix incorrect structure packing for booleans
Jiri Slaby (1):
TTY: n_hdlc, fix lockdep false positive
Julian Wiedmann (1):
s390/qdio: clear DSCI prior to scanning multiple input queues
K. Y. Srinivasan (1):
drivers: hv: Turn off write permission on the hypercall page
Long Li (3):
scsi: storvsc: use tagged SRB requests if supported by the device
scsi: storvsc: properly handle SRB_ERROR when sense message is present
scsi: storvsc: properly set residual data length on errors
Marc Kleine-Budde (1):
can: usb_8dev: Fix memory leak of priv->cmd_msg_buffer
Marcelo Ricardo Leitner (1):
sctp: deny peeloff operation on asocs with threads sleeping on it
Martin Schwidefsky (1):
s390: TASK_SIZE for kernel threads
Mathias Svensson (1):
samples/seccomp: fix 64-bit comparison macros
Matt Chen (1):
mac80211: flush delayed work when entering suspend
Max Filippov (1):
xtensa: move parse_tag_fdt out of #ifdef CONFIG_BLK_DEV_INITRD
Michel Dänzer (1):
drm/ttm: Make sure BOs being swapped out are cacheable
Miklos Szeredi (1):
fuse: add missing FR_FORCE
OGAWA Hirofumi (1):
fat: fix using uninitialized fields of fat_inode/fsinfo_inode
Paul Burton (6):
MIPS: Clear ISA bit correctly in get_frame_info()
MIPS: Prevent unaligned accesses during stack unwinding
MIPS: Fix get_frame_info() handling of microMIPS function size
MIPS: Fix is_jump_ins() handling of 16b microMIPS instructions
MIPS: Calculate microMIPS ra properly when unwinding the stack
MIPS: Handle microMIPS jumps in the same way as MIPS32/MIPS64 jumps
Rafał Miłecki (1):
bcma: use (get|put)_device when probing/removing device driver
Raghava Aditya Renukunta (1):
scsi: aacraid: Reorder Adapter status check
Ralf Baechle (3):
MIPS: Fix special case in 64 bit IP checksumming.
MIPS: IP22: Reformat inline assembler code to modern standards.
MIPS: IP22: Fix build error due to binutils 2.25 uselessnes.
Ravi Bangoria (1):
powerpc/xmon: Fix data-breakpoint
Shmulik Ladkani (1):
net/sched: em_meta: Fix 'meta vlan' to correctly recognize zero VID
frames
Steve Wise (1):
rdma_cm: fail iwarp accepts w/o connection params
Steven Rostedt (VMware) (1):
ktest: Fix child exit code processing
Takashi Iwai (2):
ALSA: timer: Reject user params with too small ticks
ALSA: seq: Fix link corruption by event error handling
Theodore Ts'o (3):
jbd2: don't leak modified metadata buffers on an aborted journal
ext4: preserve the needs_recovery flag when the journal is aborted
ext4: return EROFS if device is r/o and journal replay is needed
Trond Myklebust (2):
NFSv4: Fix memory and state leak in _nfs4_open_and_get_state
nlm: Ensure callback code also checks that the files match
Vinayak Menon (1):
mm: vmpressure: fix sending wrong events on underflow
Vitaly Kuznetsov (1):
hv: allocate synic pages for all present CPUs
Weston Andros Adamson (1):
NFSv4: fix getacl ERANGE for some ACL buffer sizes
Y.C. Chen (1):
drm/ast: Fix test for VGA enabled
colyli@suse.de (1):
md linear: fix a race between linear_add() and linear_congested()
arch/mips/cavium-octeon/octeon-memcpy.S | 20 ++--
arch/mips/include/asm/checksum.h | 2 +
arch/mips/kernel/process.c | 153 ++++++++++++++++---------
arch/mips/mm/sc-ip22.c | 54 +++++----
arch/powerpc/kernel/hw_breakpoint.c | 4 +-
arch/s390/include/asm/processor.h | 3 +-
arch/x86/kvm/vmx.c | 2 +-
arch/xtensa/kernel/setup.c | 4 +-
drivers/bcma/main.c | 4 +
drivers/bluetooth/ath3k.c | 2 +
drivers/bluetooth/btusb.c | 1 +
drivers/gpu/drm/ast/ast_post.c | 8 +-
drivers/gpu/drm/ttm/ttm_bo.c | 4 +-
drivers/hv/hv.c | 6 +-
drivers/infiniband/core/cma.c | 3 +
drivers/infiniband/ulp/ipoib/ipoib_cm.c | 12 +-
drivers/infiniband/ulp/ipoib/ipoib_main.c | 6 +-
drivers/md/linear.c | 29 ++++-
drivers/md/linear.h | 1 +
drivers/media/usb/uvc/uvc_queue.c | 2 +-
drivers/net/can/usb/usb_8dev.c | 9 +-
drivers/net/wireless/ath/ath5k/mac80211-ops.c | 3 +-
drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 4 +-
drivers/s390/cio/qdio_thinint.c | 8 +-
drivers/scsi/aacraid/src.c | 21 +++-
drivers/scsi/lpfc/lpfc_hw4.h | 2 +
drivers/scsi/lpfc/lpfc_sli.c | 9 +-
drivers/scsi/sd.c | 9 +-
drivers/scsi/storvsc_drv.c | 32 +++++-
drivers/staging/rtl8188eu/core/rtw_recv.c | 3 +
drivers/staging/rtl8712/rtl871x_recv.c | 7 +-
drivers/tty/n_hdlc.c | 143 +++++++++++------------
drivers/tty/serial/8250/8250_pci.c | 13 +++
fs/ext4/mballoc.c | 7 ++
fs/ext4/super.c | 9 +-
fs/fat/inode.c | 13 ++-
fs/fuse/file.c | 1 +
fs/jbd2/transaction.c | 4 +-
fs/nfs/nfs4proc.c | 10 +-
fs/nfs/nfs4xdr.c | 2 +-
include/linux/lockd/lockd.h | 3 +-
include/rdma/ib_sa.h | 6 +-
ipc/shm.c | 13 ++-
mm/vmpressure.c | 10 +-
net/mac80211/pm.c | 1 +
net/sched/em_meta.c | 9 +-
net/sctp/socket.c | 8 +-
samples/seccomp/bpf-helper.h | 125 +++++++++++---------
sound/core/seq/seq_fifo.c | 3 +
sound/core/timer.c | 18 ++-
sound/pci/hda/hda_intel.c | 4 +-
tools/perf/builtin-trace.c | 4 +-
tools/testing/ktest/ktest.pl | 2 +-
53 files changed, 535 insertions(+), 300 deletions(-)
--
2.12.0
[toc] | [next] | [standalone]
| From | Jiri Slaby <jslaby@suse.cz> |
|---|---|
| Date | 2017-03-14 15:30 +0100 |
| Subject | [PATCH 3.12 01/60] md linear: fix a race between linear_add() and linear_congested() |
| Message-ID | <tkUwN-Bf-3@gated-at.bofh.it> |
| In reply to | #1600474 |
From: "colyli@suse.de" <colyli@suse.de>
3.12-stable review patch. If anyone has any objections, please let me know.
===============
commit 03a9e24ef2aaa5f1f9837356aed79c860521407a upstream.
Recently I receive a bug report that on Linux v3.0 based kerenl, hot add
disk to a md linear device causes kernel crash at linear_congested(). From
the crash image analysis, I find in linear_congested(), mddev->raid_disks
contains value N, but conf->disks[] only has N-1 pointers available. Then
a NULL pointer deference crashes the kernel.
There is a race between linear_add() and linear_congested(), RCU stuffs
used in these two functions cannot avoid the race. Since Linuv v4.0
RCU code is replaced by introducing mddev_suspend(). After checking the
upstream code, it seems linear_congested() is not called in
generic_make_request() code patch, so mddev_suspend() cannot provent it
from being called. The possible race still exists.
Here I explain how the race still exists in current code. For a machine
has many CPUs, on one CPU, linear_add() is called to add a hard disk to a
md linear device; at the same time on other CPU, linear_congested() is
called to detect whether this md linear device is congested before issuing
an I/O request onto it.
Now I use a possible code execution time sequence to demo how the possible
race happens,
seq linear_add() linear_congested()
0 conf=mddev->private
1 oldconf=mddev->private
2 mddev->raid_disks++
3 for (i=0; i<mddev->raid_disks;i++)
4 bdev_get_queue(conf->disks[i].rdev->bdev)
5 mddev->private=newconf
In linear_add() mddev->raid_disks is increased in time seq 2, and on
another CPU in linear_congested() the for-loop iterates conf->disks[i] by
the increased mddev->raid_disks in time seq 3,4. But conf with one more
element (which is a pointer to struct dev_info type) to conf->disks[] is
not updated yet, accessing its structure member in time seq 4 will cause a
NULL pointer deference fault.
To fix this race, there are 2 parts of modification in the patch,
1) Add 'int raid_disks' in struct linear_conf, as a copy of
mddev->raid_disks. It is initialized in linear_conf(), always being
consistent with pointers number of 'struct dev_info disks[]'. When
iterating conf->disks[] in linear_congested(), use conf->raid_disks to
replace mddev->raid_disks in the for-loop, then NULL pointer deference
will not happen again.
2) RCU stuffs are back again, and use kfree_rcu() in linear_add() to
free oldconf memory. Because oldconf may be referenced as mddev->private
in linear_congested(), kfree_rcu() makes sure that its memory will not
be released until no one uses it any more.
Also some code comments are added in this patch, to make this modification
to be easier understandable.
This patch can be applied for kernels since v4.0 after commit:
3be260cc18f8 ("md/linear: remove rcu protections in favour of
suspend/resume"). But this bug is reported on Linux v3.0 based kernel, for
people who maintain kernels before Linux v4.0, they need to do some back
back port to this patch.
Changelog:
- V3: add 'int raid_disks' in struct linear_conf, and use kfree_rcu() to
replace rcu_call() in linear_add().
- v2: add RCU stuffs by suggestion from Shaohua and Neil.
- v1: initial effort.
Signed-off-by: Coly Li <colyli@suse.de>
Cc: Shaohua Li <shli@fb.com>
Cc: Neil Brown <neilb@suse.com>
Signed-off-by: Shaohua Li <shli@fb.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
drivers/md/linear.c | 29 ++++++++++++++++++++++++++++-
drivers/md/linear.h | 1 +
2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index f03fabd2b37b..f169afac0266 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -97,6 +97,12 @@ static int linear_mergeable_bvec(struct request_queue *q,
return maxsectors << 9;
}
+/*
+ * In linear_congested() conf->raid_disks is used as a copy of
+ * mddev->raid_disks to iterate conf->disks[], because conf->raid_disks
+ * and conf->disks[] are created in linear_conf(), they are always
+ * consitent with each other, but mddev->raid_disks does not.
+ */
static int linear_congested(void *data, int bits)
{
struct mddev *mddev = data;
@@ -109,7 +115,7 @@ static int linear_congested(void *data, int bits)
rcu_read_lock();
conf = rcu_dereference(mddev->private);
- for (i = 0; i < mddev->raid_disks && !ret ; i++) {
+ for (i = 0; i < conf->raid_disks && !ret ; i++) {
struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev);
ret |= bdi_congested(&q->backing_dev_info, bits);
}
@@ -196,6 +202,19 @@ static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks)
conf->disks[i-1].end_sector +
conf->disks[i].rdev->sectors;
+ /*
+ * conf->raid_disks is copy of mddev->raid_disks. The reason to
+ * keep a copy of mddev->raid_disks in struct linear_conf is,
+ * mddev->raid_disks may not be consistent with pointers number of
+ * conf->disks[] when it is updated in linear_add() and used to
+ * iterate old conf->disks[] earray in linear_congested().
+ * Here conf->raid_disks is always consitent with number of
+ * pointers in conf->disks[] array, and mddev->private is updated
+ * with rcu_assign_pointer() in linear_addr(), such race can be
+ * avoided.
+ */
+ conf->raid_disks = raid_disks;
+
return conf;
out:
@@ -252,10 +271,18 @@ static int linear_add(struct mddev *mddev, struct md_rdev *rdev)
if (!newconf)
return -ENOMEM;
+ /* newconf->raid_disks already keeps a copy of * the increased
+ * value of mddev->raid_disks, WARN_ONCE() is just used to make
+ * sure of this. It is possible that oldconf is still referenced
+ * in linear_congested(), therefore kfree_rcu() is used to free
+ * oldconf until no one uses it anymore.
+ */
oldconf = rcu_dereference_protected(mddev->private,
lockdep_is_held(
&mddev->reconfig_mutex));
mddev->raid_disks++;
+ WARN_ONCE(mddev->raid_disks != newconf->raid_disks,
+ "copied raid_disks doesn't match mddev->raid_disks");
rcu_assign_pointer(mddev->private, newconf);
md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
set_capacity(mddev->gendisk, mddev->array_sectors);
diff --git a/drivers/md/linear.h b/drivers/md/linear.h
index b685ddd7d7f7..8d392e6098b3 100644
--- a/drivers/md/linear.h
+++ b/drivers/md/linear.h
@@ -10,6 +10,7 @@ struct linear_conf
{
struct rcu_head rcu;
sector_t array_sectors;
+ int raid_disks; /* a copy of mddev->raid_disks */
struct dev_info disks[0];
};
#endif
--
2.12.0
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web