]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.13-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Oct 2017 18:15:55 +0000 (20:15 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 10 Oct 2017 18:15:55 +0000 (20:15 +0200)
added patches:
brcmfmac-add-length-check-in-brcmf_cfg80211_escan_handler.patch
brcmfmac-setup-passive-scan-if-requested-by-user-space.patch
bsg-lib-fix-use-after-free-under-memory-pressure.patch
clk-samsung-exynos4-enable-vpll-and-epll-clocks-for-suspend-resume-cycle.patch
drm-i915-always-update-eld-connector-type-after-get-modes.patch
drm-i915-bios-ignore-hdmi-on-port-a.patch
mmc-core-add-driver-strength-selection-when-selecting-hs400es.patch
nl80211-define-policy-for-packet-pattern-attributes.patch
nvme-pci-use-pci-bus-address-for-data-queues-in-cmb.patch
udp-fix-bcast-packet-reception.patch
udp-perform-source-validation-for-mcast-early-demux.patch

12 files changed:
queue-4.13/brcmfmac-add-length-check-in-brcmf_cfg80211_escan_handler.patch [new file with mode: 0644]
queue-4.13/brcmfmac-setup-passive-scan-if-requested-by-user-space.patch [new file with mode: 0644]
queue-4.13/bsg-lib-fix-use-after-free-under-memory-pressure.patch [new file with mode: 0644]
queue-4.13/clk-samsung-exynos4-enable-vpll-and-epll-clocks-for-suspend-resume-cycle.patch [new file with mode: 0644]
queue-4.13/drm-i915-always-update-eld-connector-type-after-get-modes.patch [new file with mode: 0644]
queue-4.13/drm-i915-bios-ignore-hdmi-on-port-a.patch [new file with mode: 0644]
queue-4.13/mmc-core-add-driver-strength-selection-when-selecting-hs400es.patch [new file with mode: 0644]
queue-4.13/nl80211-define-policy-for-packet-pattern-attributes.patch [new file with mode: 0644]
queue-4.13/nvme-pci-use-pci-bus-address-for-data-queues-in-cmb.patch [new file with mode: 0644]
queue-4.13/series
queue-4.13/udp-fix-bcast-packet-reception.patch [new file with mode: 0644]
queue-4.13/udp-perform-source-validation-for-mcast-early-demux.patch [new file with mode: 0644]

diff --git a/queue-4.13/brcmfmac-add-length-check-in-brcmf_cfg80211_escan_handler.patch b/queue-4.13/brcmfmac-add-length-check-in-brcmf_cfg80211_escan_handler.patch
new file mode 100644 (file)
index 0000000..4bb8249
--- /dev/null
@@ -0,0 +1,71 @@
+From 17df6453d4be17910456e99c5a85025aa1b7a246 Mon Sep 17 00:00:00 2001
+From: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Date: Tue, 12 Sep 2017 10:47:53 +0200
+Subject: brcmfmac: add length check in brcmf_cfg80211_escan_handler()
+
+From: Arend Van Spriel <arend.vanspriel@broadcom.com>
+
+commit 17df6453d4be17910456e99c5a85025aa1b7a246 upstream.
+
+Upon handling the firmware notification for scans the length was
+checked properly and may result in corrupting kernel heap memory
+due to buffer overruns. This fix addresses CVE-2017-0786.
+
+Cc: Kevin Cernekee <cernekee@chromium.org>
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c |   18 ++++++++++--
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -3162,6 +3162,7 @@ brcmf_cfg80211_escan_handler(struct brcm
+       struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
+       s32 status;
+       struct brcmf_escan_result_le *escan_result_le;
++      u32 escan_buflen;
+       struct brcmf_bss_info_le *bss_info_le;
+       struct brcmf_bss_info_le *bss = NULL;
+       u32 bi_length;
+@@ -3181,11 +3182,23 @@ brcmf_cfg80211_escan_handler(struct brcm
+       if (status == BRCMF_E_STATUS_PARTIAL) {
+               brcmf_dbg(SCAN, "ESCAN Partial result\n");
++              if (e->datalen < sizeof(*escan_result_le)) {
++                      brcmf_err("invalid event data length\n");
++                      goto exit;
++              }
+               escan_result_le = (struct brcmf_escan_result_le *) data;
+               if (!escan_result_le) {
+                       brcmf_err("Invalid escan result (NULL pointer)\n");
+                       goto exit;
+               }
++              escan_buflen = le32_to_cpu(escan_result_le->buflen);
++              if (escan_buflen > BRCMF_ESCAN_BUF_SIZE ||
++                  escan_buflen > e->datalen ||
++                  escan_buflen < sizeof(*escan_result_le)) {
++                      brcmf_err("Invalid escan buffer length: %d\n",
++                                escan_buflen);
++                      goto exit;
++              }
+               if (le16_to_cpu(escan_result_le->bss_count) != 1) {
+                       brcmf_err("Invalid bss_count %d: ignoring\n",
+                                 escan_result_le->bss_count);
+@@ -3202,9 +3215,8 @@ brcmf_cfg80211_escan_handler(struct brcm
+               }
+               bi_length = le32_to_cpu(bss_info_le->length);
+-              if (bi_length != (le32_to_cpu(escan_result_le->buflen) -
+-                                      WL_ESCAN_RESULTS_FIXED_SIZE)) {
+-                      brcmf_err("Invalid bss_info length %d: ignoring\n",
++              if (bi_length != escan_buflen - WL_ESCAN_RESULTS_FIXED_SIZE) {
++                      brcmf_err("Ignoring invalid bss_info length: %d\n",
+                                 bi_length);
+                       goto exit;
+               }
diff --git a/queue-4.13/brcmfmac-setup-passive-scan-if-requested-by-user-space.patch b/queue-4.13/brcmfmac-setup-passive-scan-if-requested-by-user-space.patch
new file mode 100644 (file)
index 0000000..2aa498c
--- /dev/null
@@ -0,0 +1,85 @@
+From 35f62727df0ed8e5e4857e162d94fd46d861f1cf Mon Sep 17 00:00:00 2001
+From: Arend Van Spriel <arend.vanspriel@broadcom.com>
+Date: Tue, 12 Sep 2017 10:47:54 +0200
+Subject: brcmfmac: setup passive scan if requested by user-space
+
+From: Arend Van Spriel <arend.vanspriel@broadcom.com>
+
+commit 35f62727df0ed8e5e4857e162d94fd46d861f1cf upstream.
+
+The driver was not properly configuring firmware with regard to the
+type of scan. It always performed an active scan even when user-space
+was requesting for passive scan, ie. the scan request was done without
+any SSIDs specified.
+
+Reported-by: Huang, Jiangyang <Jiangyang.Huang@itron.com>
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c   |   19 ++--------
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h |    5 ++
+ 2 files changed, 9 insertions(+), 15 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -980,7 +980,7 @@ static void brcmf_escan_prep(struct brcm
+       eth_broadcast_addr(params_le->bssid);
+       params_le->bss_type = DOT11_BSSTYPE_ANY;
+-      params_le->scan_type = 0;
++      params_le->scan_type = BRCMF_SCANTYPE_ACTIVE;
+       params_le->channel_num = 0;
+       params_le->nprobes = cpu_to_le32(-1);
+       params_le->active_time = cpu_to_le32(-1);
+@@ -988,12 +988,9 @@ static void brcmf_escan_prep(struct brcm
+       params_le->home_time = cpu_to_le32(-1);
+       memset(&params_le->ssid_le, 0, sizeof(params_le->ssid_le));
+-      /* if request is null exit so it will be all channel broadcast scan */
+-      if (!request)
+-              return;
+-
+       n_ssids = request->n_ssids;
+       n_channels = request->n_channels;
++
+       /* Copy channel array if applicable */
+       brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n",
+                 n_channels);
+@@ -1030,16 +1027,8 @@ static void brcmf_escan_prep(struct brcm
+                       ptr += sizeof(ssid_le);
+               }
+       } else {
+-              brcmf_dbg(SCAN, "Broadcast scan %p\n", request->ssids);
+-              if ((request->ssids) && request->ssids->ssid_len) {
+-                      brcmf_dbg(SCAN, "SSID %s len=%d\n",
+-                                params_le->ssid_le.SSID,
+-                                request->ssids->ssid_len);
+-                      params_le->ssid_le.SSID_len =
+-                              cpu_to_le32(request->ssids->ssid_len);
+-                      memcpy(&params_le->ssid_le.SSID, request->ssids->ssid,
+-                              request->ssids->ssid_len);
+-              }
++              brcmf_dbg(SCAN, "Performing passive scan\n");
++              params_le->scan_type = BRCMF_SCANTYPE_PASSIVE;
+       }
+       /* Adding mask to channel numbers */
+       params_le->channel_num =
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+@@ -45,6 +45,11 @@
+ #define BRCMF_SCAN_PARAMS_COUNT_MASK  0x0000ffff
+ #define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16
++/* scan type definitions */
++#define BRCMF_SCANTYPE_DEFAULT                0xFF
++#define BRCMF_SCANTYPE_ACTIVE         0
++#define BRCMF_SCANTYPE_PASSIVE                1
++
+ #define BRCMF_WSEC_MAX_PSK_LEN                32
+ #define       BRCMF_WSEC_PASSPHRASE           BIT(0)
diff --git a/queue-4.13/bsg-lib-fix-use-after-free-under-memory-pressure.patch b/queue-4.13/bsg-lib-fix-use-after-free-under-memory-pressure.patch
new file mode 100644 (file)
index 0000000..dfa2159
--- /dev/null
@@ -0,0 +1,105 @@
+From eab40cf336065e8d765e006b81ff48c5c114b365 Mon Sep 17 00:00:00 2001
+From: Benjamin Block <bblock@linux.vnet.ibm.com>
+Date: Tue, 3 Oct 2017 12:48:37 +0200
+Subject: bsg-lib: fix use-after-free under memory-pressure
+
+From: Benjamin Block <bblock@linux.vnet.ibm.com>
+
+commit eab40cf336065e8d765e006b81ff48c5c114b365 upstream.
+
+When under memory-pressure it is possible that the mempool which backs
+the 'struct request_queue' will make use of up to BLKDEV_MIN_RQ count
+emergency buffers - in case it can't get a regular allocation. These
+buffers are preallocated and once they are also used, they are
+re-supplied with old finished requests from the same request_queue (see
+mempool_free()).
+
+The bug is, when re-supplying the emergency pool, the old requests are
+not again ran through the callback mempool_t->alloc(), and thus also not
+through the callback bsg_init_rq(). Thus we skip initialization, and
+while the sense-buffer still should be good, scsi_request->cmd might
+have become to be an invalid pointer in the meantime. When the request
+is initialized in bsg.c, and the user's CDB is larger than BLK_MAX_CDB,
+bsg will replace it with a custom allocated buffer, which is freed when
+the user's command is finished, thus it dangles afterwards. When next a
+command is sent by the user that has a smaller/similar CDB as
+BLK_MAX_CDB, bsg will assume that scsi_request->cmd is backed by
+scsi_request->__cmd, will not make a custom allocation, and write into
+undefined memory.
+
+Fix this by splitting bsg_init_rq() into two functions:
+ - bsg_init_rq() is changed to only do the allocation of the
+   sense-buffer, which is used to back the bsg job's reply buffer. This
+   pointer should never change during the lifetime of a scsi_request, so
+   it doesn't need re-initialization.
+ - bsg_initialize_rq() is a new function that makes use of
+   'struct request_queue's initialize_rq_fn callback (which was
+   introduced in v4.12). This is always called before the request is
+   given out via blk_get_request(). This function does the remaining
+   initialization that was previously done in bsg_init_rq(), and will
+   also do it when the request is taken from the emergency-pool of the
+   backing mempool.
+
+Fixes: 50b4d485528d ("bsg-lib: fix kernel panic resulting from missing allocation of reply-buffer")
+Reviewed-by: Hannes Reinecke <hare@suse.com>
+Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Benjamin Block <bblock@linux.vnet.ibm.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ block/bsg-lib.c |   27 +++++++++++++++++++++------
+ 1 file changed, 21 insertions(+), 6 deletions(-)
+
+--- a/block/bsg-lib.c
++++ b/block/bsg-lib.c
+@@ -207,20 +207,34 @@ static int bsg_init_rq(struct request_qu
+       struct bsg_job *job = blk_mq_rq_to_pdu(req);
+       struct scsi_request *sreq = &job->sreq;
++      /* called right after the request is allocated for the request_queue */
++
++      sreq->sense = kzalloc(SCSI_SENSE_BUFFERSIZE, gfp);
++      if (!sreq->sense)
++              return -ENOMEM;
++
++      return 0;
++}
++
++static void bsg_initialize_rq(struct request *req)
++{
++      struct bsg_job *job = blk_mq_rq_to_pdu(req);
++      struct scsi_request *sreq = &job->sreq;
++      void *sense = sreq->sense;
++
++      /* called right before the request is given to the request_queue user */
++
+       memset(job, 0, sizeof(*job));
+       scsi_req_init(sreq);
++
++      sreq->sense = sense;
+       sreq->sense_len = SCSI_SENSE_BUFFERSIZE;
+-      sreq->sense = kzalloc(sreq->sense_len, gfp);
+-      if (!sreq->sense)
+-              return -ENOMEM;
+       job->req = req;
+-      job->reply = sreq->sense;
++      job->reply = sense;
+       job->reply_len = sreq->sense_len;
+       job->dd_data = job + 1;
+-
+-      return 0;
+ }
+ static void bsg_exit_rq(struct request_queue *q, struct request *req)
+@@ -250,6 +264,7 @@ struct request_queue *bsg_setup_queue(st
+       q->cmd_size = sizeof(struct bsg_job) + dd_job_size;
+       q->init_rq_fn = bsg_init_rq;
+       q->exit_rq_fn = bsg_exit_rq;
++      q->initialize_rq_fn = bsg_initialize_rq;
+       q->request_fn = bsg_request_fn;
+       ret = blk_init_allocated_queue(q);
diff --git a/queue-4.13/clk-samsung-exynos4-enable-vpll-and-epll-clocks-for-suspend-resume-cycle.patch b/queue-4.13/clk-samsung-exynos4-enable-vpll-and-epll-clocks-for-suspend-resume-cycle.patch
new file mode 100644 (file)
index 0000000..bd7a919
--- /dev/null
@@ -0,0 +1,61 @@
+From 5dcbeca615ef12047a5f4097b91030cbf995b1d2 Mon Sep 17 00:00:00 2001
+From: Marek Szyprowski <m.szyprowski@samsung.com>
+Date: Tue, 19 Sep 2017 12:01:08 +0200
+Subject: clk: samsung: exynos4: Enable VPLL and EPLL clocks for suspend/resume cycle
+
+From: Marek Szyprowski <m.szyprowski@samsung.com>
+
+commit 5dcbeca615ef12047a5f4097b91030cbf995b1d2 upstream.
+
+Commit 6edfa11cb396 ("clk: samsung: Add enable/disable operation for
+PLL36XX clocks") added enable/disable operations to PLL clocks. Prior that
+VPLL and EPPL clocks were always enabled because the enable bit was never
+touched. Those clocks have to be enabled during suspend/resume cycle,
+because otherwise board fails to enter sleep mode. This patch enables them
+unconditionally before entering system suspend state. System restore
+function will set them to the previous state saved in the register cache
+done before that unconditional enable.
+
+Fixes: 6edfa11cb396 ("clk: samsung: Add enable/disable operation for PLL36XX clocks")
+Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
+Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com>
+Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
+Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
+Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/clk/samsung/clk-exynos4.c |   15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+--- a/drivers/clk/samsung/clk-exynos4.c
++++ b/drivers/clk/samsung/clk-exynos4.c
+@@ -294,6 +294,18 @@ static const struct samsung_clk_reg_dump
+ #define PLL_ENABLED   (1 << 31)
+ #define PLL_LOCKED    (1 << 29)
++static void exynos4_clk_enable_pll(u32 reg)
++{
++      u32 pll_con = readl(reg_base + reg);
++      pll_con |= PLL_ENABLED;
++      writel(pll_con, reg_base + reg);
++
++      while (!(pll_con & PLL_LOCKED)) {
++              cpu_relax();
++              pll_con = readl(reg_base + reg);
++      }
++}
++
+ static void exynos4_clk_wait_for_pll(u32 reg)
+ {
+       u32 pll_con;
+@@ -315,6 +327,9 @@ static int exynos4_clk_suspend(void)
+       samsung_clk_save(reg_base, exynos4_save_pll,
+                               ARRAY_SIZE(exynos4_clk_pll_regs));
++      exynos4_clk_enable_pll(EPLL_CON0);
++      exynos4_clk_enable_pll(VPLL_CON0);
++
+       if (exynos4_soc == EXYNOS4210) {
+               samsung_clk_save(reg_base, exynos4_save_soc,
+                                       ARRAY_SIZE(exynos4210_clk_save));
diff --git a/queue-4.13/drm-i915-always-update-eld-connector-type-after-get-modes.patch b/queue-4.13/drm-i915-always-update-eld-connector-type-after-get-modes.patch
new file mode 100644 (file)
index 0000000..fa2a9c8
--- /dev/null
@@ -0,0 +1,89 @@
+From 2d8f63297b9f0b430c96329893667c0bfdcbd47e Mon Sep 17 00:00:00 2001
+From: Jani Nikula <jani.nikula@intel.com>
+Date: Tue, 19 Sep 2017 18:38:13 +0300
+Subject: drm/i915: always update ELD connector type after get modes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jani Nikula <jani.nikula@intel.com>
+
+commit 2d8f63297b9f0b430c96329893667c0bfdcbd47e upstream.
+
+drm_edid_to_eld() initializes the connector ELD to zero, overwriting the
+ELD connector type initialized in intel_audio_codec_enable(). If
+userspace does getconnector and thus get_modes after modeset, a
+subsequent audio component i915_audio_component_get_eld() call will
+receive an ELD without the connector type properly set. It's fine for
+HDMI, but screws up audio for DP.
+
+Always set the ELD connector type at intel_connector_update_modes()
+based on the connector type. We can drop the connector type update from
+intel_audio_codec_enable().
+
+Credits to Joseph Nuzman <jnuzman@gmail.com> for figuring this out.
+
+Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Cc: Joseph Nuzman <jnuzman@gmail.com>
+Reported-by: Joseph Nuzman <jnuzman@gmail.com>
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=101583
+Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Tested-by: Joseph Nuzman <jnuzman@gmail.com>
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20170919153813.29808-1-jani.nikula@intel.com
+(cherry picked from commit d81fb7fd9436e81fda67e5bc8ed0713aa28d3db2)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/intel_audio.c |    5 -----
+ drivers/gpu/drm/i915/intel_modes.c |   17 +++++++++++++++++
+ 2 files changed, 17 insertions(+), 5 deletions(-)
+
+--- a/drivers/gpu/drm/i915/intel_audio.c
++++ b/drivers/gpu/drm/i915/intel_audio.c
+@@ -606,11 +606,6 @@ void intel_audio_codec_enable(struct int
+                        connector->encoder->base.id,
+                        connector->encoder->name);
+-      /* ELD Conn_Type */
+-      connector->eld[5] &= ~(3 << 2);
+-      if (intel_crtc_has_dp_encoder(crtc_state))
+-              connector->eld[5] |= (1 << 2);
+-
+       connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2;
+       if (dev_priv->display.audio_codec_enable)
+--- a/drivers/gpu/drm/i915/intel_modes.c
++++ b/drivers/gpu/drm/i915/intel_modes.c
+@@ -30,6 +30,21 @@
+ #include "intel_drv.h"
+ #include "i915_drv.h"
++static void intel_connector_update_eld_conn_type(struct drm_connector *connector)
++{
++      u8 conn_type;
++
++      if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
++          connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
++              conn_type = DRM_ELD_CONN_TYPE_DP;
++      } else {
++              conn_type = DRM_ELD_CONN_TYPE_HDMI;
++      }
++
++      connector->eld[DRM_ELD_SAD_COUNT_CONN_TYPE] &= ~DRM_ELD_CONN_TYPE_MASK;
++      connector->eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= conn_type;
++}
++
+ /**
+  * intel_connector_update_modes - update connector from edid
+  * @connector: DRM connector device to use
+@@ -44,6 +59,8 @@ int intel_connector_update_modes(struct
+       ret = drm_add_edid_modes(connector, edid);
+       drm_edid_to_eld(connector, edid);
++      intel_connector_update_eld_conn_type(connector);
++
+       return ret;
+ }
diff --git a/queue-4.13/drm-i915-bios-ignore-hdmi-on-port-a.patch b/queue-4.13/drm-i915-bios-ignore-hdmi-on-port-a.patch
new file mode 100644 (file)
index 0000000..f546246
--- /dev/null
@@ -0,0 +1,48 @@
+From 2ba7d7e0437127314864238f8bfcb8369d81075c Mon Sep 17 00:00:00 2001
+From: Jani Nikula <jani.nikula@intel.com>
+Date: Thu, 21 Sep 2017 17:19:20 +0300
+Subject: drm/i915/bios: ignore HDMI on port A
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Jani Nikula <jani.nikula@intel.com>
+
+commit 2ba7d7e0437127314864238f8bfcb8369d81075c upstream.
+
+The hardware state readout oopses after several warnings when trying to
+use HDMI on port A, if such a combination is configured in VBT. Filter
+the combo out already at the VBT parsing phase.
+
+v2: also ignore DVI (Ville)
+
+Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=102889
+Cc: Imre Deak <imre.deak@intel.com>
+Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
+Tested-by: Daniel Drake <dan@reactivated.net>
+Signed-off-by: Jani Nikula <jani.nikula@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20170921141920.18172-1-jani.nikula@intel.com
+(cherry picked from commit d27ffc1d00327c29b3aa97f941b42f0949f9e99f)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/intel_bios.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/gpu/drm/i915/intel_bios.c
++++ b/drivers/gpu/drm/i915/intel_bios.c
+@@ -1163,6 +1163,13 @@ static void parse_ddi_port(struct drm_i9
+       is_hdmi = is_dvi && (child->common.device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0;
+       is_edp = is_dp && (child->common.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR);
++      if (port == PORT_A && is_dvi) {
++              DRM_DEBUG_KMS("VBT claims port A supports DVI%s, ignoring\n",
++                            is_hdmi ? "/HDMI" : "");
++              is_dvi = false;
++              is_hdmi = false;
++      }
++
+       info->supports_dvi = is_dvi;
+       info->supports_hdmi = is_hdmi;
+       info->supports_dp = is_dp;
diff --git a/queue-4.13/mmc-core-add-driver-strength-selection-when-selecting-hs400es.patch b/queue-4.13/mmc-core-add-driver-strength-selection-when-selecting-hs400es.patch
new file mode 100644 (file)
index 0000000..ea78d52
--- /dev/null
@@ -0,0 +1,83 @@
+From fb458864d9a78cc433fec7979acbe4078c82d7a8 Mon Sep 17 00:00:00 2001
+From: Chanho Min <chanho.min@lge.com>
+Date: Tue, 26 Sep 2017 09:03:40 +0900
+Subject: mmc: core: add driver strength selection when selecting hs400es
+
+From: Chanho Min <chanho.min@lge.com>
+
+commit fb458864d9a78cc433fec7979acbe4078c82d7a8 upstream.
+
+The driver strength selection is missed and required when selecting
+hs400es. So, It is added here.
+
+Fixes: 81ac2af65793ecf ("mmc: core: implement enhanced strobe support")
+Signed-off-by: Hankyung Yu <hankyung.yu@lge.com>
+Signed-off-by: Chanho Min <chanho.min@lge.com>
+Reviewed-by: Adrian Hunter <adrian.hunter@intel.com>
+Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/mmc/core/mmc.c |   36 +++++++++++++++++++-----------------
+ 1 file changed, 19 insertions(+), 17 deletions(-)
+
+--- a/drivers/mmc/core/mmc.c
++++ b/drivers/mmc/core/mmc.c
+@@ -1286,6 +1286,23 @@ out_err:
+       return err;
+ }
++static void mmc_select_driver_type(struct mmc_card *card)
++{
++      int card_drv_type, drive_strength, drv_type;
++
++      card_drv_type = card->ext_csd.raw_driver_strength |
++                      mmc_driver_type_mask(0);
++
++      drive_strength = mmc_select_drive_strength(card,
++                                                 card->ext_csd.hs200_max_dtr,
++                                                 card_drv_type, &drv_type);
++
++      card->drive_strength = drive_strength;
++
++      if (drv_type)
++              mmc_set_driver_type(card->host, drv_type);
++}
++
+ static int mmc_select_hs400es(struct mmc_card *card)
+ {
+       struct mmc_host *host = card->host;
+@@ -1341,6 +1358,8 @@ static int mmc_select_hs400es(struct mmc
+               goto out_err;
+       }
++      mmc_select_driver_type(card);
++
+       /* Switch card to HS400 */
+       val = EXT_CSD_TIMING_HS400 |
+             card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
+@@ -1374,23 +1393,6 @@ out_err:
+       return err;
+ }
+-static void mmc_select_driver_type(struct mmc_card *card)
+-{
+-      int card_drv_type, drive_strength, drv_type;
+-
+-      card_drv_type = card->ext_csd.raw_driver_strength |
+-                      mmc_driver_type_mask(0);
+-
+-      drive_strength = mmc_select_drive_strength(card,
+-                                                 card->ext_csd.hs200_max_dtr,
+-                                                 card_drv_type, &drv_type);
+-
+-      card->drive_strength = drive_strength;
+-
+-      if (drv_type)
+-              mmc_set_driver_type(card->host, drv_type);
+-}
+-
+ /*
+  * For device supporting HS200 mode, the following sequence
+  * should be done before executing the tuning process.
diff --git a/queue-4.13/nl80211-define-policy-for-packet-pattern-attributes.patch b/queue-4.13/nl80211-define-policy-for-packet-pattern-attributes.patch
new file mode 100644 (file)
index 0000000..4fda7b2
--- /dev/null
@@ -0,0 +1,69 @@
+From ad670233c9e1d5feb365d870e30083ef1b889177 Mon Sep 17 00:00:00 2001
+From: Peng Xu <pxu@qti.qualcomm.com>
+Date: Tue, 3 Oct 2017 23:21:51 +0300
+Subject: nl80211: Define policy for packet pattern attributes
+
+From: Peng Xu <pxu@qti.qualcomm.com>
+
+commit ad670233c9e1d5feb365d870e30083ef1b889177 upstream.
+
+Define a policy for packet pattern attributes in order to fix a
+potential read over the end of the buffer during nla_get_u32()
+of the NL80211_PKTPAT_OFFSET attribute.
+
+Note that the data there can always be read due to SKB allocation
+(with alignment and struct skb_shared_info at the end), but the
+data might be uninitialized. This could be used to leak some data
+from uninitialized vmalloc() memory, but most drivers don't allow
+an offset (so you'd just get -EINVAL if the data is non-zero) or
+just allow it with a fixed value - 100 or 128 bytes, so anything
+above that would get -EINVAL. With brcmfmac the limit is 1500 so
+(at least) one byte could be obtained.
+
+Signed-off-by: Peng Xu <pxu@qti.qualcomm.com>
+Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
+[rewrite description based on SKB allocation knowledge]
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/wireless/nl80211.c |   14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -549,6 +549,14 @@ nl80211_nan_srf_policy[NL80211_NAN_SRF_A
+       [NL80211_NAN_SRF_MAC_ADDRS] = { .type = NLA_NESTED },
+ };
++/* policy for packet pattern attributes */
++static const struct nla_policy
++nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
++      [NL80211_PKTPAT_MASK] = { .type = NLA_BINARY, },
++      [NL80211_PKTPAT_PATTERN] = { .type = NLA_BINARY, },
++      [NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
++};
++
+ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
+                                    struct netlink_callback *cb,
+                                    struct cfg80211_registered_device **rdev,
+@@ -10529,7 +10537,8 @@ static int nl80211_set_wowlan(struct sk_
+                       u8 *mask_pat;
+                       nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat,
+-                                       NULL, info->extack);
++                                       nl80211_packet_pattern_policy,
++                                       info->extack);
+                       err = -EINVAL;
+                       if (!pat_tb[NL80211_PKTPAT_MASK] ||
+                           !pat_tb[NL80211_PKTPAT_PATTERN])
+@@ -10778,7 +10787,8 @@ static int nl80211_parse_coalesce_rule(s
+                           rem) {
+               u8 *mask_pat;
+-              nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat, NULL, NULL);
++              nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat,
++                               nl80211_packet_pattern_policy, NULL);
+               if (!pat_tb[NL80211_PKTPAT_MASK] ||
+                   !pat_tb[NL80211_PKTPAT_PATTERN])
+                       return -EINVAL;
diff --git a/queue-4.13/nvme-pci-use-pci-bus-address-for-data-queues-in-cmb.patch b/queue-4.13/nvme-pci-use-pci-bus-address-for-data-queues-in-cmb.patch
new file mode 100644 (file)
index 0000000..f85c832
--- /dev/null
@@ -0,0 +1,86 @@
+From 8969f1f8291762c13147c1ba89d46238af01675b Mon Sep 17 00:00:00 2001
+From: Christoph Hellwig <hch@lst.de>
+Date: Sun, 1 Oct 2017 09:37:35 +0200
+Subject: nvme-pci: Use PCI bus address for data/queues in CMB
+
+From: Christoph Hellwig <hch@lst.de>
+
+commit 8969f1f8291762c13147c1ba89d46238af01675b upstream.
+
+Currently, NVMe PCI host driver is programming CMB dma address as
+I/O SQs addresses. This results in failures on systems where 1:1
+outbound mapping is not used (example Broadcom iProc SOCs) because
+CMB BAR will be progammed with PCI bus address but NVMe PCI EP will
+try to access CMB using dma address.
+
+To have CMB working on systems without 1:1 outbound mapping, we
+program PCI bus address for I/O SQs instead of dma address. This
+approach will work on systems with/without 1:1 outbound mapping.
+
+Based on a report and previous patch from Abhishek Shah.
+
+Fixes: 8ffaadf7 ("NVMe: Use CMB for the IO SQes if available")
+Reported-by: Abhishek Shah <abhishek.shah@broadcom.com>
+Tested-by: Abhishek Shah <abhishek.shah@broadcom.com>
+Reviewed-by: Keith Busch <keith.busch@intel.com>
+Signed-off-by: Christoph Hellwig <hch@lst.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/nvme/host/pci.c |   14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+--- a/drivers/nvme/host/pci.c
++++ b/drivers/nvme/host/pci.c
+@@ -93,7 +93,7 @@ struct nvme_dev {
+       struct mutex shutdown_lock;
+       bool subsystem;
+       void __iomem *cmb;
+-      dma_addr_t cmb_dma_addr;
++      pci_bus_addr_t cmb_bus_addr;
+       u64 cmb_size;
+       u32 cmbsz;
+       u32 cmbloc;
+@@ -1218,7 +1218,7 @@ static int nvme_alloc_sq_cmds(struct nvm
+       if (qid && dev->cmb && use_cmb_sqes && NVME_CMB_SQS(dev->cmbsz)) {
+               unsigned offset = (qid - 1) * roundup(SQ_SIZE(depth),
+                                                     dev->ctrl.page_size);
+-              nvmeq->sq_dma_addr = dev->cmb_dma_addr + offset;
++              nvmeq->sq_dma_addr = dev->cmb_bus_addr + offset;
+               nvmeq->sq_cmds_io = dev->cmb + offset;
+       } else {
+               nvmeq->sq_cmds = dma_alloc_coherent(dev->dev, SQ_SIZE(depth),
+@@ -1517,7 +1517,7 @@ static void __iomem *nvme_map_cmb(struct
+       resource_size_t bar_size;
+       struct pci_dev *pdev = to_pci_dev(dev->dev);
+       void __iomem *cmb;
+-      dma_addr_t dma_addr;
++      int bar;
+       dev->cmbsz = readl(dev->bar + NVME_REG_CMBSZ);
+       if (!(NVME_CMB_SZ(dev->cmbsz)))
+@@ -1530,7 +1530,8 @@ static void __iomem *nvme_map_cmb(struct
+       szu = (u64)1 << (12 + 4 * NVME_CMB_SZU(dev->cmbsz));
+       size = szu * NVME_CMB_SZ(dev->cmbsz);
+       offset = szu * NVME_CMB_OFST(dev->cmbloc);
+-      bar_size = pci_resource_len(pdev, NVME_CMB_BIR(dev->cmbloc));
++      bar = NVME_CMB_BIR(dev->cmbloc);
++      bar_size = pci_resource_len(pdev, bar);
+       if (offset > bar_size)
+               return NULL;
+@@ -1543,12 +1544,11 @@ static void __iomem *nvme_map_cmb(struct
+       if (size > bar_size - offset)
+               size = bar_size - offset;
+-      dma_addr = pci_resource_start(pdev, NVME_CMB_BIR(dev->cmbloc)) + offset;
+-      cmb = ioremap_wc(dma_addr, size);
++      cmb = ioremap_wc(pci_resource_start(pdev, bar) + offset, size);
+       if (!cmb)
+               return NULL;
+-      dev->cmb_dma_addr = dma_addr;
++      dev->cmb_bus_addr = pci_bus_address(pdev, bar) + offset;
+       dev->cmb_size = size;
+       return cmb;
+ }
index cc7880b4858d62d77e68854484094aba206f22cb..448f8dbcaf4cb45c9d4cf0f14c34412038fc1c0b 100644 (file)
@@ -146,3 +146,14 @@ kvm-x86-avoid-async-pf-preempting-the-kernel-incorrectly.patch
 iwlwifi-mvm-use-iwl_hcmd_nocopy-for-mcast_filter_cmd.patch
 scsi-sd-implement-blacklist-option-for-write-same-w-unmap.patch
 scsi-sd-do-not-override-max_sectors_kb-sysfs-setting.patch
+brcmfmac-add-length-check-in-brcmf_cfg80211_escan_handler.patch
+brcmfmac-setup-passive-scan-if-requested-by-user-space.patch
+drm-i915-always-update-eld-connector-type-after-get-modes.patch
+drm-i915-bios-ignore-hdmi-on-port-a.patch
+bsg-lib-fix-use-after-free-under-memory-pressure.patch
+nvme-pci-use-pci-bus-address-for-data-queues-in-cmb.patch
+mmc-core-add-driver-strength-selection-when-selecting-hs400es.patch
+nl80211-define-policy-for-packet-pattern-attributes.patch
+clk-samsung-exynos4-enable-vpll-and-epll-clocks-for-suspend-resume-cycle.patch
+udp-perform-source-validation-for-mcast-early-demux.patch
+udp-fix-bcast-packet-reception.patch
diff --git a/queue-4.13/udp-fix-bcast-packet-reception.patch b/queue-4.13/udp-fix-bcast-packet-reception.patch
new file mode 100644 (file)
index 0000000..1794cda
--- /dev/null
@@ -0,0 +1,59 @@
+From 996b44fcef8f216ea0b6b6e74468c5a77b5e341f Mon Sep 17 00:00:00 2001
+From: Paolo Abeni <pabeni@redhat.com>
+Date: Mon, 9 Oct 2017 14:52:10 +0200
+Subject: udp: fix bcast packet reception
+
+From: Paolo Abeni <pabeni@redhat.com>
+
+commit 996b44fcef8f216ea0b6b6e74468c5a77b5e341f upstream.
+
+The commit bc044e8db796 ("udp: perform source validation for
+mcast early demux") does not take into account that broadcast packets
+lands in the same code path and they need different checks for the
+source address - notably, zero source address are valid for bcast
+and invalid for mcast.
+
+As a result, 2nd and later broadcast packets with 0 source address
+landing to the same socket are dropped. This breaks dhcp servers.
+
+Since we don't have stringent performance requirements for ingress
+broadcast traffic, fix it by disabling UDP early demux such traffic.
+
+Reported-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Fixes: bc044e8db796 ("udp: perform source validation for mcast early demux")
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/ipv4/udp.c |   14 +++++---------
+ 1 file changed, 5 insertions(+), 9 deletions(-)
+
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -2235,20 +2235,16 @@ int udp_v4_early_demux(struct sk_buff *s
+       iph = ip_hdr(skb);
+       uh = udp_hdr(skb);
+-      if (skb->pkt_type == PACKET_BROADCAST ||
+-          skb->pkt_type == PACKET_MULTICAST) {
++      if (skb->pkt_type == PACKET_MULTICAST) {
+               in_dev = __in_dev_get_rcu(skb->dev);
+               if (!in_dev)
+                       return 0;
+-              /* we are supposed to accept bcast packets */
+-              if (skb->pkt_type == PACKET_MULTICAST) {
+-                      ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr,
+-                                             iph->protocol);
+-                      if (!ours)
+-                              return 0;
+-              }
++              ours = ip_check_mc_rcu(in_dev, iph->daddr, iph->saddr,
++                                     iph->protocol);
++              if (!ours)
++                      return 0;
+               sk = __udp4_lib_mcast_demux_lookup(net, uh->dest, iph->daddr,
+                                                  uh->source, iph->saddr, dif);
diff --git a/queue-4.13/udp-perform-source-validation-for-mcast-early-demux.patch b/queue-4.13/udp-perform-source-validation-for-mcast-early-demux.patch
new file mode 100644 (file)
index 0000000..cfee690
--- /dev/null
@@ -0,0 +1,191 @@
+From foo@baz Mon Oct  9 09:32:35 CEST 2017
+From: Paolo Abeni <pabeni@redhat.com>
+Date: Thu, 28 Sep 2017 15:51:37 +0200
+Subject: udp: perform source validation for mcast early demux
+
+From: Paolo Abeni <pabeni@redhat.com>
+
+
+[ Upstream commit bc044e8db7962e727a75b591b9851ff2ac5cf846 ]
+
+The UDP early demux can leverate the rx dst cache even for
+multicast unconnected sockets.
+
+In such scenario the ipv4 source address is validated only on
+the first packet in the given flow. After that, when we fetch
+the dst entry  from the socket rx cache, we stop enforcing
+the rp_filter and we even start accepting any kind of martian
+addresses.
+
+Disabling the dst cache for unconnected multicast socket will
+cause large performace regression, nearly reducing by half the
+max ingress tput.
+
+Instead we factor out a route helper to completely validate an
+skb source address for multicast packets and we call it from
+the UDP early demux for mcast packets landing on unconnected
+sockets, after successful fetching the related cached dst entry.
+
+This still gives a measurable, but limited performance
+regression:
+
+               rp_filter = 0           rp_filter = 1
+edmux disabled:        1182 Kpps               1127 Kpps
+edmux before:  2238 Kpps               2238 Kpps
+edmux after:   2037 Kpps               2019 Kpps
+
+The above figures are on top of current net tree.
+Applying the net-next commit 6e617de84e87 ("net: avoid a full
+fib lookup when rp_filter is disabled.") the delta with
+rp_filter == 0 will decrease even more.
+
+Fixes: 421b3885bf6d ("udp: ipv4: Add udp early demux")
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/route.h |    4 +++-
+ net/ipv4/route.c    |   46 ++++++++++++++++++++++++++--------------------
+ net/ipv4/udp.c      |   13 ++++++++++++-
+ 3 files changed, 41 insertions(+), 22 deletions(-)
+
+--- a/include/net/route.h
++++ b/include/net/route.h
+@@ -175,7 +175,9 @@ static inline struct rtable *ip_route_ou
+       fl4->fl4_gre_key = gre_key;
+       return ip_route_output_key(net, fl4);
+ }
+-
++int ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr,
++                        u8 tos, struct net_device *dev,
++                        struct in_device *in_dev, u32 *itag);
+ int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src,
+                        u8 tos, struct net_device *devin);
+ int ip_route_input_rcu(struct sk_buff *skb, __be32 dst, __be32 src,
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -1520,43 +1520,56 @@ struct rtable *rt_dst_alloc(struct net_d
+ EXPORT_SYMBOL(rt_dst_alloc);
+ /* called in rcu_read_lock() section */
+-static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+-                              u8 tos, struct net_device *dev, int our)
++int ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr,
++                        u8 tos, struct net_device *dev,
++                        struct in_device *in_dev, u32 *itag)
+ {
+-      struct rtable *rth;
+-      struct in_device *in_dev = __in_dev_get_rcu(dev);
+-      unsigned int flags = RTCF_MULTICAST;
+-      u32 itag = 0;
+       int err;
+       /* Primary sanity checks. */
+-
+       if (!in_dev)
+               return -EINVAL;
+       if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr) ||
+           skb->protocol != htons(ETH_P_IP))
+-              goto e_inval;
++              return -EINVAL;
+       if (ipv4_is_loopback(saddr) && !IN_DEV_ROUTE_LOCALNET(in_dev))
+-              goto e_inval;
++              return -EINVAL;
+       if (ipv4_is_zeronet(saddr)) {
+               if (!ipv4_is_local_multicast(daddr))
+-                      goto e_inval;
++                      return -EINVAL;
+       } else {
+               err = fib_validate_source(skb, saddr, 0, tos, 0, dev,
+-                                        in_dev, &itag);
++                                        in_dev, itag);
+               if (err < 0)
+-                      goto e_err;
++                      return err;
+       }
++      return 0;
++}
++
++/* called in rcu_read_lock() section */
++static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
++                           u8 tos, struct net_device *dev, int our)
++{
++      struct in_device *in_dev = __in_dev_get_rcu(dev);
++      unsigned int flags = RTCF_MULTICAST;
++      struct rtable *rth;
++      u32 itag = 0;
++      int err;
++
++      err = ip_mc_validate_source(skb, daddr, saddr, tos, dev, in_dev, &itag);
++      if (err)
++              return err;
++
+       if (our)
+               flags |= RTCF_LOCAL;
+       rth = rt_dst_alloc(dev_net(dev)->loopback_dev, flags, RTN_MULTICAST,
+                          IN_DEV_CONF_GET(in_dev, NOPOLICY), false, false);
+       if (!rth)
+-              goto e_nobufs;
++              return -ENOBUFS;
+ #ifdef CONFIG_IP_ROUTE_CLASSID
+       rth->dst.tclassid = itag;
+@@ -1572,13 +1585,6 @@ static int ip_route_input_mc(struct sk_b
+       skb_dst_set(skb, &rth->dst);
+       return 0;
+-
+-e_nobufs:
+-      return -ENOBUFS;
+-e_inval:
+-      return -EINVAL;
+-e_err:
+-      return err;
+ }
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -2220,6 +2220,7 @@ static struct sock *__udp4_lib_demux_loo
+ int udp_v4_early_demux(struct sk_buff *skb)
+ {
+       struct net *net = dev_net(skb->dev);
++      struct in_device *in_dev = NULL;
+       const struct iphdr *iph;
+       const struct udphdr *uh;
+       struct sock *sk = NULL;
+@@ -2236,7 +2237,7 @@ int udp_v4_early_demux(struct sk_buff *s
+       if (skb->pkt_type == PACKET_BROADCAST ||
+           skb->pkt_type == PACKET_MULTICAST) {
+-              struct in_device *in_dev = __in_dev_get_rcu(skb->dev);
++              in_dev = __in_dev_get_rcu(skb->dev);
+               if (!in_dev)
+                       return 0;
+@@ -2266,11 +2267,21 @@ int udp_v4_early_demux(struct sk_buff *s
+       if (dst)
+               dst = dst_check(dst, 0);
+       if (dst) {
++              u32 itag = 0;
++
+               /* set noref for now.
+                * any place which wants to hold dst has to call
+                * dst_hold_safe()
+                */
+               skb_dst_set_noref(skb, dst);
++
++              /* for unconnected multicast sockets we need to validate
++               * the source on each packet
++               */
++              if (!inet_sk(sk)->inet_daddr && in_dev)
++                      return ip_mc_validate_source(skb, iph->daddr,
++                                                   iph->saddr, iph->tos,
++                                                   skb->dev, in_dev, &itag);
+       }
+       return 0;
+ }