diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h index 3db92d9a030b9051e1337661b017a719ac998293..ff73b2c17be538a48dbe267424d3e72e404f8ae4 100644 --- a/drivers/md/dm-core.h +++ b/drivers/md/dm-core.h @@ -19,6 +19,8 @@ #include "dm.h" #define DM_RESERVED_MAX_IOS 1024 +#define DM_MAX_TARGETS 1048576 +#define DM_MAX_TARGET_PARAMS 1024 struct dm_kobject_holder { struct kobject kobj; diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 5f9b9178c647e2e64632b78c70c3538ef1513f8e..2e3f24ef1d13fea367f81d12ce2de66b1b8b8db3 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1761,6 +1761,8 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern return -EFAULT; if (param_kernel->data_size < minimum_data_size) + if (unlikely(param_kernel->data_size < minimum_data_size) || + unlikely(param_kernel->data_size > DM_MAX_TARGETS * DM_MAX_TARGET_PARAMS)) return -EINVAL; secure_data = param_kernel->flags & DM_SECURE_DATA_FLAG; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 5c590895c14c37b68fbd544ac7c92402f6a43d45..31bcdcd93c7a873e4cfaad7fe488d8537a404c39 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -144,7 +144,12 @@ static int alloc_targets(struct dm_table *t, unsigned int num) int dm_table_create(struct dm_table **result, fmode_t mode, unsigned num_targets, struct mapped_device *md) { - struct dm_table *t = kzalloc(sizeof(*t), GFP_KERNEL); + struct dm_table *t; + + if (num_targets > DM_MAX_TARGETS) + return -EOVERFLOW; + + t = kzalloc(sizeof(*t), GFP_KERNEL); if (!t) return -ENOMEM; @@ -158,7 +163,7 @@ int dm_table_create(struct dm_table **result, fmode_t mode, if (!num_targets) { kfree(t); - return -ENOMEM; + return -EOVERFLOW; } if (alloc_targets(t, num_targets)) { diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 5a114cad988a65130f70c6c05c93f469af9bc1b3..f2f42ffdbfddfd1ba15f274767091388f174fdeb 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1553,8 +1553,17 @@ static struct btrfs_root *btrfs_get_root_ref(struct btrfs_fs_info *fs_info, again: root = btrfs_lookup_fs_root(fs_info, objectid); if (root) { - /* Shouldn't get preallocated anon_dev for cached roots */ - ASSERT(!anon_dev); + /* + * Some other caller may have read out the newly inserted + * subvolume already (for things like backref walk etc). Not + * that common but still possible. In that case, we just need + * to free the anon_dev. + */ + if (unlikely(anon_dev)) { + free_anon_bdev(anon_dev); + anon_dev = 0; + } + if (check_ref && btrfs_root_refs(&root->root_item) == 0) { btrfs_put_root(root); return ERR_PTR(-ENOENT); diff --git a/net/rds/af_rds.c b/net/rds/af_rds.c index b239120dd9ca691df8a561418dd91dbdaa319a77..0ec0ae1483492d93da2aa01947685e1cd737398c 100644 --- a/net/rds/af_rds.c +++ b/net/rds/af_rds.c @@ -419,7 +419,7 @@ static int rds_recv_track_latency(struct rds_sock *rs, sockptr_t optval, rs->rs_rx_traces = trace.rx_traces; for (i = 0; i < rs->rs_rx_traces; i++) { - if (trace.rx_trace_pos[i] > RDS_MSG_RX_DGRAM_TRACE_MAX) { + if (trace.rx_trace_pos[i] >= RDS_MSG_RX_DGRAM_TRACE_MAX) { rs->rs_rx_traces = 0; return -EFAULT; }