From 504a127fea38c9cbf9f14fb04544b28862a21daf Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 14 Jan 2013 10:54:00 -0800 Subject: [PATCH] 3.4-stable patches added patches: dm-ioctl-prevent-unsafe-change-to-dm_ioctl-data_size.patch dm-persistent-data-rename-node-to-btree_node.patch rdma-nes-fix-for-crash-when-registering-zero-length-mr-for-cq.patch rdma-nes-fix-for-terminate-timer-crash.patch ring-buffer-fix-race-between-integrity-check-and-readers.patch --- ...-unsafe-change-to-dm_ioctl-data_size.patch | 62 +++ ...stent-data-rename-node-to-btree_node.patch | 403 ++++++++++++++++++ ...en-registering-zero-length-mr-for-cq.patch | 32 ++ ...ma-nes-fix-for-terminate-timer-crash.patch | 84 ++++ ...-between-integrity-check-and-readers.patch | 65 +++ queue-3.4/series | 5 + 6 files changed, 651 insertions(+) create mode 100644 queue-3.4/dm-ioctl-prevent-unsafe-change-to-dm_ioctl-data_size.patch create mode 100644 queue-3.4/dm-persistent-data-rename-node-to-btree_node.patch create mode 100644 queue-3.4/rdma-nes-fix-for-crash-when-registering-zero-length-mr-for-cq.patch create mode 100644 queue-3.4/rdma-nes-fix-for-terminate-timer-crash.patch create mode 100644 queue-3.4/ring-buffer-fix-race-between-integrity-check-and-readers.patch diff --git a/queue-3.4/dm-ioctl-prevent-unsafe-change-to-dm_ioctl-data_size.patch b/queue-3.4/dm-ioctl-prevent-unsafe-change-to-dm_ioctl-data_size.patch new file mode 100644 index 00000000000..098a28f9f61 --- /dev/null +++ b/queue-3.4/dm-ioctl-prevent-unsafe-change-to-dm_ioctl-data_size.patch @@ -0,0 +1,62 @@ +From e910d7ebecd1aac43125944a8641b6cb1a0dfabe Mon Sep 17 00:00:00 2001 +From: Alasdair G Kergon +Date: Fri, 21 Dec 2012 20:23:30 +0000 +Subject: dm ioctl: prevent unsafe change to dm_ioctl data_size + +From: Alasdair G Kergon + +commit e910d7ebecd1aac43125944a8641b6cb1a0dfabe upstream. + +Abort dm ioctl processing if userspace changes the data_size parameter +after we validated it but before we finished copying the data buffer +from userspace. + +The dm ioctl parameters are processed in the following sequence: + 1. ctl_ioctl() calls copy_params(); + 2. copy_params() makes a first copy of the fixed-sized portion of the + userspace parameters into the local variable "tmp"; + 3. copy_params() then validates tmp.data_size and allocates a new + structure big enough to hold the complete data and copies the whole + userspace buffer there; + 4. ctl_ioctl() reads userspace data the second time and copies the whole + buffer into the pointer "param"; + 5. ctl_ioctl() reads param->data_size without any validation and stores it + in the variable "input_param_size"; + 6. "input_param_size" is further used as the authoritative size of the + kernel buffer. + +The problem is that userspace code could change the contents of user +memory between steps 2 and 4. In particular, the data_size parameter +can be changed to an invalid value after the kernel has validated it. +This lets userspace force the kernel to access invalid kernel memory. + +The fix is to ensure that the size has not changed at step 4. + +This patch shouldn't have a security impact because CAP_SYS_ADMIN is +required to run this code, but it should be fixed anyway. + +Reported-by: Mikulas Patocka +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/dm-ioctl.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/md/dm-ioctl.c ++++ b/drivers/md/dm-ioctl.c +@@ -1563,6 +1563,14 @@ static int copy_params(struct dm_ioctl _ + if (copy_from_user(dmi, user, tmp.data_size)) + goto bad; + ++ /* ++ * Abort if something changed the ioctl data while it was being copied. ++ */ ++ if (dmi->data_size != tmp.data_size) { ++ DMERR("rejecting ioctl: data size modified while processing parameters"); ++ goto bad; ++ } ++ + /* Wipe the user buffer so we do not return it to userspace */ + if (secure_data && clear_user(user, tmp.data_size)) + goto bad; diff --git a/queue-3.4/dm-persistent-data-rename-node-to-btree_node.patch b/queue-3.4/dm-persistent-data-rename-node-to-btree_node.patch new file mode 100644 index 00000000000..427d577c4b8 --- /dev/null +++ b/queue-3.4/dm-persistent-data-rename-node-to-btree_node.patch @@ -0,0 +1,403 @@ +From 550929faf89e2e2cdb3e9945ea87d383989274cf Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Fri, 21 Dec 2012 20:23:30 +0000 +Subject: dm persistent data: rename node to btree_node + +From: Mikulas Patocka + +commit 550929faf89e2e2cdb3e9945ea87d383989274cf upstream. + +This patch fixes a compilation failure on sparc32 by renaming struct node. + +struct node is already defined in include/linux/node.h. On sparc32, it +happens to be included through other dependencies and persistent-data +doesn't compile because of conflicting declarations. + +Signed-off-by: Mikulas Patocka +Signed-off-by: Alasdair G Kergon +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/md/persistent-data/dm-btree-internal.h | 16 ++++---- + drivers/md/persistent-data/dm-btree-remove.c | 50 ++++++++++++------------- + drivers/md/persistent-data/dm-btree-spine.c | 6 +-- + drivers/md/persistent-data/dm-btree.c | 22 +++++------ + 4 files changed, 47 insertions(+), 47 deletions(-) + +--- a/drivers/md/persistent-data/dm-btree-internal.h ++++ b/drivers/md/persistent-data/dm-btree-internal.h +@@ -36,13 +36,13 @@ struct node_header { + __le32 padding; + } __packed; + +-struct node { ++struct btree_node { + struct node_header header; + __le64 keys[0]; + } __packed; + + +-void inc_children(struct dm_transaction_manager *tm, struct node *n, ++void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, + struct dm_btree_value_type *vt); + + int new_block(struct dm_btree_info *info, struct dm_block **result); +@@ -64,7 +64,7 @@ struct ro_spine { + void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info); + int exit_ro_spine(struct ro_spine *s); + int ro_step(struct ro_spine *s, dm_block_t new_child); +-struct node *ro_node(struct ro_spine *s); ++struct btree_node *ro_node(struct ro_spine *s); + + struct shadow_spine { + struct dm_btree_info *info; +@@ -98,17 +98,17 @@ int shadow_root(struct shadow_spine *s); + /* + * Some inlines. + */ +-static inline __le64 *key_ptr(struct node *n, uint32_t index) ++static inline __le64 *key_ptr(struct btree_node *n, uint32_t index) + { + return n->keys + index; + } + +-static inline void *value_base(struct node *n) ++static inline void *value_base(struct btree_node *n) + { + return &n->keys[le32_to_cpu(n->header.max_entries)]; + } + +-static inline void *value_ptr(struct node *n, uint32_t index) ++static inline void *value_ptr(struct btree_node *n, uint32_t index) + { + uint32_t value_size = le32_to_cpu(n->header.value_size); + return value_base(n) + (value_size * index); +@@ -117,7 +117,7 @@ static inline void *value_ptr(struct nod + /* + * Assumes the values are suitably-aligned and converts to core format. + */ +-static inline uint64_t value64(struct node *n, uint32_t index) ++static inline uint64_t value64(struct btree_node *n, uint32_t index) + { + __le64 *values_le = value_base(n); + +@@ -127,7 +127,7 @@ static inline uint64_t value64(struct no + /* + * Searching for a key within a single node. + */ +-int lower_bound(struct node *n, uint64_t key); ++int lower_bound(struct btree_node *n, uint64_t key); + + extern struct dm_block_validator btree_node_validator; + +--- a/drivers/md/persistent-data/dm-btree-remove.c ++++ b/drivers/md/persistent-data/dm-btree-remove.c +@@ -53,7 +53,7 @@ + /* + * Some little utilities for moving node data around. + */ +-static void node_shift(struct node *n, int shift) ++static void node_shift(struct btree_node *n, int shift) + { + uint32_t nr_entries = le32_to_cpu(n->header.nr_entries); + uint32_t value_size = le32_to_cpu(n->header.value_size); +@@ -79,7 +79,7 @@ static void node_shift(struct node *n, i + } + } + +-static void node_copy(struct node *left, struct node *right, int shift) ++static void node_copy(struct btree_node *left, struct btree_node *right, int shift) + { + uint32_t nr_left = le32_to_cpu(left->header.nr_entries); + uint32_t value_size = le32_to_cpu(left->header.value_size); +@@ -108,7 +108,7 @@ static void node_copy(struct node *left, + /* + * Delete a specific entry from a leaf node. + */ +-static void delete_at(struct node *n, unsigned index) ++static void delete_at(struct btree_node *n, unsigned index) + { + unsigned nr_entries = le32_to_cpu(n->header.nr_entries); + unsigned nr_to_copy = nr_entries - (index + 1); +@@ -128,7 +128,7 @@ static void delete_at(struct node *n, un + n->header.nr_entries = cpu_to_le32(nr_entries - 1); + } + +-static unsigned merge_threshold(struct node *n) ++static unsigned merge_threshold(struct btree_node *n) + { + return le32_to_cpu(n->header.max_entries) / 3; + } +@@ -136,7 +136,7 @@ static unsigned merge_threshold(struct n + struct child { + unsigned index; + struct dm_block *block; +- struct node *n; ++ struct btree_node *n; + }; + + static struct dm_btree_value_type le64_type = { +@@ -147,7 +147,7 @@ static struct dm_btree_value_type le64_t + .equal = NULL + }; + +-static int init_child(struct dm_btree_info *info, struct node *parent, ++static int init_child(struct dm_btree_info *info, struct btree_node *parent, + unsigned index, struct child *result) + { + int r, inc; +@@ -177,7 +177,7 @@ static int exit_child(struct dm_btree_in + return dm_tm_unlock(info->tm, c->block); + } + +-static void shift(struct node *left, struct node *right, int count) ++static void shift(struct btree_node *left, struct btree_node *right, int count) + { + uint32_t nr_left = le32_to_cpu(left->header.nr_entries); + uint32_t nr_right = le32_to_cpu(right->header.nr_entries); +@@ -203,11 +203,11 @@ static void shift(struct node *left, str + right->header.nr_entries = cpu_to_le32(nr_right + count); + } + +-static void __rebalance2(struct dm_btree_info *info, struct node *parent, ++static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent, + struct child *l, struct child *r) + { +- struct node *left = l->n; +- struct node *right = r->n; ++ struct btree_node *left = l->n; ++ struct btree_node *right = r->n; + uint32_t nr_left = le32_to_cpu(left->header.nr_entries); + uint32_t nr_right = le32_to_cpu(right->header.nr_entries); + unsigned threshold = 2 * merge_threshold(left) + 1; +@@ -239,7 +239,7 @@ static int rebalance2(struct shadow_spin + unsigned left_index) + { + int r; +- struct node *parent; ++ struct btree_node *parent; + struct child left, right; + + parent = dm_block_data(shadow_current(s)); +@@ -270,9 +270,9 @@ static int rebalance2(struct shadow_spin + * in right, then rebalance2. This wastes some cpu, but I want something + * simple atm. + */ +-static void delete_center_node(struct dm_btree_info *info, struct node *parent, ++static void delete_center_node(struct dm_btree_info *info, struct btree_node *parent, + struct child *l, struct child *c, struct child *r, +- struct node *left, struct node *center, struct node *right, ++ struct btree_node *left, struct btree_node *center, struct btree_node *right, + uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) + { + uint32_t max_entries = le32_to_cpu(left->header.max_entries); +@@ -301,9 +301,9 @@ static void delete_center_node(struct dm + /* + * Redistributes entries among 3 sibling nodes. + */ +-static void redistribute3(struct dm_btree_info *info, struct node *parent, ++static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, + struct child *l, struct child *c, struct child *r, +- struct node *left, struct node *center, struct node *right, ++ struct btree_node *left, struct btree_node *center, struct btree_node *right, + uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) + { + int s; +@@ -343,12 +343,12 @@ static void redistribute3(struct dm_btre + *key_ptr(parent, r->index) = right->keys[0]; + } + +-static void __rebalance3(struct dm_btree_info *info, struct node *parent, ++static void __rebalance3(struct dm_btree_info *info, struct btree_node *parent, + struct child *l, struct child *c, struct child *r) + { +- struct node *left = l->n; +- struct node *center = c->n; +- struct node *right = r->n; ++ struct btree_node *left = l->n; ++ struct btree_node *center = c->n; ++ struct btree_node *right = r->n; + + uint32_t nr_left = le32_to_cpu(left->header.nr_entries); + uint32_t nr_center = le32_to_cpu(center->header.nr_entries); +@@ -371,7 +371,7 @@ static int rebalance3(struct shadow_spin + unsigned left_index) + { + int r; +- struct node *parent = dm_block_data(shadow_current(s)); ++ struct btree_node *parent = dm_block_data(shadow_current(s)); + struct child left, center, right; + + /* +@@ -421,7 +421,7 @@ static int get_nr_entries(struct dm_tran + { + int r; + struct dm_block *block; +- struct node *n; ++ struct btree_node *n; + + r = dm_tm_read_lock(tm, b, &btree_node_validator, &block); + if (r) +@@ -438,7 +438,7 @@ static int rebalance_children(struct sha + { + int i, r, has_left_sibling, has_right_sibling; + uint32_t child_entries; +- struct node *n; ++ struct btree_node *n; + + n = dm_block_data(shadow_current(s)); + +@@ -483,7 +483,7 @@ static int rebalance_children(struct sha + return r; + } + +-static int do_leaf(struct node *n, uint64_t key, unsigned *index) ++static int do_leaf(struct btree_node *n, uint64_t key, unsigned *index) + { + int i = lower_bound(n, key); + +@@ -506,7 +506,7 @@ static int remove_raw(struct shadow_spin + uint64_t key, unsigned *index) + { + int i = *index, r; +- struct node *n; ++ struct btree_node *n; + + for (;;) { + r = shadow_step(s, root, vt); +@@ -556,7 +556,7 @@ int dm_btree_remove(struct dm_btree_info + unsigned level, last_level = info->levels - 1; + int index = 0, r = 0; + struct shadow_spine spine; +- struct node *n; ++ struct btree_node *n; + + init_shadow_spine(&spine, info); + for (level = 0; level < info->levels; level++) { +--- a/drivers/md/persistent-data/dm-btree-spine.c ++++ b/drivers/md/persistent-data/dm-btree-spine.c +@@ -23,7 +23,7 @@ static void node_prepare_for_write(struc + struct dm_block *b, + size_t block_size) + { +- struct node *n = dm_block_data(b); ++ struct btree_node *n = dm_block_data(b); + struct node_header *h = &n->header; + + h->blocknr = cpu_to_le64(dm_block_location(b)); +@@ -38,7 +38,7 @@ static int node_check(struct dm_block_va + struct dm_block *b, + size_t block_size) + { +- struct node *n = dm_block_data(b); ++ struct btree_node *n = dm_block_data(b); + struct node_header *h = &n->header; + size_t value_size; + __le32 csum_disk; +@@ -164,7 +164,7 @@ int ro_step(struct ro_spine *s, dm_block + return r; + } + +-struct node *ro_node(struct ro_spine *s) ++struct btree_node *ro_node(struct ro_spine *s) + { + struct dm_block *block; + +--- a/drivers/md/persistent-data/dm-btree.c ++++ b/drivers/md/persistent-data/dm-btree.c +@@ -38,7 +38,7 @@ static void array_insert(void *base, siz + /*----------------------------------------------------------------*/ + + /* makes the assumption that no two keys are the same. */ +-static int bsearch(struct node *n, uint64_t key, int want_hi) ++static int bsearch(struct btree_node *n, uint64_t key, int want_hi) + { + int lo = -1, hi = le32_to_cpu(n->header.nr_entries); + +@@ -58,12 +58,12 @@ static int bsearch(struct node *n, uint6 + return want_hi ? hi : lo; + } + +-int lower_bound(struct node *n, uint64_t key) ++int lower_bound(struct btree_node *n, uint64_t key) + { + return bsearch(n, key, 0); + } + +-void inc_children(struct dm_transaction_manager *tm, struct node *n, ++void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, + struct dm_btree_value_type *vt) + { + unsigned i; +@@ -77,7 +77,7 @@ void inc_children(struct dm_transaction_ + vt->inc(vt->context, value_ptr(n, i)); + } + +-static int insert_at(size_t value_size, struct node *node, unsigned index, ++static int insert_at(size_t value_size, struct btree_node *node, unsigned index, + uint64_t key, void *value) + __dm_written_to_disk(value) + { +@@ -122,7 +122,7 @@ int dm_btree_empty(struct dm_btree_info + { + int r; + struct dm_block *b; +- struct node *n; ++ struct btree_node *n; + size_t block_size; + uint32_t max_entries; + +@@ -154,7 +154,7 @@ EXPORT_SYMBOL_GPL(dm_btree_empty); + #define MAX_SPINE_DEPTH 64 + struct frame { + struct dm_block *b; +- struct node *n; ++ struct btree_node *n; + unsigned level; + unsigned nr_children; + unsigned current_child; +@@ -295,7 +295,7 @@ EXPORT_SYMBOL_GPL(dm_btree_del); + /*----------------------------------------------------------------*/ + + static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key, +- int (*search_fn)(struct node *, uint64_t), ++ int (*search_fn)(struct btree_node *, uint64_t), + uint64_t *result_key, void *v, size_t value_size) + { + int i, r; +@@ -406,7 +406,7 @@ static int btree_split_sibling(struct sh + size_t size; + unsigned nr_left, nr_right; + struct dm_block *left, *right, *parent; +- struct node *ln, *rn, *pn; ++ struct btree_node *ln, *rn, *pn; + __le64 location; + + left = shadow_current(s); +@@ -491,7 +491,7 @@ static int btree_split_beneath(struct sh + size_t size; + unsigned nr_left, nr_right; + struct dm_block *left, *right, *new_parent; +- struct node *pn, *ln, *rn; ++ struct btree_node *pn, *ln, *rn; + __le64 val; + + new_parent = shadow_current(s); +@@ -576,7 +576,7 @@ static int btree_insert_raw(struct shado + uint64_t key, unsigned *index) + { + int r, i = *index, top = 1; +- struct node *node; ++ struct btree_node *node; + + for (;;) { + r = shadow_step(s, root, vt); +@@ -643,7 +643,7 @@ static int insert(struct dm_btree_info * + unsigned level, index = -1, last_level = info->levels - 1; + dm_block_t block = root; + struct shadow_spine spine; +- struct node *n; ++ struct btree_node *n; + struct dm_btree_value_type le64_type; + + le64_type.context = NULL; diff --git a/queue-3.4/rdma-nes-fix-for-crash-when-registering-zero-length-mr-for-cq.patch b/queue-3.4/rdma-nes-fix-for-crash-when-registering-zero-length-mr-for-cq.patch new file mode 100644 index 00000000000..a050d6d465a --- /dev/null +++ b/queue-3.4/rdma-nes-fix-for-crash-when-registering-zero-length-mr-for-cq.patch @@ -0,0 +1,32 @@ +From 7d9c199a55200c9b9fcad08e150470d02fb385be Mon Sep 17 00:00:00 2001 +From: Tatyana Nikolova +Date: Thu, 6 Dec 2012 20:05:02 +0000 +Subject: RDMA/nes: Fix for crash when registering zero length MR for CQ + +From: Tatyana Nikolova + +commit 7d9c199a55200c9b9fcad08e150470d02fb385be upstream. + +Signed-off-by: Tatyana Nikolova +Signed-off-by: Roland Dreier +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/nes/nes_verbs.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/infiniband/hw/nes/nes_verbs.c ++++ b/drivers/infiniband/hw/nes/nes_verbs.c +@@ -2559,6 +2559,11 @@ static struct ib_mr *nes_reg_user_mr(str + return ibmr; + case IWNES_MEMREG_TYPE_QP: + case IWNES_MEMREG_TYPE_CQ: ++ if (!region->length) { ++ nes_debug(NES_DBG_MR, "Unable to register zero length region for CQ\n"); ++ ib_umem_release(region); ++ return ERR_PTR(-EINVAL); ++ } + nespbl = kzalloc(sizeof(*nespbl), GFP_KERNEL); + if (!nespbl) { + nes_debug(NES_DBG_MR, "Unable to allocate PBL\n"); diff --git a/queue-3.4/rdma-nes-fix-for-terminate-timer-crash.patch b/queue-3.4/rdma-nes-fix-for-terminate-timer-crash.patch new file mode 100644 index 00000000000..351af10b37e --- /dev/null +++ b/queue-3.4/rdma-nes-fix-for-terminate-timer-crash.patch @@ -0,0 +1,84 @@ +From 7bfcfa51c35cdd2d37e0d70fc11790642dd11fb3 Mon Sep 17 00:00:00 2001 +From: Tatyana Nikolova +Date: Thu, 6 Dec 2012 19:58:27 +0000 +Subject: RDMA/nes: Fix for terminate timer crash + +From: Tatyana Nikolova + +commit 7bfcfa51c35cdd2d37e0d70fc11790642dd11fb3 upstream. + +The terminate timer needs to be initialized just once. + +Signed-off-by: Tatyana Nikolova +Signed-off-by: Roland Dreier +Signed-off-by: CAI Qian +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/infiniband/hw/nes/nes.h | 1 + + drivers/infiniband/hw/nes/nes_hw.c | 9 ++------- + drivers/infiniband/hw/nes/nes_verbs.c | 4 +++- + 3 files changed, 6 insertions(+), 8 deletions(-) + +--- a/drivers/infiniband/hw/nes/nes.h ++++ b/drivers/infiniband/hw/nes/nes.h +@@ -524,6 +524,7 @@ void nes_iwarp_ce_handler(struct nes_dev + int nes_destroy_cqp(struct nes_device *); + int nes_nic_cm_xmit(struct sk_buff *, struct net_device *); + void nes_recheck_link_status(struct work_struct *work); ++void nes_terminate_timeout(unsigned long context); + + /* nes_nic.c */ + struct net_device *nes_netdev_init(struct nes_device *, void __iomem *); +--- a/drivers/infiniband/hw/nes/nes_hw.c ++++ b/drivers/infiniband/hw/nes/nes_hw.c +@@ -75,7 +75,6 @@ static void nes_process_iwarp_aeqe(struc + static void process_critical_error(struct nes_device *nesdev); + static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number); + static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode); +-static void nes_terminate_timeout(unsigned long context); + static void nes_terminate_start_timer(struct nes_qp *nesqp); + + #ifdef CONFIG_INFINIBAND_NES_DEBUG +@@ -3522,7 +3521,7 @@ static void nes_terminate_received(struc + } + + /* Timeout routine in case terminate fails to complete */ +-static void nes_terminate_timeout(unsigned long context) ++void nes_terminate_timeout(unsigned long context) + { + struct nes_qp *nesqp = (struct nes_qp *)(unsigned long)context; + +@@ -3532,11 +3531,7 @@ static void nes_terminate_timeout(unsign + /* Set a timer in case hw cannot complete the terminate sequence */ + static void nes_terminate_start_timer(struct nes_qp *nesqp) + { +- init_timer(&nesqp->terminate_timer); +- nesqp->terminate_timer.function = nes_terminate_timeout; +- nesqp->terminate_timer.expires = jiffies + HZ; +- nesqp->terminate_timer.data = (unsigned long)nesqp; +- add_timer(&nesqp->terminate_timer); ++ mod_timer(&nesqp->terminate_timer, (jiffies + HZ)); + } + + /** +--- a/drivers/infiniband/hw/nes/nes_verbs.c ++++ b/drivers/infiniband/hw/nes/nes_verbs.c +@@ -1404,6 +1404,9 @@ static struct ib_qp *nes_create_qp(struc + } + + nesqp->sig_all = (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR); ++ init_timer(&nesqp->terminate_timer); ++ nesqp->terminate_timer.function = nes_terminate_timeout; ++ nesqp->terminate_timer.data = (unsigned long)nesqp; + + /* update the QP table */ + nesdev->nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = nesqp; +@@ -1413,7 +1416,6 @@ static struct ib_qp *nes_create_qp(struc + return &nesqp->ibqp; + } + +- + /** + * nes_clean_cq + */ diff --git a/queue-3.4/ring-buffer-fix-race-between-integrity-check-and-readers.patch b/queue-3.4/ring-buffer-fix-race-between-integrity-check-and-readers.patch new file mode 100644 index 00000000000..ffaae649dd7 --- /dev/null +++ b/queue-3.4/ring-buffer-fix-race-between-integrity-check-and-readers.patch @@ -0,0 +1,65 @@ +From 9366c1ba13fbc41bdb57702e75ca4382f209c82f Mon Sep 17 00:00:00 2001 +From: Steven Rostedt +Date: Thu, 29 Nov 2012 22:31:16 -0500 +Subject: ring-buffer: Fix race between integrity check and readers + +From: Steven Rostedt + +commit 9366c1ba13fbc41bdb57702e75ca4382f209c82f upstream. + +The function rb_check_pages() was added to make sure the ring buffer's +pages were sane. This check is done when the ring buffer size is modified +as well as when the iterator is released (closing the "trace" file), +as that was considered a non fast path and a good place to do a sanity +check. + +The problem is that the check does not have any locks around it. +If one process were to read the trace file, and another were to read +the raw binary file, the check could happen while the reader is reading +the file. + +The issues with this is that the check requires to clear the HEAD page +before doing the full check and it restores it afterward. But readers +require the HEAD page to exist before it can read the buffer, otherwise +it gives a nasty warning and disables the buffer. + +By adding the reader lock around the check, this keeps the race from +happening. + +Signed-off-by: Steven Rostedt +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/trace/ring_buffer.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -2708,7 +2708,7 @@ unsigned long ring_buffer_oldest_event_t + unsigned long flags; + struct ring_buffer_per_cpu *cpu_buffer; + struct buffer_page *bpage; +- unsigned long ret; ++ unsigned long ret = 0; + + if (!cpumask_test_cpu(cpu, buffer->cpumask)) + return 0; +@@ -2723,7 +2723,8 @@ unsigned long ring_buffer_oldest_event_t + bpage = cpu_buffer->reader_page; + else + bpage = rb_set_head_page(cpu_buffer); +- ret = bpage->page->time_stamp; ++ if (bpage) ++ ret = bpage->page->time_stamp; + raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); + + return ret; +@@ -3030,6 +3031,8 @@ rb_get_reader_page(struct ring_buffer_pe + * Splice the empty reader page into the list around the head. + */ + reader = rb_set_head_page(cpu_buffer); ++ if (!reader) ++ goto out; + cpu_buffer->reader_page->list.next = rb_list_head(reader->list.next); + cpu_buffer->reader_page->list.prev = reader->list.prev; + diff --git a/queue-3.4/series b/queue-3.4/series index bbdb155a309..b90ab8acac2 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -40,3 +40,8 @@ drm-radeon-add-wait_until-to-evergreen-vm-safe-reg-list.patch drm-radeon-properly-handle-ddc-probe-for-dp-bridges.patch drm-i915-make-the-panel-fitter-work-on-pipes-b-and-c-on-ivb.patch sunrpc-fix-validity-issues-with-rpc_pipefs-sb-s_fs_info.patch +rdma-nes-fix-for-crash-when-registering-zero-length-mr-for-cq.patch +rdma-nes-fix-for-terminate-timer-crash.patch +ring-buffer-fix-race-between-integrity-check-and-readers.patch +dm-persistent-data-rename-node-to-btree_node.patch +dm-ioctl-prevent-unsafe-change-to-dm_ioctl-data_size.patch -- 2.47.3