From: Greg Kroah-Hartman Date: Tue, 3 Apr 2018 09:55:50 +0000 (+0200) Subject: 3.18-stable patches X-Git-Tag: v3.18.103~55 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e5567e0055e0ef6f9ca508215d37dbc0903da2b4;p=thirdparty%2Fkernel%2Fstable-queue.git 3.18-stable patches added patches: usb-gadget-align-buffer-size-when-allocating-for-out-endpoint.patch usb-gadget-change-len-to-size_t-on-alloc_ep_req.patch usb-gadget-define-free_ep_req-as-universal-function.patch usb-gadget-f_hid-fix-prevent-accessing-released-memory.patch usb-gadget-fix-usb_ep_align_maybe-endianness-and-new-usb_ep_align.patch --- diff --git a/queue-3.18/series b/queue-3.18/series index 31de45579f8..3885c0d9d12 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -39,3 +39,8 @@ alsa-pcm-use-dma_bytes-as-size-parameter-in-dma_mmap_coherent.patch alsa-pcm-potential-uninitialized-return-values.patch perf-hwbp-simplify-the-perf-hwbp-code-fix-documentation.patch partitions-msdos-unable-to-mount-ufs-44bsd-partitions.patch +usb-gadget-define-free_ep_req-as-universal-function.patch +usb-gadget-change-len-to-size_t-on-alloc_ep_req.patch +usb-gadget-fix-usb_ep_align_maybe-endianness-and-new-usb_ep_align.patch +usb-gadget-align-buffer-size-when-allocating-for-out-endpoint.patch +usb-gadget-f_hid-fix-prevent-accessing-released-memory.patch diff --git a/queue-3.18/usb-gadget-align-buffer-size-when-allocating-for-out-endpoint.patch b/queue-3.18/usb-gadget-align-buffer-size-when-allocating-for-out-endpoint.patch new file mode 100644 index 00000000000..7369d55fee0 --- /dev/null +++ b/queue-3.18/usb-gadget-align-buffer-size-when-allocating-for-out-endpoint.patch @@ -0,0 +1,67 @@ +From e0466156ee2e944fb47a3fa00932c3698a6d2c67 Mon Sep 17 00:00:00 2001 +From: "Felipe F. Tonello" +Date: Mon, 8 Aug 2016 21:30:06 +0100 +Subject: usb: gadget: align buffer size when allocating for OUT endpoint + +From: Felipe F. Tonello + +commit e0466156ee2e944fb47a3fa00932c3698a6d2c67 upstream. + +Using usb_ep_align() makes sure that the buffer size for OUT endpoints is +always aligned with wMaxPacketSize (512 usually). This makes sure +that no buffer has the wrong size, which can cause nasty bugs. + +Signed-off-by: Felipe F. Tonello +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/u_f.c | 3 +++ + drivers/usb/gadget/u_f.h | 16 +++++++++++++++- + 2 files changed, 18 insertions(+), 1 deletion(-) + +--- a/drivers/usb/gadget/u_f.c ++++ b/drivers/usb/gadget/u_f.c +@@ -12,6 +12,7 @@ + */ + + #include "u_f.h" ++#include + + struct usb_request *alloc_ep_req(struct usb_ep *ep, size_t len, int default_len) + { +@@ -20,6 +21,8 @@ struct usb_request *alloc_ep_req(struct + req = usb_ep_alloc_request(ep, GFP_ATOMIC); + if (req) { + req->length = len ?: default_len; ++ if (usb_endpoint_dir_out(ep->desc)) ++ req->length = usb_ep_align(ep, req->length); + req->buf = kmalloc(req->length, GFP_ATOMIC); + if (!req->buf) { + usb_ep_free_request(ep, req); +--- a/drivers/usb/gadget/u_f.h ++++ b/drivers/usb/gadget/u_f.h +@@ -47,8 +47,22 @@ + struct usb_ep; + struct usb_request; + +-/* Requests allocated via alloc_ep_req() must be freed by free_ep_req(). */ ++/** ++ * alloc_ep_req - returns a usb_request allocated by the gadget driver and ++ * allocates the request's buffer. ++ * ++ * @ep: the endpoint to allocate a usb_request ++ * @len: usb_requests's buffer suggested size ++ * @default_len: used if @len is not provided, ie, is 0 ++ * ++ * In case @ep direction is OUT, the @len will be aligned to ep's ++ * wMaxPacketSize. In order to avoid memory leaks or drops, *always* use ++ * usb_requests's length (req->length) to refer to the allocated buffer size. ++ * Requests allocated via alloc_ep_req() *must* be freed by free_ep_req(). ++ */ + struct usb_request *alloc_ep_req(struct usb_ep *ep, size_t len, int default_len); ++ ++/* Frees a usb_request previously allocated by alloc_ep_req() */ + static inline void free_ep_req(struct usb_ep *ep, struct usb_request *req) + { + kfree(req->buf); diff --git a/queue-3.18/usb-gadget-change-len-to-size_t-on-alloc_ep_req.patch b/queue-3.18/usb-gadget-change-len-to-size_t-on-alloc_ep_req.patch new file mode 100644 index 00000000000..aefaf7dee55 --- /dev/null +++ b/queue-3.18/usb-gadget-change-len-to-size_t-on-alloc_ep_req.patch @@ -0,0 +1,44 @@ +From 69bb99738b5c6d56d2b1a75db9cbb4d187453c1a Mon Sep 17 00:00:00 2001 +From: "Felipe F. Tonello" +Date: Mon, 8 Aug 2016 21:30:05 +0100 +Subject: usb: gadget: change len to size_t on alloc_ep_req() + +From: Felipe F. Tonello + +commit 69bb99738b5c6d56d2b1a75db9cbb4d187453c1a upstream. + +Length of buffers should be of type size_t whenever possible. Altough +recommended, this change has no real practical change, unless a driver has a +uses a huge or negative buffer size - it might help find these bugs. + +Signed-off-by: Felipe F. Tonello +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/u_f.c | 2 +- + drivers/usb/gadget/u_f.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/usb/gadget/u_f.c ++++ b/drivers/usb/gadget/u_f.c +@@ -13,7 +13,7 @@ + + #include "u_f.h" + +-struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len) ++struct usb_request *alloc_ep_req(struct usb_ep *ep, size_t len, int default_len) + { + struct usb_request *req; + +--- a/drivers/usb/gadget/u_f.h ++++ b/drivers/usb/gadget/u_f.h +@@ -48,7 +48,7 @@ struct usb_ep; + struct usb_request; + + /* Requests allocated via alloc_ep_req() must be freed by free_ep_req(). */ +-struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len); ++struct usb_request *alloc_ep_req(struct usb_ep *ep, size_t len, int default_len); + static inline void free_ep_req(struct usb_ep *ep, struct usb_request *req) + { + kfree(req->buf); diff --git a/queue-3.18/usb-gadget-define-free_ep_req-as-universal-function.patch b/queue-3.18/usb-gadget-define-free_ep_req-as-universal-function.patch new file mode 100644 index 00000000000..89a19820ac0 --- /dev/null +++ b/queue-3.18/usb-gadget-define-free_ep_req-as-universal-function.patch @@ -0,0 +1,101 @@ +From 079fe5a6da616891cca1a26e803e1df2a87e9ae5 Mon Sep 17 00:00:00 2001 +From: "Felipe F. Tonello" +Date: Tue, 10 Nov 2015 17:52:05 +0000 +Subject: usb: gadget: define free_ep_req as universal function + +From: Felipe F. Tonello + +commit 079fe5a6da616891cca1a26e803e1df2a87e9ae5 upstream. + +This function is shared between gadget functions, so this avoid unnecessary +duplicated code and potentially avoid memory leaks. + +Reviewed-by: Robert Baldyga +Signed-off-by: Felipe F. Tonello +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/function/f_midi.c | 6 ------ + drivers/usb/gadget/function/f_sourcesink.c | 6 ------ + drivers/usb/gadget/function/g_zero.h | 1 - + drivers/usb/gadget/u_f.c | 1 - + drivers/usb/gadget/u_f.h | 10 ++++++++-- + 5 files changed, 8 insertions(+), 16 deletions(-) + +--- a/drivers/usb/gadget/function/f_midi.c ++++ b/drivers/usb/gadget/function/f_midi.c +@@ -199,12 +199,6 @@ static inline struct usb_request *midi_a + return alloc_ep_req(ep, length, length); + } + +-static void free_ep_req(struct usb_ep *ep, struct usb_request *req) +-{ +- kfree(req->buf); +- usb_ep_free_request(ep, req); +-} +- + static const uint8_t f_midi_cin_length[] = { + 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1 + }; +--- a/drivers/usb/gadget/function/f_sourcesink.c ++++ b/drivers/usb/gadget/function/f_sourcesink.c +@@ -435,12 +435,6 @@ static inline struct usb_request *ss_all + return alloc_ep_req(ep, len, buflen); + } + +-void free_ep_req(struct usb_ep *ep, struct usb_request *req) +-{ +- kfree(req->buf); +- usb_ep_free_request(ep, req); +-} +- + static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep) + { + int value; +--- a/drivers/usb/gadget/function/g_zero.h ++++ b/drivers/usb/gadget/function/g_zero.h +@@ -69,7 +69,6 @@ void lb_modexit(void); + int lb_modinit(void); + + /* common utilities */ +-void free_ep_req(struct usb_ep *ep, struct usb_request *req); + void disable_endpoints(struct usb_composite_dev *cdev, + struct usb_ep *in, struct usb_ep *out, + struct usb_ep *iso_in, struct usb_ep *iso_out, +--- a/drivers/usb/gadget/u_f.c ++++ b/drivers/usb/gadget/u_f.c +@@ -11,7 +11,6 @@ + * published by the Free Software Foundation. + */ + +-#include + #include "u_f.h" + + struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len) +--- a/drivers/usb/gadget/u_f.h ++++ b/drivers/usb/gadget/u_f.h +@@ -16,6 +16,8 @@ + #ifndef __U_F_H__ + #define __U_F_H__ + ++#include ++ + /* Variable Length Array Macros **********************************************/ + #define vla_group(groupname) size_t groupname##__next = 0 + #define vla_group_size(groupname) groupname##__next +@@ -45,8 +47,12 @@ + struct usb_ep; + struct usb_request; + ++/* Requests allocated via alloc_ep_req() must be freed by free_ep_req(). */ + struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len); ++static inline void free_ep_req(struct usb_ep *ep, struct usb_request *req) ++{ ++ kfree(req->buf); ++ usb_ep_free_request(ep, req); ++} + + #endif /* __U_F_H__ */ +- +- diff --git a/queue-3.18/usb-gadget-f_hid-fix-prevent-accessing-released-memory.patch b/queue-3.18/usb-gadget-f_hid-fix-prevent-accessing-released-memory.patch new file mode 100644 index 00000000000..61a6f9a3728 --- /dev/null +++ b/queue-3.18/usb-gadget-f_hid-fix-prevent-accessing-released-memory.patch @@ -0,0 +1,93 @@ +From aa65d11aa008f4de58a9cee7e121666d9d68505e Mon Sep 17 00:00:00 2001 +From: Krzysztof Opasiak +Date: Thu, 19 Jan 2017 18:55:28 +0100 +Subject: usb: gadget: f_hid: fix: Prevent accessing released memory + +From: Krzysztof Opasiak + +commit aa65d11aa008f4de58a9cee7e121666d9d68505e upstream. + +When we unlock our spinlock to copy data to user we may get +disabled by USB host and free the whole list of completed out +requests including the one from which we are copying the data +to user memory. + +To prevent from this let's remove our working element from +the list and place it back only if there is sth left when we +finish with it. + +Fixes: 99c515005857 ("usb: gadget: hidg: register OUT INT endpoint for SET_REPORT") +Cc: stable@vger.kernel.org +Tested-by: David Lechner +Signed-off-by: Krzysztof Opasiak +Signed-off-by: Felipe Balbi +Cc: Jerry Zhang +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/function/f_hid.c | 24 ++++++++++++++++++++---- + 1 file changed, 20 insertions(+), 4 deletions(-) + +--- a/drivers/usb/gadget/function/f_hid.c ++++ b/drivers/usb/gadget/function/f_hid.c +@@ -197,6 +197,13 @@ static ssize_t f_hidg_read(struct file * + /* pick the first one */ + list = list_first_entry(&hidg->completed_out_req, + struct f_hidg_req_list, list); ++ ++ /* ++ * Remove this from list to protect it from beign free() ++ * while host disables our function ++ */ ++ list_del(&list->list); ++ + req = list->req; + count = min_t(unsigned int, count, req->actual - list->pos); + spin_unlock_irqrestore(&hidg->spinlock, flags); +@@ -212,15 +219,20 @@ static ssize_t f_hidg_read(struct file * + * call, taking into account its current read position. + */ + if (list->pos == req->actual) { +- spin_lock_irqsave(&hidg->spinlock, flags); +- list_del(&list->list); + kfree(list); +- spin_unlock_irqrestore(&hidg->spinlock, flags); + + req->length = hidg->report_length; + ret = usb_ep_queue(hidg->out_ep, req, GFP_KERNEL); +- if (ret < 0) ++ if (ret < 0) { ++ free_ep_req(hidg->out_ep, req); + return ret; ++ } ++ } else { ++ spin_lock_irqsave(&hidg->spinlock, flags); ++ list_add(&list->list, &hidg->completed_out_req); ++ spin_unlock_irqrestore(&hidg->spinlock, flags); ++ ++ wake_up(&hidg->read_queue); + } + + return count; +@@ -455,6 +467,7 @@ static void hidg_disable(struct usb_func + { + struct f_hidg *hidg = func_to_hidg(f); + struct f_hidg_req_list *list, *next; ++ unsigned long flags; + + usb_ep_disable(hidg->in_ep); + hidg->in_ep->driver_data = NULL; +@@ -462,10 +475,13 @@ static void hidg_disable(struct usb_func + usb_ep_disable(hidg->out_ep); + hidg->out_ep->driver_data = NULL; + ++ spin_lock_irqsave(&hidg->spinlock, flags); + list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) { ++ free_ep_req(hidg->out_ep, list->req); + list_del(&list->list); + kfree(list); + } ++ spin_unlock_irqrestore(&hidg->spinlock, flags); + } + + static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) diff --git a/queue-3.18/usb-gadget-fix-usb_ep_align_maybe-endianness-and-new-usb_ep_align.patch b/queue-3.18/usb-gadget-fix-usb_ep_align_maybe-endianness-and-new-usb_ep_align.patch new file mode 100644 index 00000000000..4db4b02a13d --- /dev/null +++ b/queue-3.18/usb-gadget-fix-usb_ep_align_maybe-endianness-and-new-usb_ep_align.patch @@ -0,0 +1,59 @@ +From 16b114a6d7973cf027e4c2b23eae1076eaf98c25 Mon Sep 17 00:00:00 2001 +From: "Felipe F. Tonello" +Date: Mon, 8 Aug 2016 21:30:04 +0100 +Subject: usb: gadget: fix usb_ep_align_maybe endianness and new usb_ep_align + +From: Felipe F. Tonello + +commit 16b114a6d7973cf027e4c2b23eae1076eaf98c25 upstream. + +USB spec specifies wMaxPacketSize to be little endian (as other properties), +so when using this variable in the driver we should convert to the current +CPU endianness if necessary. + +This patch also introduces usb_ep_align() which does always returns the +aligned buffer size for an endpoint. This is useful to be used by USB requests +allocator functions. + +Signed-off-by: Felipe F. Tonello +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/usb/gadget.h | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +--- a/include/linux/usb/gadget.h ++++ b/include/linux/usb/gadget.h +@@ -582,8 +582,20 @@ static inline struct usb_gadget *dev_to_ + + + /** ++ * usb_ep_align - returns @len aligned to ep's maxpacketsize. ++ * @ep: the endpoint whose maxpacketsize is used to align @len ++ * @len: buffer size's length to align to @ep's maxpacketsize ++ * ++ * This helper is used to align buffer's size to an ep's maxpacketsize. ++ */ ++static inline size_t usb_ep_align(struct usb_ep *ep, size_t len) ++{ ++ return round_up(len, (size_t)le16_to_cpu(ep->desc->wMaxPacketSize)); ++} ++ ++/** + * usb_ep_align_maybe - returns @len aligned to ep's maxpacketsize if gadget +- * requires quirk_ep_out_aligned_size, otherwise reguens len. ++ * requires quirk_ep_out_aligned_size, otherwise returns len. + * @g: controller to check for quirk + * @ep: the endpoint whose maxpacketsize is used to align @len + * @len: buffer size's length to align to @ep's maxpacketsize +@@ -594,8 +606,7 @@ static inline struct usb_gadget *dev_to_ + static inline size_t + usb_ep_align_maybe(struct usb_gadget *g, struct usb_ep *ep, size_t len) + { +- return !g->quirk_ep_out_aligned_size ? len : +- round_up(len, (size_t)ep->desc->wMaxPacketSize); ++ return g->quirk_ep_out_aligned_size ? usb_ep_align(ep, len) : len; + } + + /**