From: Greg Kroah-Hartman Date: Sun, 6 Oct 2013 00:04:57 +0000 (-0700) Subject: 3.11-stable patches X-Git-Tag: v3.0.100~26 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=add44208eb0c29a93de0646f1f525833611c484c;p=thirdparty%2Fkernel%2Fstable-queue.git 3.11-stable patches added patches: cciss-fix-info-leak-in-cciss_ioctl32_passthru.patch cpqarray-fix-info-leak-in-ida_locked_ioctl.patch hid-fix-data-access-in-implement.patch hid-fix-unused-rsize-usage.patch nfsd4-fix-leak-of-inode-reference-on-delegation-failure.patch --- diff --git a/queue-3.11/cciss-fix-info-leak-in-cciss_ioctl32_passthru.patch b/queue-3.11/cciss-fix-info-leak-in-cciss_ioctl32_passthru.patch new file mode 100644 index 00000000000..888d25532b2 --- /dev/null +++ b/queue-3.11/cciss-fix-info-leak-in-cciss_ioctl32_passthru.patch @@ -0,0 +1,35 @@ +From 58f09e00ae095e46ef9edfcf3a5fd9ccdfad065e Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Tue, 24 Sep 2013 15:27:45 -0700 +Subject: cciss: fix info leak in cciss_ioctl32_passthru() + +From: Dan Carpenter + +commit 58f09e00ae095e46ef9edfcf3a5fd9ccdfad065e upstream. + +The arg64 struct has a hole after ->buf_size which isn't cleared. Or if +any of the calls to copy_from_user() fail then that would cause an +information leak as well. + +This was assigned CVE-2013-2147. + +Signed-off-by: Dan Carpenter +Acked-by: Mike Miller +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/cciss.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/block/cciss.c ++++ b/drivers/block/cciss.c +@@ -1189,6 +1189,7 @@ static int cciss_ioctl32_passthru(struct + int err; + u32 cp; + ++ memset(&arg64, 0, sizeof(arg64)); + err = 0; + err |= + copy_from_user(&arg64.LUN_info, &arg32->LUN_info, diff --git a/queue-3.11/cpqarray-fix-info-leak-in-ida_locked_ioctl.patch b/queue-3.11/cpqarray-fix-info-leak-in-ida_locked_ioctl.patch new file mode 100644 index 00000000000..c0199dcedd6 --- /dev/null +++ b/queue-3.11/cpqarray-fix-info-leak-in-ida_locked_ioctl.patch @@ -0,0 +1,34 @@ +From 627aad1c01da6f881e7f98d71fd928ca0c316b1a Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Tue, 24 Sep 2013 15:27:44 -0700 +Subject: cpqarray: fix info leak in ida_locked_ioctl() + +From: Dan Carpenter + +commit 627aad1c01da6f881e7f98d71fd928ca0c316b1a upstream. + +The pciinfo struct has a two byte hole after ->dev_fn so stack +information could be leaked to the user. + +This was assigned CVE-2013-2147. + +Signed-off-by: Dan Carpenter +Acked-by: Mike Miller +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/cpqarray.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/block/cpqarray.c ++++ b/drivers/block/cpqarray.c +@@ -1193,6 +1193,7 @@ out_passthru: + ida_pci_info_struct pciinfo; + + if (!arg) return -EINVAL; ++ memset(&pciinfo, 0, sizeof(pciinfo)); + pciinfo.bus = host->pci_dev->bus->number; + pciinfo.dev_fn = host->pci_dev->devfn; + pciinfo.board_id = host->board_id; diff --git a/queue-3.11/hid-fix-data-access-in-implement.patch b/queue-3.11/hid-fix-data-access-in-implement.patch new file mode 100644 index 00000000000..cda7e8a77af --- /dev/null +++ b/queue-3.11/hid-fix-data-access-in-implement.patch @@ -0,0 +1,243 @@ +From 27ce405039bfe6d3f4143415c638f56a3df77dca Mon Sep 17 00:00:00 2001 +From: Jiri Kosina +Date: Wed, 10 Jul 2013 19:56:27 +0200 +Subject: HID: fix data access in implement() + +From: Jiri Kosina + +commit 27ce405039bfe6d3f4143415c638f56a3df77dca upstream. + +implement() is setting bytes in LE data stream. In case the data is not +aligned to 64bits, it reads past the allocated buffer. It doesn't really +change any value there (it's properly bitmasked), but in case that this +read past the boundary hits a page boundary, pagefault happens when +accessing 64bits of 'x' in implement(), and kernel oopses. + +This happens much more often when numbered reports are in use, as the +initial 8bit skip in the buffer makes the whole process work on values +which are not aligned to 64bits. + +This problem dates back to attempts in 2005 and 2006 to make implement() +and extract() as generic as possible, and even back then the problem +was realized by Adam Kroperlin, but falsely assumed to be impossible +to cause any harm: + + http://www.mail-archive.com/linux-usb-devel@lists.sourceforge.net/msg47690.html + +I have made several attempts at fixing it "on the spot" directly in +implement(), but the results were horrible; the special casing for processing +last 64bit chunk and switching to different math makes it unreadable mess. + +I therefore took a path to allocate a few bytes more which will never make +it into final report, but are there as a cushion for all the 64bit math +operations happening in implement() and extract(). + +All callers of hid_output_report() are converted at the same time to allocate +the buffer by newly introduced hid_alloc_report_buf() helper. + +Bruno noticed that the whole raw_size test can be dropped as well, as +hid_alloc_report_buf() makes sure that the buffer is always of a proper +size. + +Reviewed-by: Benjamin Tissoires +Acked-by: Gustavo Padovan +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-core.c | 19 ++++++++++++++++++- + drivers/hid/hid-logitech-dj.c | 12 ++++++++++-- + drivers/hid/hid-picolcd_debugfs.c | 23 ++++++++++++----------- + drivers/hid/usbhid/hid-core.c | 5 ++--- + include/linux/hid.h | 1 + + net/bluetooth/hidp/core.c | 14 +++++++++----- + 6 files changed, 52 insertions(+), 22 deletions(-) + +--- a/drivers/hid/hid-core.c ++++ b/drivers/hid/hid-core.c +@@ -1188,7 +1188,8 @@ static void hid_output_field(const struc + } + + /* +- * Create a report. ++ * Create a report. 'data' has to be allocated using ++ * hid_alloc_report_buf() so that it has proper size. + */ + + void hid_output_report(struct hid_report *report, __u8 *data) +@@ -1205,6 +1206,22 @@ void hid_output_report(struct hid_report + EXPORT_SYMBOL_GPL(hid_output_report); + + /* ++ * Allocator for buffer that is going to be passed to hid_output_report() ++ */ ++u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags) ++{ ++ /* ++ * 7 extra bytes are necessary to achieve proper functionality ++ * of implement() working on 8 byte chunks ++ */ ++ ++ int len = ((report->size - 1) >> 3) + 1 + (report->id > 0) + 7; ++ ++ return kmalloc(len, flags); ++} ++EXPORT_SYMBOL_GPL(hid_alloc_report_buf); ++ ++/* + * Set a field value. The report this field belongs to has to be + * created and transferred to the device, to set this value in the + * device. +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -619,7 +619,7 @@ static int logi_dj_ll_input_event(struct + + struct hid_field *field; + struct hid_report *report; +- unsigned char data[8]; ++ unsigned char *data; + int offset; + + dbg_hid("%s: %s, type:%d | code:%d | value:%d\n", +@@ -635,6 +635,13 @@ static int logi_dj_ll_input_event(struct + return -1; + } + hid_set_field(field, offset, value); ++ ++ data = hid_alloc_report_buf(field->report, GFP_KERNEL); ++ if (!data) { ++ dev_warn(&dev->dev, "failed to allocate report buf memory\n"); ++ return -1; ++ } ++ + hid_output_report(field->report, &data[0]); + + output_report_enum = &dj_rcv_hiddev->report_enum[HID_OUTPUT_REPORT]; +@@ -645,8 +652,9 @@ static int logi_dj_ll_input_event(struct + + hid_hw_request(dj_rcv_hiddev, report, HID_REQ_SET_REPORT); + +- return 0; ++ kfree(data); + ++ return 0; + } + + static int logi_dj_ll_start(struct hid_device *hid) +--- a/drivers/hid/hid-picolcd_debugfs.c ++++ b/drivers/hid/hid-picolcd_debugfs.c +@@ -394,7 +394,7 @@ static void dump_buff_as_hex(char *dst, + void picolcd_debug_out_report(struct picolcd_data *data, + struct hid_device *hdev, struct hid_report *report) + { +- u8 raw_data[70]; ++ u8 *raw_data; + int raw_size = (report->size >> 3) + 1; + char *buff; + #define BUFF_SZ 256 +@@ -407,20 +407,20 @@ void picolcd_debug_out_report(struct pic + if (!buff) + return; + +- snprintf(buff, BUFF_SZ, "\nout report %d (size %d) = ", +- report->id, raw_size); +- hid_debug_event(hdev, buff); +- if (raw_size + 5 > sizeof(raw_data)) { ++ raw_data = hid_alloc_report_buf(report, GFP_ATOMIC); ++ if (!raw_data) { + kfree(buff); +- hid_debug_event(hdev, " TOO BIG\n"); + return; +- } else { +- raw_data[0] = report->id; +- hid_output_report(report, raw_data); +- dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size); +- hid_debug_event(hdev, buff); + } + ++ snprintf(buff, BUFF_SZ, "\nout report %d (size %d) = ", ++ report->id, raw_size); ++ hid_debug_event(hdev, buff); ++ raw_data[0] = report->id; ++ hid_output_report(report, raw_data); ++ dump_buff_as_hex(buff, BUFF_SZ, raw_data, raw_size); ++ hid_debug_event(hdev, buff); ++ + switch (report->id) { + case REPORT_LED_STATE: + /* 1 data byte with GPO state */ +@@ -644,6 +644,7 @@ void picolcd_debug_out_report(struct pic + break; + } + wake_up_interruptible(&hdev->debug_wait); ++ kfree(raw_data); + kfree(buff); + } + +--- a/drivers/hid/usbhid/hid-core.c ++++ b/drivers/hid/usbhid/hid-core.c +@@ -535,7 +535,6 @@ static void __usbhid_submit_report(struc + { + int head; + struct usbhid_device *usbhid = hid->driver_data; +- int len = ((report->size - 1) >> 3) + 1 + (report->id > 0); + + if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) + return; +@@ -546,7 +545,7 @@ static void __usbhid_submit_report(struc + return; + } + +- usbhid->out[usbhid->outhead].raw_report = kmalloc(len, GFP_ATOMIC); ++ usbhid->out[usbhid->outhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC); + if (!usbhid->out[usbhid->outhead].raw_report) { + hid_warn(hid, "output queueing failed\n"); + return; +@@ -595,7 +594,7 @@ static void __usbhid_submit_report(struc + } + + if (dir == USB_DIR_OUT) { +- usbhid->ctrl[usbhid->ctrlhead].raw_report = kmalloc(len, GFP_ATOMIC); ++ usbhid->ctrl[usbhid->ctrlhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC); + if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) { + hid_warn(hid, "control queueing failed\n"); + return; +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -746,6 +746,7 @@ struct hid_field *hidinput_get_led_field + unsigned int hidinput_count_leds(struct hid_device *hid); + __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code); + void hid_output_report(struct hid_report *report, __u8 *data); ++u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags); + struct hid_device *hid_allocate_device(void); + struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); + int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); +--- a/net/bluetooth/hidp/core.c ++++ b/net/bluetooth/hidp/core.c +@@ -225,17 +225,21 @@ static void hidp_input_report(struct hid + + static int hidp_send_report(struct hidp_session *session, struct hid_report *report) + { +- unsigned char buf[32], hdr; +- int rsize; ++ unsigned char hdr; ++ u8 *buf; ++ int rsize, ret; + +- rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0); +- if (rsize > sizeof(buf)) ++ buf = hid_alloc_report_buf(report, GFP_ATOMIC); ++ if (!buf) + return -EIO; + + hid_output_report(report, buf); + hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT; + +- return hidp_send_intr_message(session, hdr, buf, rsize); ++ ret = hidp_send_intr_message(session, hdr, buf, rsize); ++ ++ kfree(buf); ++ return ret; + } + + static int hidp_get_raw_report(struct hid_device *hid, diff --git a/queue-3.11/hid-fix-unused-rsize-usage.patch b/queue-3.11/hid-fix-unused-rsize-usage.patch new file mode 100644 index 00000000000..bd0456533e5 --- /dev/null +++ b/queue-3.11/hid-fix-unused-rsize-usage.patch @@ -0,0 +1,30 @@ +From bc197eedef1ae082ec662c64c3f4aa302821fb7a Mon Sep 17 00:00:00 2001 +From: Jiri Kosina +Date: Mon, 22 Jul 2013 17:11:44 +0200 +Subject: HID: fix unused rsize usage + +From: Jiri Kosina + +commit bc197eedef1ae082ec662c64c3f4aa302821fb7a upstream. + +27ce4050 ("HID: fix data access in implement()") by mistake removed +a setting of buffer size in hidp. Fix that by putting it back. + +Reported-by: kbuild test robot +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + net/bluetooth/hidp/core.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/bluetooth/hidp/core.c ++++ b/net/bluetooth/hidp/core.c +@@ -236,6 +236,7 @@ static int hidp_send_report(struct hidp_ + hid_output_report(report, buf); + hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT; + ++ rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0); + ret = hidp_send_intr_message(session, hdr, buf, rsize); + + kfree(buf); diff --git a/queue-3.11/nfsd4-fix-leak-of-inode-reference-on-delegation-failure.patch b/queue-3.11/nfsd4-fix-leak-of-inode-reference-on-delegation-failure.patch new file mode 100644 index 00000000000..5d68d5a73d4 --- /dev/null +++ b/queue-3.11/nfsd4-fix-leak-of-inode-reference-on-delegation-failure.patch @@ -0,0 +1,107 @@ +From bf7bd3e98be5c74813bee6ad496139fb0a011b3b Mon Sep 17 00:00:00 2001 +From: "J. Bruce Fields" +Date: Thu, 15 Aug 2013 16:55:26 -0400 +Subject: nfsd4: fix leak of inode reference on delegation failure + +From: "J. Bruce Fields" + +commit bf7bd3e98be5c74813bee6ad496139fb0a011b3b upstream. + +This fixes a regression from 68a3396178e6688ad7367202cdf0af8ed03c8727 +"nfsd4: shut down more of delegation earlier". + +After that commit, nfs4_set_delegation() failures result in +nfs4_put_delegation being called, but nfs4_put_delegation doesn't free +the nfs4_file that has already been set by alloc_init_deleg(). + +This can result in an oops on later unmounting the exported filesystem. + +Note also delaying the fi_had_conflict check we're able to return a +better error (hence give 4.1 clients a better idea why the delegation +failed; though note CONFLICT isn't an exact match here, as that's +supposed to indicate a current conflict, but all we know here is that +there was one recently). + +Reported-by: Toralf Förster +Tested-by: Toralf Förster +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfsd/nfs4state.c | 31 ++++++++++++++++++++----------- + 1 file changed, 20 insertions(+), 11 deletions(-) + +--- a/fs/nfsd/nfs4state.c ++++ b/fs/nfsd/nfs4state.c +@@ -368,11 +368,8 @@ static struct nfs4_delegation * + alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh) + { + struct nfs4_delegation *dp; +- struct nfs4_file *fp = stp->st_file; + + dprintk("NFSD alloc_init_deleg\n"); +- if (fp->fi_had_conflict) +- return NULL; + if (num_delegations > max_delegations) + return NULL; + dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab)); +@@ -389,8 +386,7 @@ alloc_init_deleg(struct nfs4_client *clp + INIT_LIST_HEAD(&dp->dl_perfile); + INIT_LIST_HEAD(&dp->dl_perclnt); + INIT_LIST_HEAD(&dp->dl_recall_lru); +- get_nfs4_file(fp); +- dp->dl_file = fp; ++ dp->dl_file = NULL; + dp->dl_type = NFS4_OPEN_DELEGATE_READ; + fh_copy_shallow(&dp->dl_fh, ¤t_fh->fh_handle); + dp->dl_time = 0; +@@ -3044,22 +3040,35 @@ static int nfs4_setlease(struct nfs4_del + return 0; + } + +-static int nfs4_set_delegation(struct nfs4_delegation *dp) ++static int nfs4_set_delegation(struct nfs4_delegation *dp, struct nfs4_file *fp) + { +- struct nfs4_file *fp = dp->dl_file; ++ int status; + +- if (!fp->fi_lease) +- return nfs4_setlease(dp); ++ if (fp->fi_had_conflict) ++ return -EAGAIN; ++ get_nfs4_file(fp); ++ dp->dl_file = fp; ++ if (!fp->fi_lease) { ++ status = nfs4_setlease(dp); ++ if (status) ++ goto out_free; ++ return 0; ++ } + spin_lock(&recall_lock); + if (fp->fi_had_conflict) { + spin_unlock(&recall_lock); +- return -EAGAIN; ++ status = -EAGAIN; ++ goto out_free; + } + atomic_inc(&fp->fi_delegees); + list_add(&dp->dl_perfile, &fp->fi_delegations); + spin_unlock(&recall_lock); + list_add(&dp->dl_perclnt, &dp->dl_stid.sc_client->cl_delegations); + return 0; ++out_free: ++ put_nfs4_file(fp); ++ dp->dl_file = fp; ++ return status; + } + + static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status) +@@ -3134,7 +3143,7 @@ nfs4_open_delegation(struct net *net, st + dp = alloc_init_deleg(oo->oo_owner.so_client, stp, fh); + if (dp == NULL) + goto out_no_deleg; +- status = nfs4_set_delegation(dp); ++ status = nfs4_set_delegation(dp, stp->st_file); + if (status) + goto out_free; + diff --git a/queue-3.11/series b/queue-3.11/series new file mode 100644 index 00000000000..ea86c234f93 --- /dev/null +++ b/queue-3.11/series @@ -0,0 +1,5 @@ +nfsd4-fix-leak-of-inode-reference-on-delegation-failure.patch +cpqarray-fix-info-leak-in-ida_locked_ioctl.patch +cciss-fix-info-leak-in-cciss_ioctl32_passthru.patch +hid-fix-data-access-in-implement.patch +hid-fix-unused-rsize-usage.patch