aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
authorNicolas Schichan <nschichan@freebox.fr>2014-01-15 10:58:52 -0500
committerNeilBrown <neilb@suse.de>2014-01-15 16:55:00 -0500
commitcb335f88eb35af712d1f4171642d0487f7bb2e7e (patch)
treefba070397b84f40067bf5d12aded18672eea3ebf /drivers/md/md.c
parent830778a180f268ac106f072b8aad793a79088c87 (diff)
md: check command validity early in md_ioctl().
Verify that the cmd parameter passed to md_ioctl() is valid before doing anything. This fixes mddev->hold_active being set to 0 when an invalid ioctl command is passed to md_ioctl() before the array has been configured. Clearing mddev->hold_active in that case can lead to a livelock situation when an invalid ioctl number is given to md_ioctl() by a process when the mddev is currently being opened by another process: Process 1 Process 2 --------- --------- md_alloc() mddev_find() -> returns a new mddev with hold_active == UNTIL_IOCTL add_disk() -> sends KOBJ_ADD uevent (sees KOBJ_ADD uevent for device) md_open() md_ioctl(INVALID_IOCTL) -> returns ENODEV and clears mddev->hold_active md_release() md_put() -> deletes the mddev as hold_active is 0 md_open() mddev_find() -> returns a newly allocated mddev with mddev->gendisk == NULL -> returns with ERESTARTSYS (kernel restarts the open syscall) Signed-off-by: Nicolas Schichan <nschichan@freebox.fr> Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index a20b7806de7a..b890d3fb0e02 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -6356,6 +6356,32 @@ static int md_getgeo(struct block_device *bdev, struct hd_geometry *geo)
6356 return 0; 6356 return 0;
6357} 6357}
6358 6358
6359static inline bool md_ioctl_valid(unsigned int cmd)
6360{
6361 switch (cmd) {
6362 case ADD_NEW_DISK:
6363 case BLKROSET:
6364 case GET_ARRAY_INFO:
6365 case GET_BITMAP_FILE:
6366 case GET_DISK_INFO:
6367 case HOT_ADD_DISK:
6368 case HOT_REMOVE_DISK:
6369 case PRINT_RAID_DEBUG:
6370 case RAID_AUTORUN:
6371 case RAID_VERSION:
6372 case RESTART_ARRAY_RW:
6373 case RUN_ARRAY:
6374 case SET_ARRAY_INFO:
6375 case SET_BITMAP_FILE:
6376 case SET_DISK_FAULTY:
6377 case STOP_ARRAY:
6378 case STOP_ARRAY_RO:
6379 return true;
6380 default:
6381 return false;
6382 }
6383}
6384
6359static int md_ioctl(struct block_device *bdev, fmode_t mode, 6385static int md_ioctl(struct block_device *bdev, fmode_t mode,
6360 unsigned int cmd, unsigned long arg) 6386 unsigned int cmd, unsigned long arg)
6361{ 6387{
@@ -6364,6 +6390,9 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
6364 struct mddev *mddev = NULL; 6390 struct mddev *mddev = NULL;
6365 int ro; 6391 int ro;
6366 6392
6393 if (!md_ioctl_valid(cmd))
6394 return -ENOTTY;
6395
6367 switch (cmd) { 6396 switch (cmd) {
6368 case RAID_VERSION: 6397 case RAID_VERSION:
6369 case GET_ARRAY_INFO: 6398 case GET_ARRAY_INFO: