From 58735d2d114ebe6f7fedc48b0cc1f4ea23b6ed21 Mon Sep 17 00:00:00 2001 From: Michael W Date: Thu, 6 Jul 2017 15:16:23 +0200 Subject: [PATCH 1/3] cve_checker: Order CVEs by name --- check_patches.py | 2 +- cve_check.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/check_patches.py b/check_patches.py index 317fb28..e90c428 100644 --- a/check_patches.py +++ b/check_patches.py @@ -86,7 +86,7 @@ def main(): print("missing patchfiles:\n") for subdir in missing_patches: print(subdir) - for patch in missing_patches[subdir]: + for patch in sorted(missing_patches[subdir]): print("\t" + patch) print("") diff --git a/cve_check.py b/cve_check.py index 9d10ca1..460098d 100644 --- a/cve_check.py +++ b/cve_check.py @@ -26,7 +26,7 @@ def load_patches(path): if node.endswith(patch_suffix): patches.append(os.path.abspath(path) + '/' + node) - return patches + return sorted(patches) """ From ddcf189258204b7188d42c8a5fc527fc06125971 Mon Sep 17 00:00:00 2001 From: Michael W Date: Thu, 6 Jul 2017 13:29:18 +0200 Subject: [PATCH 2/3] cve_checker: Minor fix for usage --- cve_check.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cve_check.py b/cve_check.py index 460098d..df4dddd 100644 --- a/cve_check.py +++ b/cve_check.py @@ -111,7 +111,7 @@ def basic_check(kernel_repo, cve_patch): def print_usage(): - print("usage: pycve.py cve_dir kernel_repo") + print("usage: cve_check.py cve_dir kernel_repo") print("\noutput:") print("\t The CVE patch applies cleanly.") print("\t The CVE patch applies in reverse.") From 01991653eabf30054dedca0299a478a1ff6fe5b1 Mon Sep 17 00:00:00 2001 From: Michael W Date: Thu, 6 Jul 2017 19:52:14 +0200 Subject: [PATCH 3/3] cve_checker: Add a bunch of patches --- patches/3.10/CVE-2012-6701.patch | 105 ++++++++ patches/3.10/CVE-2012-6703.1.patch | 31 +++ patches/3.10/CVE-2012-6703.2.patch | 66 +++++ patches/3.10/CVE-2014-9869.1.patch | 73 ++++++ patches/3.10/CVE-2014-9869.2.patch | 144 +++++++++++ patches/3.10/CVE-2014-9870.patch | 215 ++++++++++++++++ patches/3.10/CVE-2014-9871.patch | 145 +++++++++++ patches/3.10/CVE-2014-9872.patch | 98 +++++++ patches/3.10/CVE-2014-9873.patch | 34 +++ patches/3.10/CVE-2014-9874.patch | 63 +++++ patches/3.10/CVE-2014-9875.patch | 245 ++++++++++++++++++ patches/3.10/CVE-2014-9876.patch | 30 +++ patches/3.10/CVE-2014-9877.patch | 93 +++++++ patches/3.10/CVE-2014-9878.patch | 102 ++++++++ patches/3.10/CVE-2014-9879.patch | 154 +++++++++++ patches/3.10/CVE-2014-9880.patch | 34 +++ patches/3.10/CVE-2014-9881.patch | 62 +++++ patches/3.10/CVE-2014-9883.patch | 57 +++++ patches/3.10/CVE-2014-9884.patch | 150 +++++++++++ patches/3.10/CVE-2014-9885.patch | 29 +++ patches/3.10/CVE-2014-9886.patch | 177 +++++++++++++ patches/3.10/CVE-2014-9887.patch | 34 +++ patches/3.10/CVE-2014-9888.patch | 37 +++ patches/3.10/CVE-2014-9889.patch | 154 +++++++++++ patches/3.10/CVE-2014-9890.patch | 38 +++ patches/3.10/CVE-2014-9891.patch | 63 +++++ patches/3.10/CVE-2014-9892.patch | 34 +++ patches/3.10/CVE-2014-9893.patch | 77 ++++++ patches/3.10/CVE-2014-9894.patch | 38 +++ patches/3.10/CVE-2014-9895.patch | 32 +++ patches/3.10/CVE-2014-9896.patch | 85 +++++++ patches/3.10/CVE-2014-9897.patch | 31 +++ patches/3.10/CVE-2014-9898.patch | 177 +++++++++++++ patches/3.10/CVE-2014-9899.patch | 42 +++ patches/3.10/CVE-2014-9900.patch | 35 +++ patches/3.10/CVE-2014-9901.patch | 293 +++++++++++++++++++++ patches/3.10/CVE-2014-9902.patch | 60 +++++ patches/3.10/CVE-2014-9904.patch | 35 +++ patches/3.10/CVE-2015-8938.patch | 254 +++++++++++++++++++ patches/3.10/CVE-2015-8939.patch | 66 +++++ patches/3.10/CVE-2015-8940.patch | 47 ++++ patches/3.10/CVE-2015-8941.patch | 158 ++++++++++++ patches/3.10/CVE-2015-8943.patch | 61 +++++ patches/3.10/CVE-2016-2185.patch | 108 ++++++++ patches/3.10/CVE-2016-2186.patch | 37 +++ patches/3.10/CVE-2016-2187.patch | 55 ++++ patches/3.10/CVE-2016-2188.patch | 40 +++ patches/3.10/CVE-2016-3136.patch | 48 ++++ patches/3.10/CVE-2016-3140.patch | 53 ++++ patches/3.10/CVE-2016-3689.patch | 39 +++ patches/3.10/CVE-2016-3857.patch | 51 ++++ patches/3.10/CVE-2016-5340.patch | 81 ++++++ patches/3.10/CVE-2016-8453.patch | 46 ++++ patches/3.10/CVE-2016-8454.patch | 264 +++++++++++++++++++ patches/3.10/CVE-2016-8455.patch | 120 +++++++++ patches/3.10/CVE-2016-8456.patch | 143 +++++++++++ patches/3.10/CVE-2016-8457.patch | 348 +++++++++++++++++++++++++ patches/3.10/CVE-2016-8458.patch | 394 +++++++++++++++++++++++++++++ patches/3.10/CVE-2016-8463.patch | 34 +++ patches/3.10/CVE-2016-8464.patch | 146 +++++++++++ patches/3.10/CVE-2016-8465.patch | 155 ++++++++++++ patches/3.10/CVE-2016-8466.patch | 101 ++++++++ patches/3.10/CVE-2016-8473.patch | 46 ++++ patches/3.10/CVE-2016-8474.patch | 46 ++++ patches/3.10/CVE-2016-9555.patch | 54 ++++ patches/3.10/CVE-2017-0510.patch | 205 +++++++++++++++ 66 files changed, 6572 insertions(+) create mode 100644 patches/3.10/CVE-2012-6701.patch create mode 100644 patches/3.10/CVE-2012-6703.1.patch create mode 100644 patches/3.10/CVE-2012-6703.2.patch create mode 100644 patches/3.10/CVE-2014-9869.1.patch create mode 100644 patches/3.10/CVE-2014-9869.2.patch create mode 100644 patches/3.10/CVE-2014-9870.patch create mode 100644 patches/3.10/CVE-2014-9871.patch create mode 100644 patches/3.10/CVE-2014-9872.patch create mode 100644 patches/3.10/CVE-2014-9873.patch create mode 100644 patches/3.10/CVE-2014-9874.patch create mode 100644 patches/3.10/CVE-2014-9875.patch create mode 100644 patches/3.10/CVE-2014-9876.patch create mode 100644 patches/3.10/CVE-2014-9877.patch create mode 100644 patches/3.10/CVE-2014-9878.patch create mode 100644 patches/3.10/CVE-2014-9879.patch create mode 100644 patches/3.10/CVE-2014-9880.patch create mode 100644 patches/3.10/CVE-2014-9881.patch create mode 100644 patches/3.10/CVE-2014-9883.patch create mode 100644 patches/3.10/CVE-2014-9884.patch create mode 100644 patches/3.10/CVE-2014-9885.patch create mode 100644 patches/3.10/CVE-2014-9886.patch create mode 100644 patches/3.10/CVE-2014-9887.patch create mode 100644 patches/3.10/CVE-2014-9888.patch create mode 100644 patches/3.10/CVE-2014-9889.patch create mode 100644 patches/3.10/CVE-2014-9890.patch create mode 100644 patches/3.10/CVE-2014-9891.patch create mode 100644 patches/3.10/CVE-2014-9892.patch create mode 100644 patches/3.10/CVE-2014-9893.patch create mode 100644 patches/3.10/CVE-2014-9894.patch create mode 100644 patches/3.10/CVE-2014-9895.patch create mode 100644 patches/3.10/CVE-2014-9896.patch create mode 100644 patches/3.10/CVE-2014-9897.patch create mode 100644 patches/3.10/CVE-2014-9898.patch create mode 100644 patches/3.10/CVE-2014-9899.patch create mode 100644 patches/3.10/CVE-2014-9900.patch create mode 100644 patches/3.10/CVE-2014-9901.patch create mode 100644 patches/3.10/CVE-2014-9902.patch create mode 100644 patches/3.10/CVE-2014-9904.patch create mode 100644 patches/3.10/CVE-2015-8938.patch create mode 100644 patches/3.10/CVE-2015-8939.patch create mode 100644 patches/3.10/CVE-2015-8940.patch create mode 100644 patches/3.10/CVE-2015-8941.patch create mode 100644 patches/3.10/CVE-2015-8943.patch create mode 100644 patches/3.10/CVE-2016-2185.patch create mode 100644 patches/3.10/CVE-2016-2186.patch create mode 100644 patches/3.10/CVE-2016-2187.patch create mode 100644 patches/3.10/CVE-2016-2188.patch create mode 100644 patches/3.10/CVE-2016-3136.patch create mode 100644 patches/3.10/CVE-2016-3140.patch create mode 100644 patches/3.10/CVE-2016-3689.patch create mode 100644 patches/3.10/CVE-2016-3857.patch create mode 100644 patches/3.10/CVE-2016-5340.patch create mode 100644 patches/3.10/CVE-2016-8453.patch create mode 100644 patches/3.10/CVE-2016-8454.patch create mode 100644 patches/3.10/CVE-2016-8455.patch create mode 100644 patches/3.10/CVE-2016-8456.patch create mode 100644 patches/3.10/CVE-2016-8457.patch create mode 100644 patches/3.10/CVE-2016-8458.patch create mode 100644 patches/3.10/CVE-2016-8463.patch create mode 100644 patches/3.10/CVE-2016-8464.patch create mode 100644 patches/3.10/CVE-2016-8465.patch create mode 100644 patches/3.10/CVE-2016-8466.patch create mode 100644 patches/3.10/CVE-2016-8473.patch create mode 100644 patches/3.10/CVE-2016-8474.patch create mode 100644 patches/3.10/CVE-2016-9555.patch create mode 100644 patches/3.10/CVE-2017-0510.patch diff --git a/patches/3.10/CVE-2012-6701.patch b/patches/3.10/CVE-2012-6701.patch new file mode 100644 index 0000000..64724d1 --- /dev/null +++ b/patches/3.10/CVE-2012-6701.patch @@ -0,0 +1,105 @@ +From a70b52ec1aaeaf60f4739edb1b422827cb6f3893 Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Mon, 21 May 2012 16:06:20 -0700 +Subject: vfs: make AIO use the proper rw_verify_area() area helpers + +We had for some reason overlooked the AIO interface, and it didn't use +the proper rw_verify_area() helper function that checks (for example) +mandatory locking on the file, and that the size of the access doesn't +cause us to overflow the provided offset limits etc. + +Instead, AIO did just the security_file_permission() thing (that +rw_verify_area() also does) directly. + +This fixes it to do all the proper helper functions, which not only +means that now mandatory file locking works with AIO too, we can +actually remove lines of code. + +Reported-by: Manish Honap +Cc: stable@vger.kernel.org +Signed-off-by: Linus Torvalds +--- + fs/aio.c | 30 ++++++++++++++---------------- + 1 file changed, 14 insertions(+), 16 deletions(-) + +diff --git a/fs/aio.c b/fs/aio.c +index 67a6db3..e7f2fad 100644 +--- a/fs/aio.c ++++ b/fs/aio.c +@@ -1456,6 +1456,10 @@ static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb, bool compat) + if (ret < 0) + goto out; + ++ ret = rw_verify_area(type, kiocb->ki_filp, &kiocb->ki_pos, ret); ++ if (ret < 0) ++ goto out; ++ + kiocb->ki_nr_segs = kiocb->ki_nbytes; + kiocb->ki_cur_seg = 0; + /* ki_nbytes/left now reflect bytes instead of segs */ +@@ -1467,11 +1471,17 @@ out: + return ret; + } + +-static ssize_t aio_setup_single_vector(struct kiocb *kiocb) ++static ssize_t aio_setup_single_vector(int type, struct file * file, struct kiocb *kiocb) + { ++ int bytes; ++ ++ bytes = rw_verify_area(type, file, &kiocb->ki_pos, kiocb->ki_left); ++ if (bytes < 0) ++ return bytes; ++ + kiocb->ki_iovec = &kiocb->ki_inline_vec; + kiocb->ki_iovec->iov_base = kiocb->ki_buf; +- kiocb->ki_iovec->iov_len = kiocb->ki_left; ++ kiocb->ki_iovec->iov_len = bytes; + kiocb->ki_nr_segs = 1; + kiocb->ki_cur_seg = 0; + return 0; +@@ -1496,10 +1506,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat) + if (unlikely(!access_ok(VERIFY_WRITE, kiocb->ki_buf, + kiocb->ki_left))) + break; +- ret = security_file_permission(file, MAY_READ); +- if (unlikely(ret)) +- break; +- ret = aio_setup_single_vector(kiocb); ++ ret = aio_setup_single_vector(READ, file, kiocb); + if (ret) + break; + ret = -EINVAL; +@@ -1514,10 +1521,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat) + if (unlikely(!access_ok(VERIFY_READ, kiocb->ki_buf, + kiocb->ki_left))) + break; +- ret = security_file_permission(file, MAY_WRITE); +- if (unlikely(ret)) +- break; +- ret = aio_setup_single_vector(kiocb); ++ ret = aio_setup_single_vector(WRITE, file, kiocb); + if (ret) + break; + ret = -EINVAL; +@@ -1528,9 +1532,6 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat) + ret = -EBADF; + if (unlikely(!(file->f_mode & FMODE_READ))) + break; +- ret = security_file_permission(file, MAY_READ); +- if (unlikely(ret)) +- break; + ret = aio_setup_vectored_rw(READ, kiocb, compat); + if (ret) + break; +@@ -1542,9 +1543,6 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat) + ret = -EBADF; + if (unlikely(!(file->f_mode & FMODE_WRITE))) + break; +- ret = security_file_permission(file, MAY_WRITE); +- if (unlikely(ret)) +- break; + ret = aio_setup_vectored_rw(WRITE, kiocb, compat); + if (ret) + break; +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2012-6703.1.patch b/patches/3.10/CVE-2012-6703.1.patch new file mode 100644 index 0000000..23ff01c --- /dev/null +++ b/patches/3.10/CVE-2012-6703.1.patch @@ -0,0 +1,31 @@ +From b35cc8225845112a616e3a2266d2fde5ab13d3ab Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 5 Sep 2012 15:32:18 +0300 +Subject: [PATCH] ALSA: compress_core: integer overflow in + snd_compr_allocate_buffer() + +These are 32 bit values that come from the user, we need to check for +integer overflows or we could end up allocating a smaller buffer than +expected. + +Signed-off-by: Dan Carpenter +Signed-off-by: Takashi Iwai +--- + sound/core/compress_offload.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c +index eb60cb8dbb8a6..68fe02c7400a2 100644 +--- a/sound/core/compress_offload.c ++++ b/sound/core/compress_offload.c +@@ -407,6 +407,10 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream, + unsigned int buffer_size; + void *buffer; + ++ if (params->buffer.fragment_size == 0 || ++ params->buffer.fragments > SIZE_MAX / params->buffer.fragment_size) ++ return -EINVAL; ++ + buffer_size = params->buffer.fragment_size * params->buffer.fragments; + if (stream->ops->copy) { + buffer = NULL; \ No newline at end of file diff --git a/patches/3.10/CVE-2012-6703.2.patch b/patches/3.10/CVE-2012-6703.2.patch new file mode 100644 index 0000000..07b5d6b --- /dev/null +++ b/patches/3.10/CVE-2012-6703.2.patch @@ -0,0 +1,66 @@ +From 4dc040a0b34890d2adc0d63da6e9bfb4eb791b19 Mon Sep 17 00:00:00 2001 +From: Vinod Koul +Date: Mon, 17 Sep 2012 11:51:25 +0530 +Subject: [PATCH] ALSA: compress - move the buffer check + +Commit ALSA: compress_core: integer overflow in snd_compr_allocate_buffer() +added a new error check for input params. +this add new routine for input checks and moves buffer overflow check to this +new routine. This allows the error value to be propogated to user space + +Signed-off-by: Vinod Koul +Signed-off-by: Takashi Iwai +--- + sound/core/compress_offload.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c +index 68fe02c7400a2..bd7f28e892540 100644 +--- a/sound/core/compress_offload.c ++++ b/sound/core/compress_offload.c +@@ -407,10 +407,6 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream, + unsigned int buffer_size; + void *buffer; + +- if (params->buffer.fragment_size == 0 || +- params->buffer.fragments > SIZE_MAX / params->buffer.fragment_size) +- return -EINVAL; +- + buffer_size = params->buffer.fragment_size * params->buffer.fragments; + if (stream->ops->copy) { + buffer = NULL; +@@ -429,6 +425,16 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream, + return 0; + } + ++static int snd_compress_check_input(struct snd_compr_params *params) ++{ ++ /* first let's check the buffer parameter's */ ++ if (params->buffer.fragment_size == 0 || ++ params->buffer.fragments > SIZE_MAX / params->buffer.fragment_size) ++ return -EINVAL; ++ ++ return 0; ++} ++ + static int + snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg) + { +@@ -447,11 +453,17 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg) + retval = -EFAULT; + goto out; + } ++ ++ retval = snd_compress_check_input(params); ++ if (retval) ++ goto out; ++ + retval = snd_compr_allocate_buffer(stream, params); + if (retval) { + retval = -ENOMEM; + goto out; + } ++ + retval = stream->ops->set_params(stream, params); + if (retval) + goto out; \ No newline at end of file diff --git a/patches/3.10/CVE-2014-9869.1.patch b/patches/3.10/CVE-2014-9869.1.patch new file mode 100644 index 0000000..500c268 --- /dev/null +++ b/patches/3.10/CVE-2014-9869.1.patch @@ -0,0 +1,73 @@ +From 8d1f7531ff379befc129a6447642061e87562bca Mon Sep 17 00:00:00 2001 +From: Hariram Purushothaman +Date: Tue, 23 Jul 2013 15:39:09 -0700 +Subject: msm: camera: Check stats index MAX in ISP driver + +Add a check for the stats index MAX using +MSM_ISP_STATS_MAX before accessing stream info +using that index to avoid any invalid memory access. + +Change-Id: Iaade2af5d0e3e073e9519961a0f84a93038284bf +CRs-Fixed: 514711 +Signed-off-by: Hariram Purushothaman +--- + .../msm/camera_v2/isp/msm_isp_stats_util.c | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c +index d857a14..33f63b3 100644 +--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c ++++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c +@@ -150,6 +150,12 @@ int msm_isp_stats_create_stream(struct vfe_device *vfe_dev, + stats_idx = vfe_dev->hw_info->vfe_ops.stats_ops. + get_stats_idx(stream_req_cmd->stats_type); + ++ if ((stats_idx > MSM_ISP_STATS_MAX) || ++ (stats_idx == -EINVAL)) { ++ pr_err("%s: Stats idx Error\n", __func__); ++ return rc; ++ } ++ + stream_info = &stats_data->stream_info[stats_idx]; + if (stream_info->state != STATS_AVALIABLE) { + pr_err("%s: Stats already requested\n", __func__); +@@ -188,7 +194,7 @@ int msm_isp_stats_create_stream(struct vfe_device *vfe_dev, + + int msm_isp_request_stats_stream(struct vfe_device *vfe_dev, void *arg) + { +- int rc = 0; ++ int rc = -1; + struct msm_vfe_stats_stream_request_cmd *stream_req_cmd = arg; + struct msm_vfe_stats_stream *stream_info = NULL; + struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data; +@@ -202,6 +208,11 @@ int msm_isp_request_stats_stream(struct vfe_device *vfe_dev, void *arg) + } + + stats_idx = STATS_IDX(stream_req_cmd->stream_handle); ++ if (stats_idx > MSM_ISP_STATS_MAX) { ++ pr_err("%s: Stats idx Error\n", __func__); ++ return rc; ++ } ++ + stream_info = &stats_data->stream_info[stats_idx]; + + framedrop_period = msm_isp_get_framedrop_period( +@@ -228,9 +239,14 @@ int msm_isp_release_stats_stream(struct vfe_device *vfe_dev, void *arg) + struct msm_vfe_stats_stream_release_cmd *stream_release_cmd = arg; + struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data; + int stats_idx = STATS_IDX(stream_release_cmd->stream_handle); +- struct msm_vfe_stats_stream *stream_info = +- &stats_data->stream_info[stats_idx]; ++ struct msm_vfe_stats_stream *stream_info = NULL; ++ ++ if (stats_idx > MSM_ISP_STATS_MAX) { ++ pr_err("%s: Stats idx Error\n", __func__); ++ return rc; ++ } + ++ stream_info = &stats_data->stream_info[stats_idx]; + if (stream_info->state == STATS_AVALIABLE) { + pr_err("%s: stream already release\n", __func__); + return rc; +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9869.2.patch b/patches/3.10/CVE-2014-9869.2.patch new file mode 100644 index 0000000..5385d5c --- /dev/null +++ b/patches/3.10/CVE-2014-9869.2.patch @@ -0,0 +1,144 @@ +From 7a26934e4196b4aa61944081989189d59b108768 Mon Sep 17 00:00:00 2001 +From: Petar Sivenov +Date: Tue, 13 Aug 2013 10:12:39 -0700 +Subject: msm: camera: isp: Bound check for number stats registers + +The index of used stats register is derived from a stream handle least +significant byte and thus can be up to 255. However the stats registers +are up to 8 depending of the target. Thus a bound check is done before +use of the received stats register index value. + +Change-Id: Ic008918f4263f57a5b8aabd34266ac1ba3612a9c +Signed-off-by: Petar Sivenov +--- + .../msm/camera_v2/isp/msm_isp_stats_util.c | 50 ++++++++++++++++------ + .../platform/msm/camera_v2/isp/msm_isp_util.c | 4 +- + 2 files changed, 41 insertions(+), 13 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c +index 0840e30..b479857 100644 +--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c ++++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c +@@ -23,8 +23,16 @@ static int msm_isp_stats_cfg_ping_pong_address(struct vfe_device *vfe_dev, + struct msm_isp_buffer *buf; + uint32_t pingpong_bit = 0; + uint32_t bufq_handle = stream_info->bufq_handle; +- uint32_t stats_pingpong_offset = +- STATS_IDX(stream_info->stream_handle) + ++ uint32_t stats_pingpong_offset; ++ ++ if (STATS_IDX(stream_info->stream_handle) >= ++ vfe_dev->hw_info->stats_hw_info->num_stats_type) { ++ pr_err("%s Invalid stats index %d", __func__, ++ STATS_IDX(stream_info->stream_handle)); ++ return -EINVAL; ++ } ++ ++ stats_pingpong_offset = STATS_IDX(stream_info->stream_handle) + + vfe_dev->hw_info->stats_hw_info->stats_ping_pong_offset; + + pingpong_bit = (~(pingpong_status >> stats_pingpong_offset) & 0x1); +@@ -151,10 +159,9 @@ int msm_isp_stats_create_stream(struct vfe_device *vfe_dev, + stats_idx = vfe_dev->hw_info->vfe_ops.stats_ops. + get_stats_idx(stream_req_cmd->stats_type); + +- if ((stats_idx > MSM_ISP_STATS_MAX) || +- (stats_idx == -EINVAL)) { +- pr_err("%s: Stats idx Error\n", __func__); +- return rc; ++ if (stats_idx >= vfe_dev->hw_info->stats_hw_info->num_stats_type) { ++ pr_err("%s Invalid stats index %d", __func__, stats_idx); ++ return -EINVAL; + } + + stream_info = &stats_data->stream_info[stats_idx]; +@@ -209,9 +216,10 @@ int msm_isp_request_stats_stream(struct vfe_device *vfe_dev, void *arg) + } + + stats_idx = STATS_IDX(stream_req_cmd->stream_handle); +- if (stats_idx > MSM_ISP_STATS_MAX) { +- pr_err("%s: Stats idx Error\n", __func__); +- return rc; ++ ++ if (stats_idx >= vfe_dev->hw_info->stats_hw_info->num_stats_type) { ++ pr_err("%s Invalid stats index %d", __func__, stats_idx); ++ return -EINVAL; + } + + stream_info = &stats_data->stream_info[stats_idx]; +@@ -242,9 +250,9 @@ int msm_isp_release_stats_stream(struct vfe_device *vfe_dev, void *arg) + int stats_idx = STATS_IDX(stream_release_cmd->stream_handle); + struct msm_vfe_stats_stream *stream_info = NULL; + +- if (stats_idx > MSM_ISP_STATS_MAX) { +- pr_err("%s: Stats idx Error\n", __func__); +- return rc; ++ if (stats_idx >= vfe_dev->hw_info->stats_hw_info->num_stats_type) { ++ pr_err("%s Invalid stats index %d", __func__, stats_idx); ++ return -EINVAL; + } + + stream_info = &stats_data->stream_info[stats_idx]; +@@ -379,6 +387,12 @@ static int msm_isp_start_stats_stream(struct vfe_device *vfe_dev, + struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data; + for (i = 0; i < stream_cfg_cmd->num_streams; i++) { + idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]); ++ ++ if (idx >= vfe_dev->hw_info->stats_hw_info->num_stats_type) { ++ pr_err("%s Invalid stats index %d", __func__, idx); ++ return -EINVAL; ++ } ++ + stream_info = &stats_data->stream_info[idx]; + if (stream_info->stream_handle != + stream_cfg_cmd->stream_handle[i]) { +@@ -423,6 +437,12 @@ static int msm_isp_stop_stats_stream(struct vfe_device *vfe_dev, + struct msm_vfe_stats_shared_data *stats_data = &vfe_dev->stats_data; + for (i = 0; i < stream_cfg_cmd->num_streams; i++) { + idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]); ++ ++ if (idx >= vfe_dev->hw_info->stats_hw_info->num_stats_type) { ++ pr_err("%s Invalid stats index %d", __func__, idx); ++ return -EINVAL; ++ } ++ + stream_info = &stats_data->stream_info[idx]; + if (stream_info->stream_handle != + stream_cfg_cmd->stream_handle[i]) { +@@ -453,6 +473,12 @@ static int msm_isp_stop_stats_stream(struct vfe_device *vfe_dev, + + for (i = 0; i < stream_cfg_cmd->num_streams; i++) { + idx = STATS_IDX(stream_cfg_cmd->stream_handle[i]); ++ ++ if (idx >= vfe_dev->hw_info->stats_hw_info->num_stats_type) { ++ pr_err("%s Invalid stats index %d", __func__, idx); ++ return -EINVAL; ++ } ++ + stream_info = &stats_data->stream_info[idx]; + msm_isp_deinit_stats_ping_pong_reg(vfe_dev, stream_info); + } +diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +index fcdf34e..6dba4153 100644 +--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c ++++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +@@ -768,6 +768,8 @@ void msm_isp_update_error_frame_count(struct vfe_device *vfe_dev) + void msm_isp_process_error_info(struct vfe_device *vfe_dev) + { + int i; ++ uint8_t num_stats_type = ++ vfe_dev->hw_info->stats_hw_info->num_stats_type; + struct msm_vfe_error_info *error_info = &vfe_dev->error_info; + static DEFINE_RATELIMIT_STATE(rs, + DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST); +@@ -791,7 +793,7 @@ void msm_isp_process_error_info(struct vfe_device *vfe_dev) + error_info->stream_framedrop_count[i] = 0; + } + } +- for (i = 0; i < MSM_ISP_STATS_MAX; i++) { ++ for (i = 0; i < num_stats_type; i++) { + if (error_info->stats_framedrop_count[i] != 0 && + __ratelimit(&rs_stats)) { + pr_err("%s: Stats stream[%d]: dropped %d frames\n", +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9870.patch b/patches/3.10/CVE-2014-9870.patch new file mode 100644 index 0000000..396288f --- /dev/null +++ b/patches/3.10/CVE-2014-9870.patch @@ -0,0 +1,215 @@ +From 4f57652fcd2dce7741f1ac6dc0417e2f265cd1de Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Andr=C3=A9=20Hentschel?= +Date: Tue, 18 Jun 2013 23:23:26 +0100 +Subject: ARM: 7735/2: Preserve the user r/w register TPIDRURW on context + switch and fork +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since commit 6a1c53124aa1 the user writeable TLS register was zeroed to +prevent it from being used as a covert channel between two tasks. + +There are more and more applications coming to Windows RT, +Wine could support them, but mostly they expect to have +the thread environment block (TEB) in TPIDRURW. + +This patch preserves that register per thread instead of clearing it. +Unlike the TPIDRURO, which is already switched, the TPIDRURW +can be updated from userspace so needs careful treatment in the case that we +modify TPIDRURW and call fork(). To avoid this we must always read +TPIDRURW in copy_thread. + +Change-Id: Ib1e25be7b9faa846ba5335aad2574e21a1246066 +Signed-off-by: André Hentschel +Signed-off-by: Will Deacon +Signed-off-by: Jonathan Austin +Signed-off-by: Russell King +Git-commit: a4780adeefd042482f624f5e0d577bf9cdcbb760 +Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git +[joonwoop@codeaurora.org: fixed merge conflict] +CRs-fixed: 561044 +Signed-off-by: Joonwoo Park +--- + arch/arm/include/asm/thread_info.h | 2 +- + arch/arm/include/asm/tls.h | 40 +++++++++++++++++++++++++------------- + arch/arm/kernel/entry-armv.S | 5 +++-- + arch/arm/kernel/process.c | 4 +++- + arch/arm/kernel/ptrace.c | 2 +- + arch/arm/kernel/traps.c | 4 ++-- + 6 files changed, 37 insertions(+), 20 deletions(-) + +diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h +index 67d6443..2eb0c2c 100644 +--- a/arch/arm/include/asm/thread_info.h ++++ b/arch/arm/include/asm/thread_info.h +@@ -58,7 +58,7 @@ struct thread_info { + struct cpu_context_save cpu_context; /* cpu context */ + __u32 syscall; /* syscall number */ + __u8 used_cp[16]; /* thread used copro */ +- unsigned long tp_value; ++ unsigned long tp_value[2]; /* TLS registers */ + struct crunch_state crunchstate; + union fp_state fpstate __attribute__((aligned(8))); + union vfp_state vfpstate; +diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h +index 73409e6..83259b8 100644 +--- a/arch/arm/include/asm/tls.h ++++ b/arch/arm/include/asm/tls.h +@@ -2,27 +2,30 @@ + #define __ASMARM_TLS_H + + #ifdef __ASSEMBLY__ +- .macro set_tls_none, tp, tmp1, tmp2 ++#include ++ .macro switch_tls_none, base, tp, tpuser, tmp1, tmp2 + .endm + +- .macro set_tls_v6k, tp, tmp1, tmp2 ++ .macro switch_tls_v6k, base, tp, tpuser, tmp1, tmp2 ++ mrc p15, 0, \tmp2, c13, c0, 2 @ get the user r/w register + mcr p15, 0, \tp, c13, c0, 3 @ set TLS register +- mov \tmp1, #0 +- mcr p15, 0, \tmp1, c13, c0, 2 @ clear user r/w TLS register ++ mcr p15, 0, \tpuser, c13, c0, 2 @ and the user r/w register ++ str \tmp2, [\base, #TI_TP_VALUE + 4] @ save it + .endm + +- .macro set_tls_v6, tp, tmp1, tmp2 ++ .macro switch_tls_v6, base, tp, tpuser, tmp1, tmp2 + ldr \tmp1, =elf_hwcap + ldr \tmp1, [\tmp1, #0] + mov \tmp2, #0xffff0fff + tst \tmp1, #HWCAP_TLS @ hardware TLS available? +- mcrne p15, 0, \tp, c13, c0, 3 @ yes, set TLS register +- movne \tmp1, #0 +- mcrne p15, 0, \tmp1, c13, c0, 2 @ clear user r/w TLS register + streq \tp, [\tmp2, #-15] @ set TLS value at 0xffff0ff0 ++ mrcne p15, 0, \tmp2, c13, c0, 2 @ get the user r/w register ++ mcrne p15, 0, \tp, c13, c0, 3 @ yes, set TLS register ++ mcrne p15, 0, \tpuser, c13, c0, 2 @ set user r/w register ++ strne \tmp2, [\base, #TI_TP_VALUE + 4] @ save it + .endm + +- .macro set_tls_software, tp, tmp1, tmp2 ++ .macro switch_tls_software, base, tp, tpuser, tmp1, tmp2 + mov \tmp1, #0xffff0fff + str \tp, [\tmp1, #-15] @ set TLS value at 0xffff0ff0 + .endm +@@ -31,19 +34,30 @@ + #ifdef CONFIG_TLS_REG_EMUL + #define tls_emu 1 + #define has_tls_reg 1 +-#define set_tls set_tls_none ++#define switch_tls switch_tls_none + #elif defined(CONFIG_CPU_V6) + #define tls_emu 0 + #define has_tls_reg (elf_hwcap & HWCAP_TLS) +-#define set_tls set_tls_v6 ++#define switch_tls switch_tls_v6 + #elif defined(CONFIG_CPU_32v6K) + #define tls_emu 0 + #define has_tls_reg 1 +-#define set_tls set_tls_v6k ++#define switch_tls switch_tls_v6k + #else + #define tls_emu 0 + #define has_tls_reg 0 +-#define set_tls set_tls_software ++#define switch_tls switch_tls_software + #endif + ++#ifndef __ASSEMBLY__ ++static inline unsigned long get_tpuser(void) ++{ ++ unsigned long reg = 0; ++ ++ if (has_tls_reg && !tls_emu) ++ __asm__("mrc p15, 0, %0, c13, c0, 2" : "=r" (reg)); ++ ++ return reg; ++} ++#endif + #endif /* __ASMARM_TLS_H */ +diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S +index 7a8c2d6..0bdba55 100644 +--- a/arch/arm/kernel/entry-armv.S ++++ b/arch/arm/kernel/entry-armv.S +@@ -698,15 +698,16 @@ ENTRY(__switch_to) + UNWIND(.fnstart ) + UNWIND(.cantunwind ) + add ip, r1, #TI_CPU_SAVE +- ldr r3, [r2, #TI_TP_VALUE] + ARM( stmia ip!, {r4 - sl, fp, sp, lr} ) @ Store most regs on stack + THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack + THUMB( str sp, [ip], #4 ) + THUMB( str lr, [ip], #4 ) ++ ldr r4, [r2, #TI_TP_VALUE] ++ ldr r5, [r2, #TI_TP_VALUE + 4] + #ifdef CONFIG_CPU_USE_DOMAINS + ldr r6, [r2, #TI_CPU_DOMAIN] + #endif +- set_tls r3, r4, r5 ++ switch_tls r1, r4, r5, r3, r7 + #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) + ldr r7, [r2, #TI_TASK] + ldr r8, =__stack_chk_guard +diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c +index 0ff45bd..18e92f6 100644 +--- a/arch/arm/kernel/process.c ++++ b/arch/arm/kernel/process.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + #ifdef CONFIG_CC_STACKPROTECTOR + #include +@@ -558,7 +559,8 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start, + clear_ptrace_hw_breakpoint(p); + + if (clone_flags & CLONE_SETTLS) +- thread->tp_value = regs->ARM_r3; ++ thread->tp_value[0] = childregs->ARM_r3; ++ thread->tp_value[1] = get_tpuser(); + + thread_notify(THREAD_NOTIFY_COPY, thread); + +diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c +index 9650c14..c6c6be7 100644 +--- a/arch/arm/kernel/ptrace.c ++++ b/arch/arm/kernel/ptrace.c +@@ -844,7 +844,7 @@ long arch_ptrace(struct task_struct *child, long request, + #endif + + case PTRACE_GET_THREAD_AREA: +- ret = put_user(task_thread_info(child)->tp_value, ++ ret = put_user(task_thread_info(child)->tp_value[0], + datap); + break; + +diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c +index 12e6fcb..e0a066b 100644 +--- a/arch/arm/kernel/traps.c ++++ b/arch/arm/kernel/traps.c +@@ -593,7 +593,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs) + return regs->ARM_r0; + + case NR(set_tls): +- thread->tp_value = regs->ARM_r0; ++ thread->tp_value[0] = regs->ARM_r0; + if (tls_emu) + return 0; + if (has_tls_reg) { +@@ -711,7 +711,7 @@ static int get_tp_trap(struct pt_regs *regs, unsigned int instr) + int reg = (instr >> 12) & 15; + if (reg == 15) + return 1; +- regs->uregs[reg] = current_thread_info()->tp_value; ++ regs->uregs[reg] = current_thread_info()->tp_value[0]; + regs->ARM_pc += 4; + return 0; + } +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9871.patch b/patches/3.10/CVE-2014-9871.patch new file mode 100644 index 0000000..29f9f8c --- /dev/null +++ b/patches/3.10/CVE-2014-9871.patch @@ -0,0 +1,145 @@ +From f615e40c706708f74cd826d5b19c63025f54c041 Mon Sep 17 00:00:00 2001 +From: Seemanta Dutta +Date: Tue, 23 Jul 2013 15:52:22 -0700 +Subject: msm: camera: Fix potential memory overflow errors + +Fix potential memory overflow errors in msm_isp_util.c which happen +under certain rare conditions. + +CRs-fixed: 514717 +Change-Id: I8c70e089df9bf1e7a364c5c8264b782c9c23bf0b +Signed-off-by: Seemanta Dutta +--- + .../platform/msm/camera_v2/isp/msm_isp_util.c | 47 +++++++++++++++++++--- + .../platform/msm/camera_v2/isp/msm_isp_util.h | 2 +- + 2 files changed, 43 insertions(+), 6 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +index 3806213..9b9c5a3 100644 +--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c ++++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +@@ -366,7 +366,7 @@ long msm_isp_ioctl(struct v4l2_subdev *sd, + break; + case VIDIOC_MSM_ISP_SET_SRC_STATE: + mutex_lock(&vfe_dev->core_mutex); +- msm_isp_set_src_state(vfe_dev, arg); ++ rc = msm_isp_set_src_state(vfe_dev, arg); + mutex_unlock(&vfe_dev->core_mutex); + break; + case VIDIOC_MSM_ISP_REQUEST_STATS_STREAM: +@@ -410,7 +410,7 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, + if (resource_size(vfe_dev->vfe_mem) < + (reg_cfg_cmd->u.rw_info.reg_offset + + reg_cfg_cmd->u.rw_info.len)) { +- pr_err("%s: Invalid length\n", __func__); ++ pr_err("%s: VFE_WRITE: Invalid length\n", __func__); + return -EINVAL; + } + msm_camera_io_memcpy(vfe_dev->vfe_base + +@@ -422,16 +422,37 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, + case VFE_WRITE_MB: { + uint32_t *data_ptr = cfg_data + + reg_cfg_cmd->u.rw_info.cmd_data_offset/4; ++ ++ if ((UINT_MAX - sizeof(*data_ptr) < ++ reg_cfg_cmd->u.rw_info.reg_offset) || ++ (resource_size(vfe_dev->vfe_mem) < ++ reg_cfg_cmd->u.rw_info.reg_offset + ++ sizeof(*data_ptr))) { ++ pr_err("%s: VFE_WRITE_MB: Invalid length\n", __func__); ++ return -EINVAL; ++ } + msm_camera_io_w_mb(*data_ptr, vfe_dev->vfe_base + + reg_cfg_cmd->u.rw_info.reg_offset); + break; + } + case VFE_CFG_MASK: { + uint32_t temp; ++ if (resource_size(vfe_dev->vfe_mem) < ++ reg_cfg_cmd->u.mask_info.reg_offset) ++ return -EINVAL; + temp = msm_camera_io_r(vfe_dev->vfe_base + + reg_cfg_cmd->u.mask_info.reg_offset); ++ + temp &= ~reg_cfg_cmd->u.mask_info.mask; + temp |= reg_cfg_cmd->u.mask_info.val; ++ if ((UINT_MAX - sizeof(temp) < ++ reg_cfg_cmd->u.mask_info.reg_offset) || ++ (resource_size(vfe_dev->vfe_mem) < ++ reg_cfg_cmd->u.mask_info.reg_offset + ++ sizeof(temp))) { ++ pr_err("%s: VFE_CFG_MASK: Invalid length\n", __func__); ++ return -EINVAL; ++ } + msm_camera_io_w(temp, vfe_dev->vfe_base + + reg_cfg_cmd->u.mask_info.reg_offset); + break; +@@ -443,8 +464,10 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, + uint32_t *hi_tbl_ptr = NULL, *lo_tbl_ptr = NULL; + uint32_t hi_val, lo_val, lo_val1; + if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) { +- if (reg_cfg_cmd->u.dmi_info.hi_tbl_offset + +- reg_cfg_cmd->u.dmi_info.len > cmd_len) { ++ if ((UINT_MAX - reg_cfg_cmd->u.dmi_info.hi_tbl_offset < ++ reg_cfg_cmd->u.dmi_info.len) || ++ (reg_cfg_cmd->u.dmi_info.hi_tbl_offset + ++ reg_cfg_cmd->u.dmi_info.len > cmd_len)) { + pr_err("Invalid Hi Table out of bounds\n"); + return -EINVAL; + } +@@ -528,6 +551,12 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, + uint32_t *data_ptr = cfg_data + + reg_cfg_cmd->u.rw_info.cmd_data_offset/4; + for (i = 0; i < reg_cfg_cmd->u.rw_info.len/4; i++) { ++ if ((data_ptr < cfg_data) || ++ (UINT_MAX / sizeof(*data_ptr) < ++ (data_ptr - cfg_data)) || ++ (sizeof(*data_ptr) * (data_ptr - cfg_data) > ++ cmd_len)) ++ return -EINVAL; + *data_ptr++ = msm_camera_io_r(vfe_dev->vfe_base + + reg_cfg_cmd->u.rw_info.reg_offset); + reg_cfg_cmd->u.rw_info.reg_offset += 4; +@@ -545,6 +574,11 @@ int msm_isp_proc_cmd(struct vfe_device *vfe_dev, void *arg) + struct msm_vfe_reg_cfg_cmd *reg_cfg_cmd; + uint32_t *cfg_data; + ++ if (!proc_cmd->num_cfg) { ++ pr_err("%s: Passed num_cfg as 0\n", __func__); ++ return -EINVAL; ++ } ++ + reg_cfg_cmd = kzalloc(sizeof(struct msm_vfe_reg_cfg_cmd)* + proc_cmd->num_cfg, GFP_KERNEL); + if (!reg_cfg_cmd) { +@@ -856,11 +890,14 @@ void msm_isp_do_tasklet(unsigned long data) + } + } + +-void msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg) ++int msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg) + { + struct msm_vfe_axi_src_state *src_state = arg; ++ if (src_state->input_src >= VFE_SRC_MAX) ++ return -EINVAL; + vfe_dev->axi_data.src_info[src_state->input_src].active = + src_state->src_active; ++ return 0; + } + + int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) +diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h +index 34b9859..9d9558a 100644 +--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h ++++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h +@@ -64,7 +64,7 @@ int msm_isp_cal_word_per_line(uint32_t output_format, + uint32_t pixel_per_line); + int msm_isp_get_bit_per_pixel(uint32_t output_format); + irqreturn_t msm_isp_process_irq(int irq_num, void *data); +-void msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg); ++int msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg); + void msm_isp_do_tasklet(unsigned long data); + void msm_isp_update_error_frame_count(struct vfe_device *vfe_dev); + void msm_isp_process_error_info(struct vfe_device *vfe_dev); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9872.patch b/patches/3.10/CVE-2014-9872.patch new file mode 100644 index 0000000..859bb93 --- /dev/null +++ b/patches/3.10/CVE-2014-9872.patch @@ -0,0 +1,98 @@ +From fc787ebd71fa231cc7dd2a0d5f2208da0527096a Mon Sep 17 00:00:00 2001 +From: Katish Paran +Date: Fri, 31 Jan 2014 12:00:37 +0530 +Subject: diag: dci: Index DCI client table by client id + +Diag driver maintains a table of all DCI clients. This table +is currently indexed by the PID of the clients. Make changes +to index the table base on an unique client id. + +Change-Id: I57bfab9eae1381882b8eb6270d7ac212e0aaf271 +CRs-fixed: 590721 +Signed-off-by: Katish Paran +--- + drivers/char/diag/diag_dci.c | 16 ++++++++++++++++ + drivers/char/diag/diag_dci.h | 4 ++++ + drivers/char/diag/diagchar_core.c | 4 +++- + 3 files changed, 23 insertions(+), 1 deletion(-) + +diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c +index 37c236d..0edfdad 100644 +--- a/drivers/char/diag/diag_dci.c ++++ b/drivers/char/diag/diag_dci.c +@@ -847,6 +847,22 @@ int diag_process_dci_transaction(unsigned char *buf, int len) + return ret; + } + ++int diag_dci_find_client_index_health(int client_id) ++{ ++ int i, ret = DCI_CLIENT_INDEX_INVALID; ++ ++ for (i = 0; i < MAX_DCI_CLIENTS; i++) { ++ if (driver->dci_client_tbl[i].client != NULL) { ++ if (driver->dci_client_tbl[i].client_id == ++ client_id) { ++ ret = i; ++ break; ++ } ++ } ++ } ++ return ret; ++} ++ + int diag_dci_find_client_index(int client_id) + { + int i, ret = DCI_CLIENT_INDEX_INVALID; +diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h +index 2ab8a36..870b0f3 100644 +--- a/drivers/char/diag/diag_dci.h ++++ b/drivers/char/diag/diag_dci.h +@@ -56,6 +56,7 @@ struct dci_pkt_req_entry_t { + } __packed; + + struct diag_dci_client_tbl { ++ uint32_t client_id; + struct task_struct *client; + uint16_t list; /* bit mask */ + int signal_type; +@@ -74,6 +75,7 @@ struct diag_dci_client_tbl { + + /* This is used for DCI health stats */ + struct diag_dci_health_stats { ++ int client_id; + int dropped_logs; + int dropped_events; + int received_logs; +@@ -119,6 +121,8 @@ int diag_process_smd_dci_read_data(struct diag_smd_info *smd_info, void *buf, + int recd_bytes); + int diag_process_dci_transaction(unsigned char *buf, int len); + void extract_dci_pkt_rsp(struct diag_smd_info *smd_info, unsigned char *buf); ++ ++int diag_dci_find_client_index_health(int client_id); + int diag_dci_find_client_index(int client_id); + /* DCI Log streaming functions */ + void create_dci_log_mask_tbl(unsigned char *tbl_buf); +diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c +index 9a4e108..0e475c9 100644 +--- a/drivers/char/diag/diagchar_core.c ++++ b/drivers/char/diag/diagchar_core.c +@@ -943,6 +943,8 @@ long diagchar_ioctl(struct file *filp, + for (i = 0; i < MAX_DCI_CLIENTS; i++) { + if (driver->dci_client_tbl[i].client == NULL) { + driver->dci_client_tbl[i].client = current; ++ driver->dci_client_tbl[i].client_id = ++ driver->dci_client_id; + driver->dci_client_tbl[i].list = + dci_params->list; + driver->dci_client_tbl[i].signal_type = +@@ -1043,7 +1045,7 @@ long diagchar_ioctl(struct file *filp, + sizeof(struct diag_dci_health_stats))) + return -EFAULT; + mutex_lock(&dci_health_mutex); +- i = diag_dci_find_client_index(current->tgid); ++ i = diag_dci_find_client_index_health(stats.client_id); + if (i != DCI_CLIENT_INDEX_INVALID) { + dci_params = &(driver->dci_client_tbl[i]); + stats.dropped_logs = dci_params->dropped_logs; +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9873.patch b/patches/3.10/CVE-2014-9873.patch new file mode 100644 index 0000000..3e65e60 --- /dev/null +++ b/patches/3.10/CVE-2014-9873.patch @@ -0,0 +1,34 @@ +From ef29ae1d40536fef7fb95e4d5bb5b6b57bdf9420 Mon Sep 17 00:00:00 2001 +From: Katish Paran +Date: Tue, 17 Dec 2013 13:36:15 +0530 +Subject: diag: dci: Safeguard to prevent Integer Underflow and Memory Leak + +At certain point in diag driver there can be integer underflow +thus can lead to memory leak. Added a safeguard for that. + +Change-Id: I2a0304f5b9888fe12ca9ef5fbaa9a68ee4ab9c15 +Crs-fixed: 556860 +Signed-off-by: Katish Paran +--- + drivers/char/diag/diag_dci.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c +index 7772ebe..414207f 100644 +--- a/drivers/char/diag/diag_dci.c ++++ b/drivers/char/diag/diag_dci.c +@@ -216,7 +216,11 @@ void extract_dci_pkt_rsp(struct diag_smd_info *smd_info, unsigned char *buf) + if (recv_pkt_cmd_code != DCI_PKT_RSP_CODE) + cmd_code_len = 4; /* delayed response */ + write_len = (int)(*(uint16_t *)(buf+2)) - cmd_code_len; +- ++ if (write_len <= 0) { ++ pr_err("diag: Invalid length in %s, write_len: %d", ++ __func__, write_len); ++ return; ++ } + pr_debug("diag: len = %d\n", write_len); + tag = (int *)(buf + (4 + cmd_code_len)); /* Retrieve the Tag field */ + req_entry = diag_dci_get_request_entry(*tag); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9874.patch b/patches/3.10/CVE-2014-9874.patch new file mode 100644 index 0000000..660443c --- /dev/null +++ b/patches/3.10/CVE-2014-9874.patch @@ -0,0 +1,63 @@ +From 56ff68b1f93eaf22e5e0284648fd862dc08c9236 Mon Sep 17 00:00:00 2001 +From: Mohammad Johny Shaik +Date: Thu, 12 Dec 2013 14:26:42 +0530 +Subject: Asoc:msm:Added Buffer overflow check + +The overflow check is required to ensure that user space data +in kernel may not go beyond buffer boundary. + +Change-Id: I79b7e5f875fadcaeceb05f9163ae3666d4b6b7e1 +CRs-Fixed: 563086 +Signed-off-by: Mohammad Johny Shaik +--- + arch/arm/mach-msm/qdsp6v2/audio_utils.c | 6 ++++++ + sound/soc/msm/qdsp6v2/q6asm.c | 3 +++ + 2 files changed, 9 insertions(+) + +diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils.c b/arch/arm/mach-msm/qdsp6v2/audio_utils.c +index 2a245f8..b8e55f9 100644 +--- a/arch/arm/mach-msm/qdsp6v2/audio_utils.c ++++ b/arch/arm/mach-msm/qdsp6v2/audio_utils.c +@@ -23,6 +23,7 @@ + #include + #include "audio_utils.h" + ++#define FRAME_SIZE (1 + ((1536+sizeof(struct meta_out_dsp)) * 5)) + static int audio_in_pause(struct q6audio_in *audio) + { + int rc; +@@ -258,6 +259,11 @@ long audio_in_ioctl(struct file *file, + rc = -EINVAL; + break; + } ++ if ((cfg.buffer_size > FRAME_SIZE) || ++ (cfg.buffer_count != FRAME_NUM)) { ++ rc = -EINVAL; ++ break; ++ } + audio->str_cfg.buffer_size = cfg.buffer_size; + audio->str_cfg.buffer_count = cfg.buffer_count; + rc = q6asm_audio_client_buf_alloc(OUT, audio->ac, +diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c +index 82b92aa9..09c40d6 100644 +--- a/sound/soc/msm/qdsp6v2/q6asm.c ++++ b/sound/soc/msm/qdsp6v2/q6asm.c +@@ -55,6 +55,7 @@ + #define READDONE_IDX_FLAGS 8 + #define READDONE_IDX_NUMFRAMES 9 + #define READDONE_IDX_SEQ_ID 10 ++#define FRAME_NUM (8) + + /* TODO, combine them together */ + static DEFINE_MUTEX(session_lock); +@@ -608,6 +609,8 @@ int q6asm_audio_client_buf_alloc(unsigned int dir, + pr_debug("%s: buffer already allocated\n", __func__); + return 0; + } ++ if (bufcnt != FRAME_NUM) ++ goto fail; + mutex_lock(&ac->cmd_lock); + buf = kzalloc(((sizeof(struct audio_buffer))*bufcnt), + GFP_KERNEL); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9875.patch b/patches/3.10/CVE-2014-9875.patch new file mode 100644 index 0000000..febc226 --- /dev/null +++ b/patches/3.10/CVE-2014-9875.patch @@ -0,0 +1,245 @@ +From b77c694b88a994d077316c157168c710696f8805 Mon Sep 17 00:00:00 2001 +From: Ravi Aravamudhan +Date: Tue, 4 Jun 2013 10:10:11 -0700 +Subject: diag: dci: Check for request pkt length being lesser than minimum + length + +Added checks for DCI request packets to be greater than the minimum +packet length. We would drop the request and print an error otherwise. + +CRs-Fixed: 483310 +Change-Id: I0d89ded58ee97a08ebe6b06b411ac17d2fcb11df +Signed-off-by: Ravi Aravamudhan +--- + drivers/char/diag/diag_dci.c | 114 ++++++++++++++++++++++++++++++++++--------- + drivers/char/diag/diag_dci.h | 3 ++ + 2 files changed, 93 insertions(+), 24 deletions(-) + +diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c +index 9b404c6..fa0e9d7 100644 +--- a/drivers/char/diag/diag_dci.c ++++ b/drivers/char/diag/diag_dci.c +@@ -375,16 +375,23 @@ void diag_dci_notify_client(int peripheral_mask, int data) + int diag_send_dci_pkt(struct diag_master_table entry, unsigned char *buf, + int len, int index) + { +- int i; +- int status = 0; ++ int i, status = 0; ++ unsigned int read_len = 0; + +- /* remove UID from user space pkt before sending to peripheral */ +- buf = buf + 4; ++ /* The first 4 bytes is the uid tag and the next four bytes is ++ the minmum packet length of a request packet */ ++ if (len < DCI_PKT_REQ_MIN_LEN) { ++ pr_err("diag: dci: Invalid pkt len %d in %s\n", len, __func__); ++ return -EIO; ++ } + if (len > APPS_BUF_SIZE - 10) { +- pr_err("diag: dci: buffer overwrite possible since payload bigger than buf size\n"); ++ pr_err("diag: dci: Invalid payload length in %s\n", __func__); + return -EIO; + } +- len = len - 4; ++ /* remove UID from user space pkt before sending to peripheral*/ ++ buf = buf + sizeof(int); ++ read_len += sizeof(int); ++ len = len - sizeof(int); + mutex_lock(&driver->dci_mutex); + /* prepare DCI packet */ + driver->apps_dci_buf[0] = CONTROL_CHAR; /* start */ +@@ -395,7 +402,13 @@ int diag_send_dci_pkt(struct diag_master_table entry, unsigned char *buf, + driver->req_tracking_tbl[index].tag; + for (i = 0; i < len; i++) + driver->apps_dci_buf[i+9] = *(buf+i); ++ read_len += len; + driver->apps_dci_buf[9+len] = CONTROL_CHAR; /* end */ ++ if ((read_len + 9) >= USER_SPACE_DATA) { ++ pr_err("diag: dci: Invalid length while forming dci pkt in %s", ++ __func__); ++ return -EIO; ++ } + + for (i = 0; i < NUM_SMD_DCI_CHANNELS; i++) { + struct diag_smd_info *smd_info = driver->separate_cmdrsp[i] ? +@@ -449,10 +462,10 @@ int diag_process_dci_transaction(unsigned char *buf, int len) + { + unsigned char *temp = buf; + uint16_t subsys_cmd_code, log_code, item_num; +- int subsys_id, cmd_code, ret = -1, index = -1, found = 0, read_len = 0; ++ int subsys_id, cmd_code, ret = -1, index = -1, found = 0; + struct diag_master_table entry; + int count, set_mask, num_codes, bit_index, event_id, offset = 0, i; +- unsigned int byte_index; ++ unsigned int byte_index, read_len = 0; + uint8_t equip_id, *log_mask_ptr, *head_log_mask_ptr, byte_mask; + uint8_t *event_mask_ptr; + +@@ -462,15 +475,24 @@ int diag_process_dci_transaction(unsigned char *buf, int len) + return DIAG_DCI_SEND_DATA_FAIL; + } + ++ if (!temp) { ++ pr_err("diag: Invalid buffer in %s\n", __func__); ++ } ++ + /* This is Pkt request/response transaction */ + if (*(int *)temp > 0) { ++ if (len < DCI_PKT_REQ_MIN_LEN || len > USER_SPACE_DATA) { ++ pr_err("diag: dci: Invalid length %d len in %s", len, ++ __func__); ++ return -EIO; ++ } + /* enter this UID into kernel table and return index */ + index = diag_register_dci_transaction(*(int *)temp); + if (index < 0) { + pr_alert("diag: registering new DCI transaction failed\n"); + return DIAG_DCI_NO_REG; + } +- temp += 4; ++ temp += sizeof(int); + /* + * Check for registered peripheral and fwd pkt to + * appropriate proc +@@ -480,7 +502,12 @@ int diag_process_dci_transaction(unsigned char *buf, int len) + subsys_id = (int)(*(char *)temp); + temp++; + subsys_cmd_code = *(uint16_t *)temp; +- temp += 2; ++ temp += sizeof(uint16_t); ++ read_len += sizeof(int) + 2 + sizeof(uint16_t); ++ if (read_len >= USER_SPACE_DATA) { ++ pr_err("diag: dci: Invalid length in %s\n", __func__); ++ return -EIO; ++ } + pr_debug("diag: %d %d %d", cmd_code, subsys_id, + subsys_cmd_code); + for (i = 0; i < diag_max_reg; i++) { +@@ -514,6 +541,12 @@ int diag_process_dci_transaction(unsigned char *buf, int len) + } + } + } else if (*(int *)temp == DCI_LOG_TYPE) { ++ /* Minimum length of a log mask config is 12 + 2 bytes for ++ atleast one log code to be set or reset */ ++ if (len < DCI_LOG_CON_MIN_LEN || len > USER_SPACE_DATA) { ++ pr_err("diag: dci: Invalid length in %s\n", __func__); ++ return -EIO; ++ } + /* find client id and table */ + i = diag_dci_find_client_index(current->tgid); + if (i == DCI_CLIENT_INDEX_INVALID) { +@@ -521,21 +554,33 @@ int diag_process_dci_transaction(unsigned char *buf, int len) + return ret; + } + /* Extract each log code and put in client table */ +- temp += 4; +- read_len += 4; ++ temp += sizeof(int); ++ read_len += sizeof(int); + set_mask = *(int *)temp; +- temp += 4; +- read_len += 4; ++ temp += sizeof(int); ++ read_len += sizeof(int); + num_codes = *(int *)temp; +- temp += 4; +- read_len += 4; ++ temp += sizeof(int); ++ read_len += sizeof(int); ++ ++ if (num_codes == 0 || (num_codes >= (USER_SPACE_DATA - 8)/2)) { ++ pr_err("diag: dci: Invalid number of log codes %d\n", ++ num_codes); ++ return -EIO; ++ } + + head_log_mask_ptr = driver->dci_client_tbl[i].dci_log_mask; ++ if (!head_log_mask_ptr) { ++ pr_err("diag: dci: Invalid Log mask pointer in %s\n", ++ __func__); ++ return -ENOMEM; ++ } + pr_debug("diag: head of dci log mask %p\n", head_log_mask_ptr); + count = 0; /* iterator for extracting log codes */ + while (count < num_codes) { + if (read_len >= USER_SPACE_DATA) { +- pr_err("diag: dci: Log type, possible buffer overflow\n"); ++ pr_err("diag: dci: Invalid length for log type in %s", ++ __func__); + return -EIO; + } + log_code = *(uint16_t *)temp; +@@ -589,6 +634,12 @@ int diag_process_dci_transaction(unsigned char *buf, int len) + /* send updated mask to peripherals */ + ret = diag_send_dci_log_mask(driver->smd_cntl[MODEM_DATA].ch); + } else if (*(int *)temp == DCI_EVENT_TYPE) { ++ /* Minimum length of a event mask config is 12 + 4 bytes for ++ atleast one event id to be set or reset. */ ++ if (len < DCI_EVENT_CON_MIN_LEN || len > USER_SPACE_DATA) { ++ pr_err("diag: dci: Invalid length in %s\n", __func__); ++ return -EIO; ++ } + /* find client id and table */ + i = diag_dci_find_client_index(current->tgid); + if (i == DCI_CLIENT_INDEX_INVALID) { +@@ -596,21 +647,36 @@ int diag_process_dci_transaction(unsigned char *buf, int len) + return ret; + } + /* Extract each log code and put in client table */ +- temp += 4; +- read_len += 4; ++ temp += sizeof(int); ++ read_len += sizeof(int); + set_mask = *(int *)temp; +- temp += 4; +- read_len += 4; ++ temp += sizeof(int); ++ read_len += sizeof(int); + num_codes = *(int *)temp; +- temp += 4; +- read_len += 4; ++ temp += sizeof(int); ++ read_len += sizeof(int); ++ ++ /* Check for positive number of event ids. Also, the number of ++ event ids should fit in the buffer along with set_mask and ++ num_codes which are 4 bytes each */ ++ if (num_codes == 0 || (num_codes >= (USER_SPACE_DATA - 8)/2)) { ++ pr_err("diag: dci: Invalid number of event ids %d\n", ++ num_codes); ++ return -EIO; ++ } + + event_mask_ptr = driver->dci_client_tbl[i].dci_event_mask; ++ if (!event_mask_ptr) { ++ pr_err("diag: dci: Invalid event mask pointer in %s\n", ++ __func__); ++ return -ENOMEM; ++ } + pr_debug("diag: head of dci event mask %p\n", event_mask_ptr); + count = 0; /* iterator for extracting log codes */ + while (count < num_codes) { + if (read_len >= USER_SPACE_DATA) { +- pr_err("diag: dci: Event type, possible buffer overflow\n"); ++ pr_err("diag: dci: Invalid length for event type in %s", ++ __func__); + return -EIO; + } + event_id = *(int *)temp; +diff --git a/drivers/char/diag/diag_dci.h b/drivers/char/diag/diag_dci.h +index 4dc1bfc..d530de9 100644 +--- a/drivers/char/diag/diag_dci.h ++++ b/drivers/char/diag/diag_dci.h +@@ -24,6 +24,9 @@ + #define DISABLE_LOG_MASK 0 + #define MAX_EVENT_SIZE 512 + #define DCI_CLIENT_INDEX_INVALID -1 ++#define DCI_PKT_REQ_MIN_LEN 8 ++#define DCI_LOG_CON_MIN_LEN 14 ++#define DCI_EVENT_CON_MIN_LEN 16 + + + /* 16 log code categories, each has: +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9876.patch b/patches/3.10/CVE-2014-9876.patch new file mode 100644 index 0000000..9b11859 --- /dev/null +++ b/patches/3.10/CVE-2014-9876.patch @@ -0,0 +1,30 @@ +From 794cd44fe8e32a4afe31a2f9f6a4499aaa874a48 Mon Sep 17 00:00:00 2001 +From: Mohit Aggarwal +Date: Thu, 2 Jun 2016 18:02:29 -0700 +Subject: [PATCH] diag: Fix possible underflow/overflow issues + +Add check in order to fix possible integer underflow +during HDLC encoding which may lead to buffer +overflow. Also added check for packet length to +avoid buffer overflow. + +Bug: 28767796 +Change-Id: Ifbac719a7db73aab121cb00c2090edf1bf1094bb +Signed-off-by: Yuan Lin +--- + drivers/char/diag/diagfwd.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h +index c6e1273dc585c..9c514e629fb4c 100644 +--- a/drivers/char/diag/diagfwd.h ++++ b/drivers/char/diag/diagfwd.h +@@ -20,7 +20,7 @@ + #define RESET_AND_QUEUE 1 + + #define CHK_OVERFLOW(bufStart, start, end, length) \ +- ((((bufStart) <= (start)) && ((end) - (start) >= (length))) ? 1 : 0) ++ ((((bufStart) <= (start)) && ((end) - (start) >= (length)) && ((length) > 0)) ? 1 : 0) + + void diagfwd_init(void); + void diagfwd_exit(void); \ No newline at end of file diff --git a/patches/3.10/CVE-2014-9877.patch b/patches/3.10/CVE-2014-9877.patch new file mode 100644 index 0000000..247031e --- /dev/null +++ b/patches/3.10/CVE-2014-9877.patch @@ -0,0 +1,93 @@ +From f0c0112a6189747a3f24f20210157f9974477e03 Mon Sep 17 00:00:00 2001 +From: Vasko Kalanoski +Date: Fri, 4 Oct 2013 15:28:34 +0300 +Subject: msm: actuator: fix to prevent untrusted pointer to lead DoS + +fix to prevent untrusted userspace pointer in actuator kernel +driver to lead DoS + +Change-Id: I1b64270deb494530d268539e7b420be5ec79b658 +Signed-off-by: Vasko Kalanoski +--- + .../msm/camera_v2/sensor/actuator/msm_actuator.c | 26 +++++++++++++++++----- + 1 file changed, 20 insertions(+), 6 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +index baa2db8..201a011 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +@@ -196,11 +196,19 @@ static int32_t msm_actuator_piezo_move_focus( + struct msm_actuator_move_params_t *move_params) + { + int32_t dest_step_position = move_params->dest_step_pos; ++ struct damping_params_t ringing_params_kernel; + int32_t rc = 0; + int32_t num_steps = move_params->num_steps; + struct msm_camera_i2c_reg_setting reg_setting; + CDBG("Enter\n"); + ++ if (copy_from_user(&ringing_params_kernel, ++ &(move_params->ringing_params[0]), ++ sizeof(struct damping_params_t))) { ++ pr_err("copy_from_user failed\n"); ++ return -EFAULT; ++ } ++ + if (num_steps == 0) + return rc; + +@@ -208,7 +216,7 @@ static int32_t msm_actuator_piezo_move_focus( + a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl, + (num_steps * + a_ctrl->region_params[0].code_per_step), +- move_params->ringing_params[0].hw_params, 0); ++ ringing_params_kernel.hw_params, 0); + + reg_setting.reg_setting = a_ctrl->i2c_reg_tbl; + reg_setting.data_type = a_ctrl->i2c_data_type; +@@ -230,6 +238,7 @@ static int32_t msm_actuator_move_focus( + struct msm_actuator_move_params_t *move_params) + { + int32_t rc = 0; ++ struct damping_params_t ringing_params_kernel; + int8_t sign_dir = move_params->sign_dir; + uint16_t step_boundary = 0; + uint16_t target_step_pos = 0; +@@ -240,6 +249,14 @@ static int32_t msm_actuator_move_focus( + int32_t num_steps = move_params->num_steps; + struct msm_camera_i2c_reg_setting reg_setting; + ++ if (copy_from_user(&ringing_params_kernel, ++ &(move_params->ringing_params[a_ctrl->curr_region_index]), ++ sizeof(struct damping_params_t))) { ++ pr_err("copy_from_user failed\n"); ++ return -EFAULT; ++ } ++ ++ + CDBG("called, dir %d, num_steps %d\n", dir, num_steps); + + if (dest_step_pos == a_ctrl->curr_step_pos) +@@ -276,9 +293,7 @@ static int32_t msm_actuator_move_focus( + a_ctrl->step_position_table[target_step_pos]; + a_ctrl->func_tbl->actuator_write_focus(a_ctrl, + curr_lens_pos, +- &(move_params-> +- ringing_params[a_ctrl-> +- curr_region_index]), ++ &ringing_params_kernel, + sign_dir, + target_lens_pos); + curr_lens_pos = target_lens_pos; +@@ -289,8 +304,7 @@ static int32_t msm_actuator_move_focus( + a_ctrl->step_position_table[target_step_pos]; + a_ctrl->func_tbl->actuator_write_focus(a_ctrl, + curr_lens_pos, +- &(move_params->ringing_params[a_ctrl-> +- curr_region_index]), ++ &ringing_params_kernel, + sign_dir, + target_lens_pos); + curr_lens_pos = target_lens_pos; +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9878.patch b/patches/3.10/CVE-2014-9878.patch new file mode 100644 index 0000000..ad3ae02 --- /dev/null +++ b/patches/3.10/CVE-2014-9878.patch @@ -0,0 +1,102 @@ +From 96a62c1de93a44e6ca69514411baf4b3d67f6dee Mon Sep 17 00:00:00 2001 +From: Lee Susman +Date: Mon, 11 Nov 2013 08:53:40 +0200 +Subject: mmc: card: fix arbitrary write via read handler in mmc_block_test + +In mmc_block_test, the debug_fs based read function handlers write to an +arbitrary buffer which is given by any user. We add an access_ok check +to verify that the address pointed by *buffer is not in kernel space. +Only if the buffer is valid, do we continue the read handler. + +Change-Id: I35fe9bb70df8de92cb4d3b15c851aa9131a0e8d9 +Signed-off-by: Lee Susman +--- + drivers/mmc/card/mmc_block_test.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/drivers/mmc/card/mmc_block_test.c b/drivers/mmc/card/mmc_block_test.c +index ea73352..b24c367 100644 +--- a/drivers/mmc/card/mmc_block_test.c ++++ b/drivers/mmc/card/mmc_block_test.c +@@ -2219,6 +2219,9 @@ static ssize_t send_write_packing_test_read(struct file *file, + size_t count, + loff_t *offset) + { ++ if (!access_ok(VERIFY_WRITE, buffer, count)) ++ return count; ++ + memset((void *)buffer, 0, count); + + snprintf(buffer, count, +@@ -2317,6 +2320,9 @@ static ssize_t err_check_test_read(struct file *file, + size_t count, + loff_t *offset) + { ++ if (!access_ok(VERIFY_WRITE, buffer, count)) ++ return count; ++ + memset((void *)buffer, 0, count); + + snprintf(buffer, count, +@@ -2425,6 +2431,9 @@ static ssize_t send_invalid_packed_test_read(struct file *file, + size_t count, + loff_t *offset) + { ++ if (!access_ok(VERIFY_WRITE, buffer, count)) ++ return count; ++ + memset((void *)buffer, 0, count); + + snprintf(buffer, count, +@@ -2539,6 +2548,9 @@ static ssize_t write_packing_control_test_read(struct file *file, + size_t count, + loff_t *offset) + { ++ if (!access_ok(VERIFY_WRITE, buffer, count)) ++ return count; ++ + memset((void *)buffer, 0, count); + + snprintf(buffer, count, +@@ -2621,6 +2633,9 @@ static ssize_t bkops_test_read(struct file *file, + size_t count, + loff_t *offset) + { ++ if (!access_ok(VERIFY_WRITE, buffer, count)) ++ return count; ++ + memset((void *)buffer, 0, count); + + snprintf(buffer, count, +@@ -2709,6 +2724,9 @@ static ssize_t long_sequential_read_test_read(struct file *file, + size_t count, + loff_t *offset) + { ++ if (!access_ok(VERIFY_WRITE, buffer, count)) ++ return count; ++ + memset((void *)buffer, 0, count); + + snprintf(buffer, count, +@@ -2869,6 +2887,9 @@ static ssize_t long_sequential_write_test_read(struct file *file, + size_t count, + loff_t *offset) + { ++ if (!access_ok(VERIFY_WRITE, buffer, count)) ++ return count; ++ + memset((void *)buffer, 0, count); + + snprintf(buffer, count, +@@ -2942,6 +2963,9 @@ static ssize_t new_req_notification_test_read(struct file *file, + size_t count, + loff_t *offset) + { ++ if (!access_ok(VERIFY_WRITE, buffer, count)) ++ return count; ++ + memset((void *)buffer, 0, count); + + snprintf(buffer, count, +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9879.patch b/patches/3.10/CVE-2014-9879.patch new file mode 100644 index 0000000..be2eefb --- /dev/null +++ b/patches/3.10/CVE-2014-9879.patch @@ -0,0 +1,154 @@ +From ecc8116e1befb3a764109f47ba0389434ddabbe4 Mon Sep 17 00:00:00 2001 +From: Terence Hampson +Date: Wed, 7 Aug 2013 16:54:51 -0400 +Subject: mdss: mdp3: validate histogram data passed in + +Data passed in from userspace should be validated to be within +the appropriate ranges. + +Change-Id: I50ff818a2b03c1fff55f44403f0f1b67c26d9f0e +Signed-off-by: Terence Hampson +--- + drivers/video/msm/mdss/mdp3_ctrl.c | 77 +++++++++++++++++++++++++++++++++++--- + drivers/video/msm/mdss/mdp3_dma.c | 2 +- + drivers/video/msm/mdss/mdp3_dma.h | 6 +++ + 3 files changed, 79 insertions(+), 6 deletions(-) + +diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c +index 74e6983c..31aae26 100644 +--- a/drivers/video/msm/mdss/mdp3_ctrl.c ++++ b/drivers/video/msm/mdss/mdp3_ctrl.c +@@ -775,6 +775,64 @@ static int mdp3_get_metadata(struct msm_fb_data_type *mfd, + return ret; + } + ++int mdp3_validate_start_req(struct mdp_histogram_start_req *req) ++{ ++ if (req->frame_cnt >= MDP_HISTOGRAM_FRAME_COUNT_MAX) { ++ pr_err("%s invalid req frame_cnt\n", __func__); ++ return -EINVAL; ++ } ++ if (req->bit_mask >= MDP_HISTOGRAM_BIT_MASK_MAX) { ++ pr_err("%s invalid req bit mask\n", __func__); ++ return -EINVAL; ++ } ++ if (req->block != MDP_BLOCK_DMA_P || ++ req->num_bins != MDP_HISTOGRAM_BIN_NUM) { ++ pr_err("mdp3_histogram_start invalid request\n"); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++int mdp3_validate_scale_config(struct mdp_bl_scale_data *data) ++{ ++ if (data->scale > MDP_HISTOGRAM_BL_SCALE_MAX) { ++ pr_err("%s invalid bl_scale\n", __func__); ++ return -EINVAL; ++ } ++ if (data->min_lvl > MDP_HISTOGRAM_BL_LEVEL_MAX) { ++ pr_err("%s invalid bl_min_lvl\n", __func__); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++int mdp3_validate_csc_data(struct mdp_csc_cfg_data *data) ++{ ++ int i; ++ for (i = 0; i < 9; i++) { ++ if (data->csc_data.csc_mv[i] >= ++ MDP_HISTOGRAM_CSC_MATRIX_MAX) ++ return -EINVAL; ++ } ++ for (i = 0; i < 3; i++) { ++ if (data->csc_data.csc_pre_bv[i] >= ++ MDP_HISTOGRAM_CSC_VECTOR_MAX) ++ return -EINVAL; ++ if (data->csc_data.csc_post_bv[i] >= ++ MDP_HISTOGRAM_CSC_VECTOR_MAX) ++ return -EINVAL; ++ } ++ for (i = 0; i < 6; i++) { ++ if (data->csc_data.csc_pre_lv[i] >= ++ MDP_HISTOGRAM_CSC_VECTOR_MAX) ++ return -EINVAL; ++ if (data->csc_data.csc_post_lv[i] >= ++ MDP_HISTOGRAM_CSC_VECTOR_MAX) ++ return -EINVAL; ++ } ++ return 0; ++} ++ + static int mdp3_histogram_start(struct mdp3_session_data *session, + struct mdp_histogram_start_req *req) + { +@@ -782,11 +840,10 @@ static int mdp3_histogram_start(struct mdp3_session_data *session, + struct mdp3_dma_histogram_config histo_config; + + pr_debug("mdp3_histogram_start\n"); +- if (req->block != MDP_BLOCK_DMA_P || +- req->num_bins != MDP_HISTOGRAM_BIN_NUM) { +- pr_err("mdp3_histogram_start invalid request\n"); +- return -EINVAL; +- } ++ ++ ret = mdp3_validate_start_req(req); ++ if (ret) ++ return ret; + + if (!session->dma->histo_op || + !session->dma->config_histo) { +@@ -986,10 +1043,20 @@ static int mdp3_pp_ioctl(struct msm_fb_data_type *mfd, + + switch (mdp_pp.op) { + case mdp_bl_scale_cfg: ++ ret = mdp3_validate_scale_config(&mdp_pp.data.bl_scale_data); ++ if (ret) { ++ pr_err("%s: invalid scale config\n", __func__); ++ break; ++ } + ret = mdp3_bl_scale_config(mfd, (struct mdp_bl_scale_data *) + &mdp_pp.data.bl_scale_data); + break; + case mdp_op_csc_cfg: ++ ret = mdp3_validate_csc_data(&(mdp_pp.data.csc_cfg_data)); ++ if (ret) { ++ pr_err("%s: invalid csc data\n", __func__); ++ break; ++ } + ret = mdp3_csc_config(mdp3_session, + &(mdp_pp.data.csc_cfg_data)); + break; +diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c +index 3e1bf5d..d3f1538 100644 +--- a/drivers/video/msm/mdss/mdp3_dma.c ++++ b/drivers/video/msm/mdss/mdp3_dma.c +@@ -497,7 +497,7 @@ static int mdp3_dmap_histo_config(struct mdp3_dma *dma, + struct mdp3_dma_histogram_config *histo_config) + { + unsigned long flag; +- u32 histo_bit_mask, histo_control; ++ u32 histo_bit_mask = 0, histo_control = 0; + u32 histo_isr_mask = MDP3_DMA_P_HIST_INTR_HIST_DONE_BIT | + MDP3_DMA_P_HIST_INTR_RESET_DONE_BIT; + +diff --git a/drivers/video/msm/mdss/mdp3_dma.h b/drivers/video/msm/mdss/mdp3_dma.h +index e4a28dc..7dd6ba7 100644 +--- a/drivers/video/msm/mdss/mdp3_dma.h ++++ b/drivers/video/msm/mdss/mdp3_dma.h +@@ -16,6 +16,12 @@ + + #include + ++#define MDP_HISTOGRAM_BL_SCALE_MAX 1024 ++#define MDP_HISTOGRAM_BL_LEVEL_MAX 255 ++#define MDP_HISTOGRAM_FRAME_COUNT_MAX 0x20 ++#define MDP_HISTOGRAM_BIT_MASK_MAX 0x4 ++#define MDP_HISTOGRAM_CSC_MATRIX_MAX 0x2000 ++#define MDP_HISTOGRAM_CSC_VECTOR_MAX 0x200 + #define MDP_HISTOGRAM_BIN_NUM 32 + #define MDP_LUT_SIZE 256 + +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9880.patch b/patches/3.10/CVE-2014-9880.patch new file mode 100644 index 0000000..6443545 --- /dev/null +++ b/patches/3.10/CVE-2014-9880.patch @@ -0,0 +1,34 @@ +From f2a3f5e63e15e97a66e8f5a300457378bcb89d9c Mon Sep 17 00:00:00 2001 +From: Deepak Verma +Date: Mon, 21 Oct 2013 17:37:11 +0530 +Subject: msm: vidc: Check validity of userspace address + +Before writing to a userspace address, verification +of the validity of user space address is required. + +Change-Id: I9141e44a6c11aaf3f4d57c08bb0dd26a7b214f34 +CRs-fixed: 556356 +Signed-off-by: Deepak Verma +--- + drivers/video/msm/vidc/common/enc/venc.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c +index 1801461..707d948 100644 +--- a/drivers/video/msm/vidc/common/enc/venc.c ++++ b/drivers/video/msm/vidc/common/enc/venc.c +@@ -1414,6 +1414,12 @@ static long vid_enc_ioctl(struct file *file, + return -EFAULT; + + DBG("VEN_IOCTL_GET_SEQUENCE_HDR\n"); ++ if (!access_ok(VERIFY_WRITE, seq_header.hdrbufptr, ++ seq_header.bufsize)) { ++ ERR("VEN_IOCTL_GET_SEQUENCE_HDR:"\ ++ " Userspace address verification failed.\n"); ++ return -EFAULT; ++ } + result = vid_enc_get_sequence_header(client_ctx, + &seq_header); + if (!result) { +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9881.patch b/patches/3.10/CVE-2014-9881.patch new file mode 100644 index 0000000..4481d0c --- /dev/null +++ b/patches/3.10/CVE-2014-9881.patch @@ -0,0 +1,62 @@ +From ba3f404a10b3bb7e9c20440837df3cd35c5d0c4b Mon Sep 17 00:00:00 2001 +From: Ayaz Ahmad +Date: Thu, 31 Oct 2013 19:08:05 +0530 +Subject: radio: iris: Prevent probable overflow + +casting a unsigned int into an integer, integer to +unsigned int may cause buffer overflow. + +Change-Id: I54be4d4c5470616a59a772c587fe6d5f32575c32 +CRs-Fixed: 539008 +Signed-off-by: Ayaz Ahmad +--- + drivers/media/radio/radio-iris.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c +index bfb1088..12fd7cf 100644 +--- a/drivers/media/radio/radio-iris.c ++++ b/drivers/media/radio/radio-iris.c +@@ -3032,7 +3032,7 @@ static int iris_vidioc_s_ext_ctrls(struct file *file, void *priv, + struct v4l2_ext_controls *ctrl) + { + int retval = 0; +- int bytes_to_copy; ++ size_t bytes_to_copy; + struct hci_fm_tx_ps tx_ps; + struct hci_fm_tx_rt tx_rt; + struct hci_fm_def_data_wr_req default_data; +@@ -3041,14 +3041,20 @@ static int iris_vidioc_s_ext_ctrls(struct file *file, void *priv, + struct iris_device *radio = video_get_drvdata(video_devdata(file)); + char *data = NULL; + ++ if ((ctrl == NULL) || (ctrl->controls == NULL) ++ || (ctrl->count == 0)) { ++ retval = -EINVAL; ++ return retval; ++ } ++ + switch ((ctrl->controls[0]).id) { + case V4L2_CID_RDS_TX_PS_NAME: + FMDBG("In V4L2_CID_RDS_TX_PS_NAME\n"); + /*Pass a sample PS string */ + + memset(tx_ps.ps_data, 0, MAX_PS_LENGTH); +- bytes_to_copy = min((int)(ctrl->controls[0]).size, +- MAX_PS_LENGTH); ++ bytes_to_copy = min_t(size_t, ctrl->controls[0].size, ++ MAX_PS_LENGTH); + data = (ctrl->controls[0]).string; + + if (copy_from_user(tx_ps.ps_data, +@@ -3065,7 +3071,7 @@ static int iris_vidioc_s_ext_ctrls(struct file *file, void *priv, + break; + case V4L2_CID_RDS_TX_RADIO_TEXT: + bytes_to_copy = +- min((int)(ctrl->controls[0]).size, MAX_RT_LENGTH); ++ min_t(size_t, (ctrl->controls[0]).size, MAX_RT_LENGTH); + data = (ctrl->controls[0]).string; + + memset(tx_rt.rt_data, 0, MAX_RT_LENGTH); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9883.patch b/patches/3.10/CVE-2014-9883.patch new file mode 100644 index 0000000..d7a303c --- /dev/null +++ b/patches/3.10/CVE-2014-9883.patch @@ -0,0 +1,57 @@ +From cbf79a67348e48557c0d0bb9bc58391b3f84bc46 Mon Sep 17 00:00:00 2001 +From: Katish Paran +Date: Tue, 24 Dec 2013 14:11:41 +0530 +Subject: diag: dci: Safeguard to prevent integer overflow + +At certain point in diag driver there can be integer overflow +thus can lead to memory leak. Added a safegaurd for it. + +Change-Id: I9347405d8f1f95ed42fe0abf35cbf4c362281bdf +CRs-fixed: 565160 +Signed-off-by: Katish Paran +--- + drivers/char/diag/diag_dci.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c +index 2dbb2f5..7772ebe 100644 +--- a/drivers/char/diag/diag_dci.c ++++ b/drivers/char/diag/diag_dci.c +@@ -383,17 +383,23 @@ void extract_dci_events(unsigned char *buf) + + void extract_dci_log(unsigned char *buf) + { +- uint16_t log_code, item_num; ++ uint16_t log_code, item_num, log_length; + uint8_t equip_id, *log_mask_ptr, byte_mask; + unsigned int i, byte_index, byte_offset = 0; + struct diag_dci_client_tbl *entry; + ++ log_length = *(uint16_t *)(buf + 2); + log_code = *(uint16_t *)(buf + 6); + equip_id = LOG_GET_EQUIP_ID(log_code); + item_num = LOG_GET_ITEM_NUM(log_code); + byte_index = item_num/8 + 2; + byte_mask = 0x01 << (item_num % 8); + ++ if (log_length > USHRT_MAX - 4) { ++ pr_err("diag: Integer overflow in %s, log_len:%d", ++ __func__, log_length); ++ return; ++ } + byte_offset = (equip_id * 514) + byte_index; + if (byte_offset >= DCI_LOG_MASK_SIZE) { + pr_err("diag: Invalid byte_offset %d in dci log\n", +@@ -430,8 +436,8 @@ void extract_dci_log(unsigned char *buf) + *(int *)(entry->dci_data+entry->data_len) = + DCI_LOG_TYPE; + memcpy(entry->dci_data + entry->data_len + 4, +- buf + 4, *(uint16_t *)(buf + 2)); +- entry->data_len += 4 + *(uint16_t *)(buf + 2); ++ buf + 4, log_length); ++ entry->data_len += 4 + log_length; + } + mutex_unlock(&entry->data_mutex); + mutex_unlock(&dci_health_mutex); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9884.patch b/patches/3.10/CVE-2014-9884.patch new file mode 100644 index 0000000..e276dae --- /dev/null +++ b/patches/3.10/CVE-2014-9884.patch @@ -0,0 +1,150 @@ +From f4948193c46f75e16d4382c4472485ab12b7bd17 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Mon, 25 Nov 2013 13:05:35 -0800 +Subject: qseecom: Add checks for user space buffer pointers + +Validate pointers send from user space and pointers +embedded within the mesasge sent from user space. + +Change-Id: I1be54924ef3d301908af6e8d4e6506f2aa7f6428 +Signed-off-by: Mona Hossain +Signed-off-by: Zhen Kong +--- + drivers/misc/qseecom.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 60 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 0bc18fb..c5c0ce8 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -99,7 +99,7 @@ static DEFINE_MUTEX(clk_access_lock); + struct qseecom_registered_listener_list { + struct list_head list; + struct qseecom_register_listener_req svc; +- u8 *sb_reg_req; ++ uint32_t user_virt_sb_base; + u8 *sb_virt; + s32 sb_phys; + size_t sb_length; +@@ -319,6 +319,10 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data, + pr_err("copy_from_user failed\n"); + return ret; + } ++ if (!access_ok(VERIFY_WRITE, (void __user *)rcvd_lstnr.virt_sb_base, ++ rcvd_lstnr.sb_size)) ++ return -EFAULT; ++ + data->listener.id = 0; + if (!__qseecom_is_svc_unique(data, &rcvd_lstnr)) { + pr_err("Service is not unique and is already registered\n"); +@@ -336,6 +340,7 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data, + + new_entry->svc.listener_id = rcvd_lstnr.listener_id; + new_entry->sb_length = rcvd_lstnr.sb_size; ++ new_entry->user_virt_sb_base = rcvd_lstnr.virt_sb_base; + if (__qseecom_set_sb_memory(new_entry, data, &rcvd_lstnr)) { + pr_err("qseecom_set_sb_memoryfailed\n"); + kzfree(new_entry); +@@ -446,6 +451,10 @@ static int qseecom_set_client_mem_param(struct qseecom_dev_handle *data, + req.ifd_data_fd, req.sb_len, req.virt_sb_base); + return -EFAULT; + } ++ if (!access_ok(VERIFY_WRITE, (void __user *)req.virt_sb_base, ++ req.sb_len)) ++ return -EFAULT; ++ + /* Get the handle of the shared fd */ + data->client.ihandle = ion_import_dma_buf(qseecom.ion_clnt, + req.ifd_data_fd); +@@ -861,6 +870,13 @@ static uint32_t __qseecom_uvirt_to_kphys(struct qseecom_dev_handle *data, + return data->client.sb_phys + (virt - data->client.user_virt_sb_base); + } + ++static uint32_t __qseecom_uvirt_to_kvirt(struct qseecom_dev_handle *data, ++ uint32_t virt) ++{ ++ return (uint32_t)data->client.sb_virt + ++ (virt - data->client.user_virt_sb_base); ++} ++ + int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr, + struct qseecom_send_svc_cmd_req *req_ptr, + struct qseecom_client_send_service_ireq *send_svc_ireq_ptr) +@@ -1269,6 +1285,24 @@ static int qseecom_send_modfd_cmd(struct qseecom_dev_handle *data, + pr_err("copy_from_user failed\n"); + return ret; + } ++ ++ if (req.cmd_req_buf == NULL || req.resp_buf == NULL) { ++ pr_err("cmd buffer or response buffer is null\n"); ++ return -EINVAL; ++ } ++ if (((uint32_t)req.cmd_req_buf < data->client.user_virt_sb_base) || ++ ((uint32_t)req.cmd_req_buf >= (data->client.user_virt_sb_base + ++ data->client.sb_length))) { ++ pr_err("cmd buffer address not within shared bufffer\n"); ++ return -EINVAL; ++ } ++ ++ if (((uint32_t)req.resp_buf < data->client.user_virt_sb_base) || ++ ((uint32_t)req.resp_buf >= (data->client.user_virt_sb_base + ++ data->client.sb_length))){ ++ pr_err("response buffer address not within shared bufffer\n"); ++ return -EINVAL; ++ } + send_cmd_req.cmd_req_buf = req.cmd_req_buf; + send_cmd_req.cmd_req_len = req.cmd_req_len; + send_cmd_req.resp_buf = req.resp_buf; +@@ -1282,6 +1316,11 @@ static int qseecom_send_modfd_cmd(struct qseecom_dev_handle *data, + return -EINVAL; + } + } ++ req.cmd_req_buf = (void *)__qseecom_uvirt_to_kvirt(data, ++ (uint32_t)req.cmd_req_buf); ++ req.resp_buf = (void *)__qseecom_uvirt_to_kvirt(data, ++ (uint32_t)req.resp_buf); ++ + ret = __qseecom_update_cmd_buf(&req, false, data, false); + if (ret) + return ret; +@@ -1877,11 +1916,20 @@ static int qseecom_send_modfd_resp(struct qseecom_dev_handle *data, + { + struct qseecom_send_modfd_listener_resp resp; + int i; ++ struct qseecom_registered_listener_list *this_lstnr = NULL; + + if (copy_from_user(&resp, argp, sizeof(resp))) { + pr_err("copy_from_user failed"); + return -EINVAL; + } ++ this_lstnr = __qseecom_find_svc(data->listener.id); ++ if (this_lstnr == NULL) ++ return -EINVAL; ++ ++ if (resp.resp_buf_ptr == NULL) { ++ pr_err("Invalid resp_buf_ptr\n"); ++ return -EINVAL; ++ } + /* validate offsets */ + for (i = 0; i < MAX_ION_FD; i++) { + if (resp.ifd_data[i].cmd_buf_offset >= resp.resp_len) { +@@ -1890,6 +1938,17 @@ static int qseecom_send_modfd_resp(struct qseecom_dev_handle *data, + return -EINVAL; + } + } ++ ++ if (((uint32_t)resp.resp_buf_ptr < ++ this_lstnr->user_virt_sb_base) ++ || ((uint32_t)resp.resp_buf_ptr >= ++ (this_lstnr->user_virt_sb_base + ++ this_lstnr->sb_length))) { ++ pr_err("resp_buf_ptr address not within shared buffer\n"); ++ return -EINVAL; ++ } ++ resp.resp_buf_ptr = (uint32_t)this_lstnr->sb_virt + ++ (resp.resp_buf_ptr - this_lstnr->user_virt_sb_base); + __qseecom_update_cmd_buf(&resp, false, data, true); + qseecom.send_resp_flag = 1; + wake_up_interruptible(&qseecom.send_resp_wq); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9885.patch b/patches/3.10/CVE-2014-9885.patch new file mode 100644 index 0000000..48b0924 --- /dev/null +++ b/patches/3.10/CVE-2014-9885.patch @@ -0,0 +1,29 @@ +From a1d5a4cbd5aa8656bc23b40c7cc43941e10f89c3 Mon Sep 17 00:00:00 2001 +From: Dipen Parmar +Date: Fri, 18 Oct 2013 15:53:36 +0530 +Subject: thermal: qpnp-adc-tm: Fix format specifier in snprintf + +Add format specifier in snprintf to avoid security +vulnerability issues. + +Change-Id: I6ea67633348341267e0646912a6b428709410c78 +Signed-off-by: Dipen Parmar +--- + drivers/thermal/qpnp-adc-tm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c +index a90a042..b203ae3 100644 +--- a/drivers/thermal/qpnp-adc-tm.c ++++ b/drivers/thermal/qpnp-adc-tm.c +@@ -1886,7 +1886,7 @@ static int qpnp_adc_tm_probe(struct spmi_device *spmi) + pr_debug("thermal node%x\n", btm_channel_num); + chip->sensor[sen_idx].mode = THERMAL_DEVICE_DISABLED; + chip->sensor[sen_idx].thermal_node = true; +- snprintf(name, sizeof(name), ++ snprintf(name, sizeof(name), "%s", + chip->adc->adc_channels[sen_idx].name); + chip->sensor[sen_idx].meas_interval = + QPNP_ADC_TM_MEAS_INTERVAL; +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9886.patch b/patches/3.10/CVE-2014-9886.patch new file mode 100644 index 0000000..81052f2 --- /dev/null +++ b/patches/3.10/CVE-2014-9886.patch @@ -0,0 +1,177 @@ +From 80be0e249c906704085d13d4ae446f73913fc225 Mon Sep 17 00:00:00 2001 +From: Baruch Eruchimovitch +Date: Mon, 14 Oct 2013 15:49:41 +0300 +Subject: msm: ultrasound: add verifications of some input parameters + +Some security vulnerabilities were found. +To fix them, additional verifications of some input parameters +are required. + +CRs-Fixed: 554575, 554560, 555030 +Change-Id: Ie87a433bcda89c3e462cfd511c168e8306056020 +Signed-off-by: Baruch Eruchimovitch +--- + arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c | 82 ++++++++++++++++++------------ + 1 file changed, 49 insertions(+), 33 deletions(-) + +diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c +index 1ea213a..01fcfd9 100644 +--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c ++++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c +@@ -51,6 +51,11 @@ + #define Y_IND 1 + #define Z_IND 2 + ++/* Shared memory limits */ ++/* max_buf_size = (port_size(65535*2) * port_num(8) * group_size(3) */ ++#define USF_MAX_BUF_SIZE 3145680 ++#define USF_MAX_BUF_NUM 32 ++ + /* Place for opreation result, received from QDSP6 */ + #define APR_RESULT_IND 1 + +@@ -436,6 +441,15 @@ static int config_xx(struct usf_xx_type *usf_xx, struct us_xx_info_type *config) + (config == NULL)) + return -EINVAL; + ++ if ((config->buf_size == 0) || ++ (config->buf_size > USF_MAX_BUF_SIZE) || ++ (config->buf_num == 0) || ++ (config->buf_num > USF_MAX_BUF_NUM)) { ++ pr_err("%s: wrong params: buf_size=%d; buf_num=%d\n", ++ __func__, config->buf_size, config->buf_num); ++ return -EINVAL; ++ } ++ + data_map_size = sizeof(usf_xx->encdec_cfg.cfg_common.data_map); + min_map_size = min(data_map_size, config->port_cnt); + +@@ -748,6 +762,7 @@ static int usf_set_us_detection(struct usf_type *usf, unsigned long arg) + { + uint32_t timeout = 0; + struct us_detect_info_type detect_info; ++ struct usm_session_cmd_detect_info *p_allocated_memory = NULL; + struct usm_session_cmd_detect_info usm_detect_info; + struct usm_session_cmd_detect_info *p_usm_detect_info = + &usm_detect_info; +@@ -774,12 +789,13 @@ static int usf_set_us_detection(struct usf_type *usf, unsigned long arg) + uint8_t *p_data = NULL; + + detect_info_size += detect_info.params_data_size; +- p_usm_detect_info = kzalloc(detect_info_size, GFP_KERNEL); +- if (p_usm_detect_info == NULL) { ++ p_allocated_memory = kzalloc(detect_info_size, GFP_KERNEL); ++ if (p_allocated_memory == NULL) { + pr_err("%s: detect_info[%d] allocation failed\n", + __func__, detect_info_size); + return -ENOMEM; + } ++ p_usm_detect_info = p_allocated_memory; + p_data = (uint8_t *)p_usm_detect_info + + sizeof(struct usm_session_cmd_detect_info); + +@@ -789,7 +805,7 @@ static int usf_set_us_detection(struct usf_type *usf, unsigned long arg) + if (rc) { + pr_err("%s: copy params from user; rc=%d\n", + __func__, rc); +- kfree(p_usm_detect_info); ++ kfree(p_allocated_memory); + return -EFAULT; + } + p_usm_detect_info->algorithm_cfg_size = +@@ -806,9 +822,7 @@ static int usf_set_us_detection(struct usf_type *usf, unsigned long arg) + p_usm_detect_info, + detect_info_size); + if (rc || (detect_info.detect_timeout == USF_NO_WAIT_TIMEOUT)) { +- if (detect_info_size > +- sizeof(struct usm_session_cmd_detect_info)) +- kfree(p_usm_detect_info); ++ kfree(p_allocated_memory); + return rc; + } + +@@ -828,25 +842,24 @@ static int usf_set_us_detection(struct usf_type *usf, unsigned long arg) + USF_US_DETECT_UNDEF), + timeout); + /* In the case of timeout, "no US" is assumed */ +- if (rc < 0) { ++ if (rc < 0) + pr_err("%s: Getting US detection failed rc[%d]\n", + __func__, rc); +- return rc; +- } +- +- usf->usf_rx.us_detect_type = usf->usf_tx.us_detect_type; +- detect_info.is_us = (usf_xx->us_detect_type == USF_US_DETECT_YES); +- rc = copy_to_user((void __user *)arg, +- &detect_info, +- sizeof(detect_info)); +- if (rc) { +- pr_err("%s: copy detect_info to user; rc=%d\n", +- __func__, rc); +- rc = -EFAULT; ++ else { ++ usf->usf_rx.us_detect_type = usf->usf_tx.us_detect_type; ++ detect_info.is_us = ++ (usf_xx->us_detect_type == USF_US_DETECT_YES); ++ rc = copy_to_user((void __user *)arg, ++ &detect_info, ++ sizeof(detect_info)); ++ if (rc) { ++ pr_err("%s: copy detect_info to user; rc=%d\n", ++ __func__, rc); ++ rc = -EFAULT; ++ } + } + +- if (detect_info_size > sizeof(struct usm_session_cmd_detect_info)) +- kfree(p_usm_detect_info); ++ kfree(p_allocated_memory); + + return rc; + } /* usf_set_us_detection */ +@@ -947,16 +960,14 @@ static int usf_set_rx_info(struct usf_type *usf, unsigned long arg) + if (rc) + return rc; + +- if (usf_xx->buffer_size && usf_xx->buffer_count) { +- rc = q6usm_us_client_buf_alloc( +- IN, +- usf_xx->usc, +- usf_xx->buffer_size, +- usf_xx->buffer_count); +- if (rc) { +- (void)q6usm_cmd(usf_xx->usc, CMD_CLOSE); +- return rc; +- } ++ rc = q6usm_us_client_buf_alloc( ++ IN, ++ usf_xx->usc, ++ usf_xx->buffer_size, ++ usf_xx->buffer_count); ++ if (rc) { ++ (void)q6usm_cmd(usf_xx->usc, CMD_CLOSE); ++ return rc; + } + + rc = q6usm_dec_cfg_blk(usf_xx->usc, +@@ -1175,10 +1186,15 @@ static int usf_get_version(unsigned long arg) + return -EFAULT; + } + +- /* version_info.buf is pointer to place for the version string */ ++ if (version_info.buf_size < sizeof(DRV_VERSION)) { ++ pr_err("%s: buf_size (%d) < version string size (%d)\n", ++ __func__, version_info.buf_size, sizeof(DRV_VERSION)); ++ return -EINVAL; ++ } ++ + rc = copy_to_user(version_info.pbuf, + DRV_VERSION, +- version_info.buf_size); ++ sizeof(DRV_VERSION)); + if (rc) { + pr_err("%s: copy to version_info.pbuf; rc=%d\n", + __func__, rc); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9887.patch b/patches/3.10/CVE-2014-9887.patch new file mode 100644 index 0000000..c39af05 --- /dev/null +++ b/patches/3.10/CVE-2014-9887.patch @@ -0,0 +1,34 @@ +From b1bc773cf61265e0e3871b2e52bd6b3270ffc6c3 Mon Sep 17 00:00:00 2001 +From: Zhen Kong +Date: Thu, 27 Mar 2014 12:44:15 -0700 +Subject: qseecom: Validate pointer offset in qseecom_send_modfd_cmd + +Validate cmd_req_buf pointer offset in qseecom_send_modfy_cmd, and +make sure cmd buffer address to be within shared bufffer. + +Change-Id: I431511a92ab2cccbc2daebc0cf76cc3872689a97 +Signed-off-by: Zhen Kong +--- + drivers/misc/qseecom.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 5d2b64c..bce4994 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -1635,6 +1635,13 @@ static int qseecom_send_modfd_cmd(struct qseecom_dev_handle *data, + pr_err("response buffer address not within shared bufffer\n"); + return -EINVAL; + } ++ ++ if (req.cmd_req_len == 0 || req.cmd_req_len > data->client.sb_length || ++ req.resp_len > data->client.sb_length) { ++ pr_err("cmd or response buffer length not valid\n"); ++ return -EINVAL; ++ } ++ + send_cmd_req.cmd_req_buf = req.cmd_req_buf; + send_cmd_req.cmd_req_len = req.cmd_req_len; + send_cmd_req.resp_buf = req.resp_buf; +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9888.patch b/patches/3.10/CVE-2014-9888.patch new file mode 100644 index 0000000..069f95d --- /dev/null +++ b/patches/3.10/CVE-2014-9888.patch @@ -0,0 +1,37 @@ +From 0ea1ec713f04bdfac343c9702b21cd3a7c711826 Mon Sep 17 00:00:00 2001 +From: Russell King +Date: Wed, 23 Oct 2013 16:14:59 +0100 +Subject: [PATCH] ARM: dma-mapping: don't allow DMA mappings to be marked + executable + +DMA mapping permissions were being derived from pgprot_kernel directly +without using PAGE_KERNEL. This causes them to be marked with executable +permission, which is not what we want. Fix this. + +Signed-off-by: Russell King +--- + arch/arm/mm/dma-mapping.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c +index f5e1a8471714c..57438506d5246 100644 +--- a/arch/arm/mm/dma-mapping.c ++++ b/arch/arm/mm/dma-mapping.c +@@ -687,7 +687,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, + void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, + gfp_t gfp, struct dma_attrs *attrs) + { +- pgprot_t prot = __get_dma_pgprot(attrs, pgprot_kernel); ++ pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL); + void *memory; + + if (dma_alloc_from_coherent(dev, size, handle, &memory)) +@@ -700,7 +700,7 @@ void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, + static void *arm_coherent_dma_alloc(struct device *dev, size_t size, + dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs) + { +- pgprot_t prot = __get_dma_pgprot(attrs, pgprot_kernel); ++ pgprot_t prot = __get_dma_pgprot(attrs, PAGE_KERNEL); + void *memory; + + if (dma_alloc_from_coherent(dev, size, handle, &memory)) \ No newline at end of file diff --git a/patches/3.10/CVE-2014-9889.patch b/patches/3.10/CVE-2014-9889.patch new file mode 100644 index 0000000..b6e7f7c --- /dev/null +++ b/patches/3.10/CVE-2014-9889.patch @@ -0,0 +1,154 @@ +From f4e2f2d4ef58c88340774099dff3324ec8baa24a Mon Sep 17 00:00:00 2001 +From: Manish Poddar +Date: Thu, 10 Jul 2014 19:43:31 +0530 +Subject: msm: cpp: Validate frame message before manipulating it + +CPP frame message is used to send all frame data +to Microcontroller. It is sent every frame. CPP kernel +driver has to add information to it before transfer it. +The message has to be validated before manipulations. +If it is not valid the message and corresponding frame +are discarded. +Change-Id: Ib5b9b5d2e1886d3d671966b693ce212d58e34041 +Signed-off-by: Manish Poddar +--- + .../platform/msm/camera_v2/pproc/cpp/msm_cpp.c | 61 +++++++++++++++++----- + .../platform/msm/camera_v2/pproc/cpp/msm_cpp.h | 1 + + include/media/msmb_pproc.h | 3 +- + 3 files changed, 50 insertions(+), 15 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +index d3a848a..253cbed 100644 +--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c ++++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +@@ -56,6 +56,16 @@ + #define MSM_CPP_NOMINAL_CLOCK 266670000 + #define MSM_CPP_TURBO_CLOCK 320000000 + ++#define CPP_FW_VERSION_1_2_0 0x10020000 ++#define CPP_FW_VERSION_1_4_0 0x10040000 ++#define CPP_FW_VERSION_1_6_0 0x10060000 ++#define CPP_FW_VERSION_1_8_0 0x10080000 ++ ++/* stripe information offsets in frame command */ ++#define STRIPE_BASE_FW_1_2_0 130 ++#define STRIPE_BASE_FW_1_4_0 140 ++#define STRIPE_BASE_FW_1_6_0 464 ++ + struct msm_cpp_timer_data_t { + struct cpp_device *cpp_dev; + struct msm_cpp_frame_info_t *processed_frame; +@@ -918,7 +928,8 @@ static void cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin) + msm_cpp_poll(cpp_dev->base, MSM_CPP_MSG_ID_CMD); + msm_cpp_poll(cpp_dev->base, 0x2); + msm_cpp_poll(cpp_dev->base, MSM_CPP_MSG_ID_FW_VER); +- pr_info("CPP FW Version: 0x%x\n", msm_cpp_read(cpp_dev->base)); ++ cpp_dev->fw_version = msm_cpp_read(cpp_dev->base); ++ pr_info("CPP FW Version: 0x%08x\n", cpp_dev->fw_version); + msm_cpp_poll(cpp_dev->base, MSM_CPP_MSG_ID_TRAILER); + + /*Disable MC clock*/ +@@ -1287,9 +1298,8 @@ static int msm_cpp_cfg(struct cpp_device *cpp_dev, + struct msm_cpp_frame_info_t *u_frame_info = + (struct msm_cpp_frame_info_t *)ioctl_ptr->ioctl_ptr; + int32_t status = 0; +- uint8_t fw_version_1_2_x = 0; + int in_fd; +- ++ int32_t stripe_base = 0; + int i = 0; + if (!new_frame) { + pr_err("Insufficient memory. return\n"); +@@ -1330,7 +1340,16 @@ static int msm_cpp_cfg(struct cpp_device *cpp_dev, + } + + new_frame->cpp_cmd_msg = cpp_frame_msg; +- ++ if (cpp_frame_msg == NULL || ++ (new_frame->msg_len < MSM_CPP_MIN_FRAME_LENGTH)) { ++ pr_err("%s %d Length is not correct or frame message is missing\n", ++ __func__, __LINE__); ++ return -EINVAL; ++ } ++ if (cpp_frame_msg[new_frame->msg_len - 1] != MSM_CPP_MSG_ID_TRAILER) { ++ pr_err("%s %d Invalid frame message\n", __func__, __LINE__); ++ return -EINVAL; ++ } + in_phyaddr = msm_cpp_fetch_buffer_info(cpp_dev, + &new_frame->input_buffer_info, + ((new_frame->input_buffer_info.identity >> 16) & 0xFFFF), +@@ -1404,22 +1423,36 @@ static int msm_cpp_cfg(struct cpp_device *cpp_dev, + ((cpp_frame_msg[12] >> 10) & 0x3FF) + + (cpp_frame_msg[12] & 0x3FF); + +- fw_version_1_2_x = 0; +- if ((cpp_dev->hw_info.cpp_hw_version == CPP_HW_VERSION_1_1_0) || +- (cpp_dev->hw_info.cpp_hw_version == CPP_HW_VERSION_1_1_1) || +- (cpp_dev->hw_info.cpp_hw_version == CPP_HW_VERSION_2_0_0)) +- fw_version_1_2_x = 2; ++ if ((cpp_dev->fw_version & 0xffff0000) == ++ CPP_FW_VERSION_1_2_0) { ++ stripe_base = STRIPE_BASE_FW_1_2_0; ++ } else if ((cpp_dev->fw_version & 0xffff0000) == ++ CPP_FW_VERSION_1_4_0) { ++ stripe_base = STRIPE_BASE_FW_1_4_0; ++ } else if ((cpp_dev->fw_version & 0xffff0000) == ++ CPP_FW_VERSION_1_6_0) { ++ stripe_base = STRIPE_BASE_FW_1_6_0; ++ } else { ++ pr_err("invalid fw version %08x", cpp_dev->fw_version); ++ } ++ ++ if ((stripe_base + num_stripes*27 + 1) != new_frame->msg_len) { ++ pr_err("Invalid frame message\n"); ++ rc = -EINVAL; ++ goto ERROR3; ++ } ++ + + for (i = 0; i < num_stripes; i++) { +- cpp_frame_msg[(133 + fw_version_1_2_x) + i * 27] += ++ cpp_frame_msg[stripe_base + 5 + i*27] += + (uint32_t) in_phyaddr; +- cpp_frame_msg[(139 + fw_version_1_2_x) + i * 27] += ++ cpp_frame_msg[stripe_base + 11 + i * 27] += + (uint32_t) out_phyaddr0; +- cpp_frame_msg[(140 + fw_version_1_2_x) + i * 27] += ++ cpp_frame_msg[stripe_base + 12 + i * 27] += + (uint32_t) out_phyaddr1; +- cpp_frame_msg[(141 + fw_version_1_2_x) + i * 27] += ++ cpp_frame_msg[stripe_base + 13 + i * 27] += + (uint32_t) out_phyaddr0; +- cpp_frame_msg[(142 + fw_version_1_2_x) + i * 27] += ++ cpp_frame_msg[stripe_base + 14 + i * 27] += + (uint32_t) out_phyaddr1; + } + +diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h +index bd73ab2..af1af2d 100644 +--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h ++++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h +@@ -189,6 +189,7 @@ struct cpp_device { + char *fw_name_bin; + struct workqueue_struct *timer_wq; + struct msm_cpp_work_t *work; ++ uint32_t fw_version; + uint8_t stream_cnt; + uint8_t timeout_trial_cnt; + +diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h +index 59dcca9..f5a53a8 100644 +--- a/include/media/msmb_pproc.h ++++ b/include/media/msmb_pproc.h +@@ -13,7 +13,8 @@ + + #define MAX_NUM_CPP_STRIPS 8 + #define MSM_CPP_MAX_NUM_PLANES 3 +-#define MSM_CPP_MAX_FRAME_LENGTH 1024 ++#define MSM_CPP_MIN_FRAME_LENGTH 13 ++#define MSM_CPP_MAX_FRAME_LENGTH 2048 + #define MSM_CPP_MAX_FW_NAME_LEN 32 + #define MAX_FREQ_TBL 10 + +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9890.patch b/patches/3.10/CVE-2014-9890.patch new file mode 100644 index 0000000..ffc5a83 --- /dev/null +++ b/patches/3.10/CVE-2014-9890.patch @@ -0,0 +1,38 @@ +From 14e0c8614d2715589583d8a95e33c422d110eb6f Mon Sep 17 00:00:00 2001 +From: Rajesh Bondugula +Date: Tue, 25 Jun 2013 17:45:23 -0700 +Subject: msm: camera: Update CCI WR comamnd buffer size to 11 bytes + +I2C command length is of 11 bytes, it includes 10 bytes of data and +1 byte of WR command. Use 11 bytes char array to create command. + +Signed-off-by: Rajesh Bondugula +Change-Id: I5292f238d612810a514b6a8bba9e70e07eb2627f +--- + drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c +index 61873d3..ddc3b57 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c +@@ -181,7 +181,7 @@ static int32_t msm_cci_data_queue(struct cci_device *cci_dev, + uint16_t i = 0, j = 0, k = 0, h = 0, len = 0; + int32_t rc = 0; + uint32_t cmd = 0, delay = 0; +- uint8_t data[10]; ++ uint8_t data[11]; + uint16_t reg_addr = 0; + struct msm_camera_i2c_reg_setting *i2c_msg = + &c_ctrl->cfg.cci_i2c_write_cfg; +@@ -616,7 +616,7 @@ static int32_t msm_cci_i2c_write(struct v4l2_subdev *sd, + msm_cci_flush_queue(cci_dev, master); + goto ERROR; + } else { +- rc = 0; ++ rc = cci_dev->cci_master_info[master].status; + } + CDBG("%s:%d X wait_for_completion_interruptible\n", __func__, + __LINE__); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9891.patch b/patches/3.10/CVE-2014-9891.patch new file mode 100644 index 0000000..d409686 --- /dev/null +++ b/patches/3.10/CVE-2014-9891.patch @@ -0,0 +1,63 @@ +From c10f03f191307f7114af89933f2d91b830150094 Mon Sep 17 00:00:00 2001 +From: Hariprasad Dhalinarasimha +Date: Fri, 27 Sep 2013 18:38:53 -0700 +Subject: qseecom: Copy userspace buffer into kernel space before dereferencing + +ION memory is used for user space to kernel space data passing. +This is directly accessible in kernel. But, if the IOCTL is called +from user space without using User space library, then data might +be pointing to some other memory location, in which case, it would +not be possible to dereference this location in kernel & hence it +would be accessing invalid memory. + +Change-Id: Ic50c76ee8b2a696dbb786fce3a68cdc782e15268 +Signed-off-by: Hariprasad Dhalinarasimha +--- + drivers/misc/qseecom.c | 25 ++++++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 4c1943b..1c93bf4 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -1006,14 +1006,37 @@ int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr, + struct qseecom_client_send_service_ireq *send_svc_ireq_ptr) + { + int ret = 0; ++ void *req_buf = NULL; ++ + if ((req_ptr == NULL) || (send_svc_ireq_ptr == NULL)) { + pr_err("Error with pointer: req_ptr = %p, send_svc_ptr = %p\n", + req_ptr, send_svc_ireq_ptr); + return -EINVAL; + } ++ ++ if (((uint32_t)req_ptr->cmd_req_buf < ++ data_ptr->client.user_virt_sb_base) ++ || ((uint32_t)req_ptr->cmd_req_buf >= ++ (data_ptr->client.user_virt_sb_base + ++ data_ptr->client.sb_length))) { ++ pr_err("cmd buffer address not within shared bufffer\n"); ++ return -EINVAL; ++ } ++ ++ ++ if (((uint32_t)req_ptr->resp_buf < data_ptr->client.user_virt_sb_base) ++ || ((uint32_t)req_ptr->resp_buf >= ++ (data_ptr->client.user_virt_sb_base + ++ data_ptr->client.sb_length))){ ++ pr_err("response buffer address not within shared bufffer\n"); ++ return -EINVAL; ++ } ++ ++ req_buf = data_ptr->client.sb_virt; ++ + send_svc_ireq_ptr->qsee_cmd_id = req_ptr->cmd_id; + send_svc_ireq_ptr->key_type = +- ((struct qseecom_rpmb_provision_key *)req_ptr->cmd_req_buf)->key_type; ++ ((struct qseecom_rpmb_provision_key *)req_buf)->key_type; + send_svc_ireq_ptr->req_len = req_ptr->cmd_req_len; + send_svc_ireq_ptr->rsp_ptr = (void *)(__qseecom_uvirt_to_kphys(data_ptr, + (uint32_t)req_ptr->resp_buf)); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9892.patch b/patches/3.10/CVE-2014-9892.patch new file mode 100644 index 0000000..1ab1dd8 --- /dev/null +++ b/patches/3.10/CVE-2014-9892.patch @@ -0,0 +1,34 @@ +From 591b1f455c32206704cbcf426bb30911c260c33e Mon Sep 17 00:00:00 2001 +From: Krishnankutty Kolathappilly +Date: Wed, 6 Nov 2013 10:08:39 -0800 +Subject: ALSA: compress: Memset timestamp structure to zero. + +snd_compr_tstamp is initialized using aggregate initialization +that does not zero out the padded bytes. Initialize timestamp +structure to zero using memset to avoid this. + +CRs-Fixed: 568717 +Change-Id: I7a7d188705161f06201f1a1f2945bb6acd633d5d +Signed-off-by: Krishnankutty Kolathappilly +--- + sound/core/compress_offload.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c +index 99db892..0a69437 100644 +--- a/sound/core/compress_offload.c ++++ b/sound/core/compress_offload.c +@@ -613,9 +613,10 @@ snd_compr_set_metadata(struct snd_compr_stream *stream, unsigned long arg) + static inline int + snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg) + { +- struct snd_compr_tstamp tstamp = {0}; ++ struct snd_compr_tstamp tstamp; + int ret; + ++ memset(&tstamp, 0, sizeof(tstamp)); + ret = snd_compr_update_tstamp(stream, &tstamp); + if (ret == 0) + ret = copy_to_user((struct snd_compr_tstamp __user *)arg, +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9893.patch b/patches/3.10/CVE-2014-9893.patch new file mode 100644 index 0000000..2da18bf --- /dev/null +++ b/patches/3.10/CVE-2014-9893.patch @@ -0,0 +1,77 @@ +From bfc6eee5e30a0c20bc37495233506f4f0cc4991d Mon Sep 17 00:00:00 2001 +From: Ping Li +Date: Thu, 3 Oct 2013 20:01:52 -0400 +Subject: msm: mdss: Replace the size check for gamut LUTs + +Add more reliable size check for gamut LUTs to prevent potential +security issues such as information leak. + +Change-Id: I32be41a2612a100b9ba6167737c2f8778f720fa2 +Signed-off-by: Ping Li +--- + drivers/video/msm/mdss/mdss_mdp_pp.c | 33 +++++++++++++++++++++++++++++---- + 1 file changed, 29 insertions(+), 4 deletions(-) + +diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c +index ed95030..1d8430e 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_pp.c ++++ b/drivers/video/msm/mdss/mdss_mdp_pp.c +@@ -295,6 +295,10 @@ static void pp_update_argc_lut(char __iomem *addr, + struct mdp_pgc_lut_data *config); + static void pp_update_hist_lut(char __iomem *base, + struct mdp_hist_lut_data *cfg); ++static int pp_gm_has_invalid_lut_size(struct mdp_gamut_cfg_data *config); ++static void pp_gamut_config(struct mdp_gamut_cfg_data *gamut_cfg, ++ char __iomem *base, ++ struct pp_sts_type *pp_sts); + static void pp_pa_config(unsigned long flags, char __iomem *addr, + struct pp_sts_type *pp_sts, + struct mdp_pa_cfg *pa_config); +@@ -2086,10 +2090,32 @@ int mdss_mdp_dither_config(struct mdp_dither_cfg_data *config, + return 0; + } + ++static int pp_gm_has_invalid_lut_size(struct mdp_gamut_cfg_data *config) ++{ ++ if (config->tbl_size[0] != GAMUT_T0_SIZE) ++ return -EINVAL; ++ if (config->tbl_size[1] != GAMUT_T1_SIZE) ++ return -EINVAL; ++ if (config->tbl_size[2] != GAMUT_T2_SIZE) ++ return -EINVAL; ++ if (config->tbl_size[3] != GAMUT_T3_SIZE) ++ return -EINVAL; ++ if (config->tbl_size[4] != GAMUT_T4_SIZE) ++ return -EINVAL; ++ if (config->tbl_size[5] != GAMUT_T5_SIZE) ++ return -EINVAL; ++ if (config->tbl_size[6] != GAMUT_T6_SIZE) ++ return -EINVAL; ++ if (config->tbl_size[7] != GAMUT_T7_SIZE) ++ return -EINVAL; ++ ++ return 0; ++} ++ + int mdss_mdp_gamut_config(struct mdp_gamut_cfg_data *config, + u32 *copyback) + { +- int i, j, size_total = 0, ret = 0; ++ int i, j, ret = 0; + + u32 disp_num, dspp_num = 0; + uint16_t *tbl_off; +@@ -2102,9 +2128,8 @@ int mdss_mdp_gamut_config(struct mdp_gamut_cfg_data *config, + if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) || + (config->block >= MDP_BLOCK_MAX)) + return -EINVAL; +- for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++) +- size_total += config->tbl_size[i]; +- if (size_total != GAMUT_TOTAL_TABLE_SIZE) ++ ++ if (pp_gm_has_invalid_lut_size(config)) + return -EINVAL; + + mutex_lock(&mdss_pp_mutex); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9894.patch b/patches/3.10/CVE-2014-9894.patch new file mode 100644 index 0000000..5418f01 --- /dev/null +++ b/patches/3.10/CVE-2014-9894.patch @@ -0,0 +1,38 @@ +From 83214431cd02674c70402b160b16b7427e28737f Mon Sep 17 00:00:00 2001 +From: Hariprasad Dhalinarasimha +Date: Thu, 3 Oct 2013 16:52:16 -0700 +Subject: qseecom: Ensure incoming "app_name" does not corrupt the kernel stack + +Printing a string with that does not have null terminated character, +would lead to overflow, as the print continues until it finds a null +terminated character. +Avoid this issue by explicitly assigning a string with null termination. + +Change-Id: I9528db2ba046c514d829097d08c09540588bb1a2 +Signed-off-by: Hariprasad Dhalinarasimha +--- + drivers/misc/qseecom.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c +index 4c1943b..7ab8089 100644 +--- a/drivers/misc/qseecom.c ++++ b/drivers/misc/qseecom.c +@@ -773,6 +773,7 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp) + if (ret) + return ret; + req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND; ++ load_img_req.img_name[MAX_APP_NAME_SIZE-1] = '\0'; + memcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE); + + ret = __qseecom_check_app_exists(req); +@@ -2453,6 +2454,7 @@ static int qseecom_query_app_loaded(struct qseecom_dev_handle *data, + } + + req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND; ++ query_req.app_name[MAX_APP_NAME_SIZE-1] = '\0'; + memcpy(req.app_name, query_req.app_name, MAX_APP_NAME_SIZE); + + ret = __qseecom_check_app_exists(req); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9895.patch b/patches/3.10/CVE-2014-9895.patch new file mode 100644 index 0000000..14551af --- /dev/null +++ b/patches/3.10/CVE-2014-9895.patch @@ -0,0 +1,32 @@ +From cc4b26575602e492efd986e9a6ffc4278cee53b5 Mon Sep 17 00:00:00 2001 +From: Deva Ramasubramanian +Date: Fri, 24 Jan 2014 12:38:37 -0800 +Subject: [media] media: Init the reserved fields of struct media_link_desc + +struct media_link_desc is copy_to_user'ed as the return value of +MEDIA_IOC_ENUM_LINKS. When copying, the driver is omitting to initialise +the reserved fields. This commit fixes that by initialising the +reserved fields to 0. + +CRs-Fixed: 570757 +Change-Id: I230e2666c0845cc36399518a0f2c94db664382d1 +Signed-off-by: Deva Ramasubramanian +--- + drivers/media/media-device.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c +index 6f9eb94..4f39838 100644 +--- a/drivers/media/media-device.c ++++ b/drivers/media/media-device.c +@@ -139,7 +139,7 @@ static long media_device_enum_links(struct media_device *mdev, + unsigned int p; + + for (p = 0; p < entity->num_pads; p++) { +- struct media_pad_desc pad; ++ struct media_pad_desc pad = {0}; + media_device_kpad_to_upad(&entity->pads[p], &pad); + if (copy_to_user(&links.pads[p], &pad, sizeof(pad))) + return -EFAULT; +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9896.patch b/patches/3.10/CVE-2014-9896.patch new file mode 100644 index 0000000..13f1d41 --- /dev/null +++ b/patches/3.10/CVE-2014-9896.patch @@ -0,0 +1,85 @@ +From 89f2bcf1ac860b0b380e579e9a8764013f263a7d Mon Sep 17 00:00:00 2001 +From: Mitchel Humpherys +Date: Fri, 25 Oct 2013 12:05:47 -0700 +Subject: msm: ADSPRPC: Add checks for erroneous values + +Check for invalid parameters passed in user invocation +and validate the return values using appropriate macros. + +Change-Id: If529873d025ac0c13725efbedda5a58fae327722 +Acked-by: Sathish Ambley +Signed-off-by: Mitchel Humpherys +--- + drivers/char/adsprpc.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c +index e421135..c8b6c0a 100644 +--- a/drivers/char/adsprpc.c ++++ b/drivers/char/adsprpc.c +@@ -199,7 +199,7 @@ static void free_mem(struct fastrpc_buf *buf) + me->smmu.domain_id, 0); + buf->phys = 0; + } +- if (buf->virt) { ++ if (!IS_ERR_OR_NULL(buf->virt)) { + ion_unmap_kernel(me->iclient, buf->handle); + buf->virt = 0; + } +@@ -212,7 +212,7 @@ static void free_map(struct fastrpc_mmap *map) + { + struct fastrpc_apps *me = &gfa; + if (!IS_ERR_OR_NULL(map->handle)) { +- if (map->virt) { ++ if (!IS_ERR_OR_NULL(map->virt)) { + ion_unmap_kernel(me->iclient, map->handle); + map->virt = 0; + } +@@ -231,13 +231,15 @@ static int alloc_mem(struct fastrpc_buf *buf) + unsigned long len; + buf->handle = 0; + buf->virt = 0; ++ buf->phys = 0; + heap = me->smmu.enabled ? ION_HEAP(ION_IOMMU_HEAP_ID) : + ION_HEAP(ION_ADSP_HEAP_ID) | ION_HEAP(ION_AUDIO_HEAP_ID); + buf->handle = ion_alloc(clnt, buf->size, SZ_4K, heap, ION_FLAG_CACHED); + VERIFY(err, 0 == IS_ERR_OR_NULL(buf->handle)); + if (err) + goto bail; +- VERIFY(err, 0 != (buf->virt = ion_map_kernel(clnt, buf->handle))); ++ buf->virt = ion_map_kernel(clnt, buf->handle); ++ VERIFY(err, 0 == IS_ERR_OR_NULL(buf->virt)); + if (err) + goto bail; + if (me->smmu.enabled) { +@@ -356,6 +358,9 @@ static int get_page_list(uint32_t kernel, uint32_t sc, remote_arg_t *pra, + list[i].num = 0; + list[i].pgidx = 0; + len = pra[i].buf.len; ++ VERIFY(err, len >= 0); ++ if (err) ++ goto bail; + if (!len) + continue; + buf = pra[i].buf.pv; +@@ -857,7 +862,7 @@ static int fastrpc_internal_invoke(struct fastrpc_apps *me, uint32_t mode, + context_free(ctx); + + if (me->smmu.enabled) { +- bufs = REMOTE_SCALARS_LENGTH(sc); ++ bufs = REMOTE_SCALARS_INBUFS(sc) + REMOTE_SCALARS_OUTBUFS(sc); + if (fds) { + handles = (struct ion_handle **)(fds + bufs); + for (i = 0; i < bufs; i++) +@@ -1037,7 +1042,8 @@ static int fastrpc_internal_mmap(struct fastrpc_apps *me, + VERIFY(err, 0 == IS_ERR_OR_NULL(map->handle)); + if (err) + goto bail; +- VERIFY(err, 0 != (map->virt = ion_map_kernel(clnt, map->handle))); ++ map->virt = ion_map_kernel(clnt, map->handle); ++ VERIFY(err, 0 == IS_ERR_OR_NULL(map->virt)); + if (err) + goto bail; + buf = (void *)mmap->vaddrin; +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9897.patch b/patches/3.10/CVE-2014-9897.patch new file mode 100644 index 0000000..cbd77f9 --- /dev/null +++ b/patches/3.10/CVE-2014-9897.patch @@ -0,0 +1,31 @@ +From 46135d80765cb70a914f02a6e7b6abe64679ec86 Mon Sep 17 00:00:00 2001 +From: Mohammad Johny Shaik +Date: Wed, 13 Nov 2013 15:45:34 -0800 +Subject: msm:qdsp6v2: Check null pointer on userspace data argument in kernel + +The null pointer check is required to ensure that userspace data +in kernalspace is not null. + +Change-Id: I9e522c393ae643626a4bae03731a73f5d6db6458 +CRs-Fixed: 563752 +Signed-off-by: Mohammad Johny Shaik +--- + sound/soc/msm/qdsp6v2/msm-lsm-client.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c +index fe6ed29..2bca5e18 100644 +--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c ++++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c +@@ -170,6 +170,9 @@ static int msm_lsm_ioctl(struct snd_pcm_substream *substream, + */ + rc = -EFAULT; + } else { ++ if (!access_ok(VERIFY_READ, user, ++ sizeof(struct snd_lsm_event_status))) ++ rc = -EFAULT; + if (user->payload_size < + event_status->payload_size) { + pr_debug("%s: provided %dbytes isn't enough, needs %dbytes\n", +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9898.patch b/patches/3.10/CVE-2014-9898.patch new file mode 100644 index 0000000..81052f2 --- /dev/null +++ b/patches/3.10/CVE-2014-9898.patch @@ -0,0 +1,177 @@ +From 80be0e249c906704085d13d4ae446f73913fc225 Mon Sep 17 00:00:00 2001 +From: Baruch Eruchimovitch +Date: Mon, 14 Oct 2013 15:49:41 +0300 +Subject: msm: ultrasound: add verifications of some input parameters + +Some security vulnerabilities were found. +To fix them, additional verifications of some input parameters +are required. + +CRs-Fixed: 554575, 554560, 555030 +Change-Id: Ie87a433bcda89c3e462cfd511c168e8306056020 +Signed-off-by: Baruch Eruchimovitch +--- + arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c | 82 ++++++++++++++++++------------ + 1 file changed, 49 insertions(+), 33 deletions(-) + +diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c +index 1ea213a..01fcfd9 100644 +--- a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c ++++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c +@@ -51,6 +51,11 @@ + #define Y_IND 1 + #define Z_IND 2 + ++/* Shared memory limits */ ++/* max_buf_size = (port_size(65535*2) * port_num(8) * group_size(3) */ ++#define USF_MAX_BUF_SIZE 3145680 ++#define USF_MAX_BUF_NUM 32 ++ + /* Place for opreation result, received from QDSP6 */ + #define APR_RESULT_IND 1 + +@@ -436,6 +441,15 @@ static int config_xx(struct usf_xx_type *usf_xx, struct us_xx_info_type *config) + (config == NULL)) + return -EINVAL; + ++ if ((config->buf_size == 0) || ++ (config->buf_size > USF_MAX_BUF_SIZE) || ++ (config->buf_num == 0) || ++ (config->buf_num > USF_MAX_BUF_NUM)) { ++ pr_err("%s: wrong params: buf_size=%d; buf_num=%d\n", ++ __func__, config->buf_size, config->buf_num); ++ return -EINVAL; ++ } ++ + data_map_size = sizeof(usf_xx->encdec_cfg.cfg_common.data_map); + min_map_size = min(data_map_size, config->port_cnt); + +@@ -748,6 +762,7 @@ static int usf_set_us_detection(struct usf_type *usf, unsigned long arg) + { + uint32_t timeout = 0; + struct us_detect_info_type detect_info; ++ struct usm_session_cmd_detect_info *p_allocated_memory = NULL; + struct usm_session_cmd_detect_info usm_detect_info; + struct usm_session_cmd_detect_info *p_usm_detect_info = + &usm_detect_info; +@@ -774,12 +789,13 @@ static int usf_set_us_detection(struct usf_type *usf, unsigned long arg) + uint8_t *p_data = NULL; + + detect_info_size += detect_info.params_data_size; +- p_usm_detect_info = kzalloc(detect_info_size, GFP_KERNEL); +- if (p_usm_detect_info == NULL) { ++ p_allocated_memory = kzalloc(detect_info_size, GFP_KERNEL); ++ if (p_allocated_memory == NULL) { + pr_err("%s: detect_info[%d] allocation failed\n", + __func__, detect_info_size); + return -ENOMEM; + } ++ p_usm_detect_info = p_allocated_memory; + p_data = (uint8_t *)p_usm_detect_info + + sizeof(struct usm_session_cmd_detect_info); + +@@ -789,7 +805,7 @@ static int usf_set_us_detection(struct usf_type *usf, unsigned long arg) + if (rc) { + pr_err("%s: copy params from user; rc=%d\n", + __func__, rc); +- kfree(p_usm_detect_info); ++ kfree(p_allocated_memory); + return -EFAULT; + } + p_usm_detect_info->algorithm_cfg_size = +@@ -806,9 +822,7 @@ static int usf_set_us_detection(struct usf_type *usf, unsigned long arg) + p_usm_detect_info, + detect_info_size); + if (rc || (detect_info.detect_timeout == USF_NO_WAIT_TIMEOUT)) { +- if (detect_info_size > +- sizeof(struct usm_session_cmd_detect_info)) +- kfree(p_usm_detect_info); ++ kfree(p_allocated_memory); + return rc; + } + +@@ -828,25 +842,24 @@ static int usf_set_us_detection(struct usf_type *usf, unsigned long arg) + USF_US_DETECT_UNDEF), + timeout); + /* In the case of timeout, "no US" is assumed */ +- if (rc < 0) { ++ if (rc < 0) + pr_err("%s: Getting US detection failed rc[%d]\n", + __func__, rc); +- return rc; +- } +- +- usf->usf_rx.us_detect_type = usf->usf_tx.us_detect_type; +- detect_info.is_us = (usf_xx->us_detect_type == USF_US_DETECT_YES); +- rc = copy_to_user((void __user *)arg, +- &detect_info, +- sizeof(detect_info)); +- if (rc) { +- pr_err("%s: copy detect_info to user; rc=%d\n", +- __func__, rc); +- rc = -EFAULT; ++ else { ++ usf->usf_rx.us_detect_type = usf->usf_tx.us_detect_type; ++ detect_info.is_us = ++ (usf_xx->us_detect_type == USF_US_DETECT_YES); ++ rc = copy_to_user((void __user *)arg, ++ &detect_info, ++ sizeof(detect_info)); ++ if (rc) { ++ pr_err("%s: copy detect_info to user; rc=%d\n", ++ __func__, rc); ++ rc = -EFAULT; ++ } + } + +- if (detect_info_size > sizeof(struct usm_session_cmd_detect_info)) +- kfree(p_usm_detect_info); ++ kfree(p_allocated_memory); + + return rc; + } /* usf_set_us_detection */ +@@ -947,16 +960,14 @@ static int usf_set_rx_info(struct usf_type *usf, unsigned long arg) + if (rc) + return rc; + +- if (usf_xx->buffer_size && usf_xx->buffer_count) { +- rc = q6usm_us_client_buf_alloc( +- IN, +- usf_xx->usc, +- usf_xx->buffer_size, +- usf_xx->buffer_count); +- if (rc) { +- (void)q6usm_cmd(usf_xx->usc, CMD_CLOSE); +- return rc; +- } ++ rc = q6usm_us_client_buf_alloc( ++ IN, ++ usf_xx->usc, ++ usf_xx->buffer_size, ++ usf_xx->buffer_count); ++ if (rc) { ++ (void)q6usm_cmd(usf_xx->usc, CMD_CLOSE); ++ return rc; + } + + rc = q6usm_dec_cfg_blk(usf_xx->usc, +@@ -1175,10 +1186,15 @@ static int usf_get_version(unsigned long arg) + return -EFAULT; + } + +- /* version_info.buf is pointer to place for the version string */ ++ if (version_info.buf_size < sizeof(DRV_VERSION)) { ++ pr_err("%s: buf_size (%d) < version string size (%d)\n", ++ __func__, version_info.buf_size, sizeof(DRV_VERSION)); ++ return -EINVAL; ++ } ++ + rc = copy_to_user(version_info.pbuf, + DRV_VERSION, +- version_info.buf_size); ++ sizeof(DRV_VERSION)); + if (rc) { + pr_err("%s: copy to version_info.pbuf; rc=%d\n", + __func__, rc); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9899.patch b/patches/3.10/CVE-2014-9899.patch new file mode 100644 index 0000000..95faa10 --- /dev/null +++ b/patches/3.10/CVE-2014-9899.patch @@ -0,0 +1,42 @@ +From 8756624acb1e090b45baf07b2a8d0ebde114000e Mon Sep 17 00:00:00 2001 +From: Saket Saurabh +Date: Mon, 30 Sep 2013 17:33:57 +0530 +Subject: ehci-msm2: Add boundary check in echi driver + +This change adds boundary check before copying data from userspace +buffer to ehci local buffer. +The third parameter passed to copy_from_user() should be minimum of the two +values between userpsace buffer size count and (local_buffer size - 1). The +last one byte in local_buffer should be reserved for null terminator. + +CRs-Fixed: 547910 +Change-Id: Id3c5432aa3fae3ce9759056b5481b9f516df7764 +Signed-off-by: Saket Saurabh +--- + drivers/usb/host/ehci-msm2.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/usb/host/ehci-msm2.c b/drivers/usb/host/ehci-msm2.c +index 221af44..32ed806 100644 +--- a/drivers/usb/host/ehci-msm2.c ++++ b/drivers/usb/host/ehci-msm2.c +@@ -1059,7 +1059,7 @@ static ssize_t debug_write_phy_data(struct file *file, const char __user *buf, + + memset(kbuf, 0, 10); + +- if (copy_from_user(kbuf, buf, count > 10 ? 10 : count)) ++ if (copy_from_user(kbuf, buf, min_t(size_t, sizeof(kbuf) - 1, count))) + return -EFAULT; + + if (sscanf(kbuf, "%x", &data) != 1) +@@ -1084,7 +1084,7 @@ static ssize_t debug_phy_write_addr(struct file *file, const char __user *buf, + + memset(kbuf, 0, 10); + +- if (copy_from_user(kbuf, buf, count > 10 ? 10 : count)) ++ if (copy_from_user(kbuf, buf, min_t(size_t, sizeof(kbuf) - 1, count))) + return -EFAULT; + + if (sscanf(kbuf, "%x", &temp) != 1) +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9900.patch b/patches/3.10/CVE-2014-9900.patch new file mode 100644 index 0000000..71df138 --- /dev/null +++ b/patches/3.10/CVE-2014-9900.patch @@ -0,0 +1,35 @@ +From 63c317dbee97983004dffdd9f742a20d17150071 Mon Sep 17 00:00:00 2001 +From: Avijit Kanti Das +Date: Wed, 14 May 2014 11:03:56 -0700 +Subject: net: Zeroing the structure ethtool_wolinfo in ethtool_get_wol() + +memset() the structure ethtool_wolinfo that has padded bytes +but the padded bytes have not been zeroed out. + +Change-Id: If3fd2d872a1b1ab9521d937b86a29fc468a8bbfe +Signed-off-by: Avijit Kanti Das +--- + net/core/ethtool.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/core/ethtool.c b/net/core/ethtool.c +index ce91766..900a05f 100644 +--- a/net/core/ethtool.c ++++ b/net/core/ethtool.c +@@ -711,11 +711,13 @@ static int ethtool_reset(struct net_device *dev, char __user *useraddr) + + static int ethtool_get_wol(struct net_device *dev, char __user *useraddr) + { +- struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; ++ struct ethtool_wolinfo wol; + + if (!dev->ethtool_ops->get_wol) + return -EOPNOTSUPP; + ++ memset(&wol, 0, sizeof(struct ethtool_wolinfo)); ++ wol.cmd = ETHTOOL_GWOL; + dev->ethtool_ops->get_wol(dev, &wol); + + if (copy_to_user(useraddr, &wol, sizeof(wol))) +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9901.patch b/patches/3.10/CVE-2014-9901.patch new file mode 100644 index 0000000..287a21e --- /dev/null +++ b/patches/3.10/CVE-2014-9901.patch @@ -0,0 +1,293 @@ +From 637f0f7931dd7265ac1c250dc2884d6389c66bde Mon Sep 17 00:00:00 2001 +From: Panvar Vivek +Date: Thu, 12 Dec 2013 17:17:40 +0530 +Subject: wlan: Replace snprintf with scnprintf + +The function snprintf() do not write more than size bytes (including +the terminating null byte ('\0')). If the output was truncated due +to this limit then the return value is the number of characters +(excluding the terminating null byte) which would have been written +to the final string if enough space had been available. Thus, a +return value of size or more means that the output was truncated. + +Change-Id: Iccf9648961e2ac9eeffa0f824a80fd3798be3870 +CRs-Fixed: 548711 +--- + CORE/HDD/src/wlan_hdd_cfg.c | 2 +- + CORE/HDD/src/wlan_hdd_hostapd.c | 6 ++-- + CORE/HDD/src/wlan_hdd_scan.c | 2 +- + CORE/HDD/src/wlan_hdd_tdls.c | 9 +++--- + CORE/HDD/src/wlan_hdd_wext.c | 70 ++++++++++++++++++++++++++++++----------- + 5 files changed, 62 insertions(+), 27 deletions(-) + +diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c +index 0fa44de..31d0adc 100644 +--- a/CORE/HDD/src/wlan_hdd_cfg.c ++++ b/CORE/HDD/src/wlan_hdd_cfg.c +@@ -3240,7 +3240,7 @@ VOS_STATUS hdd_cfg_get_config(hdd_context_t *pHddCtx, char *pBuf, int buflen) + { + snprintf(valueStr, CFG_VALUE_MAX_LEN, "(unhandled)"); + } +- curlen = snprintf(configStr, CFG_ENTRY_MAX_LEN, ++ curlen = scnprintf(configStr, CFG_ENTRY_MAX_LEN, + "%s=[%s]%s\n", + pRegEntry->RegName, + valueStr, +diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c +index cc2fb0e..d9c965a 100644 +--- a/CORE/HDD/src/wlan_hdd_hostapd.c ++++ b/CORE/HDD/src/wlan_hdd_hostapd.c +@@ -2350,7 +2350,7 @@ static iw_softap_ap_stats(struct net_device *dev, + + WLANSAP_GetStatistics((WLAN_HDD_GET_CTX(pHostapdAdapter))->pvosContext, &statBuffer, (v_BOOL_t)wrqu->data.flags); + +- len = snprintf(pstatbuf, len, ++ len = scnprintf(pstatbuf, len, + "RUF=%d RMF=%d RBF=%d " + "RUB=%d RMB=%d RBB=%d " + "TUF=%d TMF=%d TBF=%d " +@@ -3481,7 +3481,7 @@ VOS_STATUS hdd_softap_get_sta_info(hdd_adapter_t *pAdapter, v_U8_t *pBuf, int bu + int len = 0; + const char sta_info_header[] = "staId staAddress\n"; + +- len = snprintf(pBuf, buf_len, sta_info_header); ++ len = scnprintf(pBuf, buf_len, sta_info_header); + pBuf += len; + buf_len -= len; + +@@ -3489,7 +3489,7 @@ VOS_STATUS hdd_softap_get_sta_info(hdd_adapter_t *pAdapter, v_U8_t *pBuf, int bu + { + if(pAdapter->aStaInfo[i].isUsed) + { +- len = snprintf(pBuf, buf_len, "%*d .%02x:%02x:%02x:%02x:%02x:%02x\n", ++ len = scnprintf(pBuf, buf_len, "%*d .%02x:%02x:%02x:%02x:%02x:%02x\n", + strlen("staId"), + pAdapter->aStaInfo[i].ucSTAId, + pAdapter->aStaInfo[i].macAddrSTA.bytes[0], +diff --git a/CORE/HDD/src/wlan_hdd_scan.c b/CORE/HDD/src/wlan_hdd_scan.c +index 8c1d259..9c60557 100644 +--- a/CORE/HDD/src/wlan_hdd_scan.c ++++ b/CORE/HDD/src/wlan_hdd_scan.c +@@ -534,7 +534,7 @@ static eHalStatus hdd_IndicateScanResult(hdd_scan_info_t *scanInfo, tCsrScanResu + /* AGE */ + event.cmd = IWEVCUSTOM; + p = custom; +- p += snprintf(p, MAX_CUSTOM_LEN, " Age: %lu", ++ p += scnprintf(p, MAX_CUSTOM_LEN, " Age: %lu", + vos_timer_get_system_ticks() - descriptor->nReceivedTime); + event.u.data.length = p - custom; + current_event = iwe_stream_add_point (scanInfo->info,current_event, end, +diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c +index 9a6149f..f616af2 100644 +--- a/CORE/HDD/src/wlan_hdd_tdls.c ++++ b/CORE/HDD/src/wlan_hdd_tdls.c +@@ -1400,11 +1400,12 @@ int wlan_hdd_tdls_get_all_peers(hdd_adapter_t *pAdapter, char *buf, int buflen) + + + init_len = buflen; +- len = snprintf(buf, buflen, "\n%-18s%-3s%-4s%-3s%-5s\n", "MAC", "Id", "cap", "up", "RSSI"); ++ len = scnprintf(buf, buflen, "\n%-18s%-3s%-4s%-3s%-5s\n", ++ "MAC", "Id", "cap", "up", "RSSI"); + buf += len; + buflen -= len; + /* 1234567890123456789012345678901234567 */ +- len = snprintf(buf, buflen, "---------------------------------\n"); ++ len = scnprintf(buf, buflen, "---------------------------------\n"); + buf += len; + buflen -= len; + +@@ -1417,7 +1418,7 @@ int wlan_hdd_tdls_get_all_peers(hdd_adapter_t *pAdapter, char *buf, int buflen) + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL == pHddTdlsCtx) { + mutex_unlock(&tdls_lock); +- len = snprintf(buf, buflen, "TDLS not enabled\n"); ++ len = scnprintf(buf, buflen, "TDLS not enabled\n"); + return len; + } + for (i = 0; i < 256; i++) { +@@ -1428,7 +1429,7 @@ int wlan_hdd_tdls_get_all_peers(hdd_adapter_t *pAdapter, char *buf, int buflen) + + if (buflen < 32+1) + break; +- len = snprintf(buf, buflen, ++ len = scnprintf(buf, buflen, + MAC_ADDRESS_STR"%3d%4s%3s%5d\n", + MAC_ADDR_ARRAY(curr_peer->peerMac), + curr_peer->staId, +diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c +index 0cd68bd..b141df0 100644 +--- a/CORE/HDD/src/wlan_hdd_wext.c ++++ b/CORE/HDD/src/wlan_hdd_wext.c +@@ -413,7 +413,7 @@ void hdd_wlan_get_version(hdd_adapter_t *pAdapter, union iwreq_data *wrqu, + pHWversion = "Unknown"; + } + +- wrqu->data.length = snprintf(extra, WE_MAX_STR_LEN, ++ wrqu->data.length = scnprintf(extra, WE_MAX_STR_LEN, + "Host SW:%s, FW:%s, HW:%s", + QWLAN_VERSIONSTR, + pSWversion, +@@ -2551,7 +2551,7 @@ static int iw_get_rssi(struct net_device *dev, + { + /* we are not connected or our SSID is too long + so we cannot report an rssi */ +- rc = snprintf(cmd, len, "OK"); ++ rc = scnprintf(cmd, len, "OK"); + } + else + { +@@ -2566,7 +2566,7 @@ static int iw_get_rssi(struct net_device *dev, + { + /* append the rssi to the ssid in the format required by + the WiFI Framework */ +- rc = snprintf(&cmd[ssidlen], len - ssidlen, " rssi %d", s7Rssi); ++ rc = scnprintf(&cmd[ssidlen], len - ssidlen, " rssi %d", s7Rssi); + } + else + { +@@ -4412,19 +4412,19 @@ static int iw_get_char_setnone(struct net_device *dev, struct iw_request_info *i + if ( WLAN_ADAPTER == adapter_num ) + { + useAdapter = pAdapter; +- buf = snprintf(extra + len, WE_MAX_STR_LEN - len, ++ buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n\n wlan0 States:-"); + len += buf; + } + else if ( P2P_ADAPTER == adapter_num ) + { +- buf = snprintf(extra + len, WE_MAX_STR_LEN - len, ++ buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n\n p2p0 States:-"); + len += buf; + + if( !pHddCtx ) + { +- buf = snprintf(extra + len, WE_MAX_STR_LEN - len, ++ buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n pHddCtx is NULL"); + len += buf; + break; +@@ -4435,7 +4435,7 @@ static int iw_get_char_setnone(struct net_device *dev, struct iw_request_info *i + useAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT); + if ( !useAdapter ) + { +- buf = snprintf(extra + len, WE_MAX_STR_LEN - len, ++ buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n Device not configured as P2P_CLIENT."); + len += buf; + break; +@@ -4447,7 +4447,7 @@ static int iw_get_char_setnone(struct net_device *dev, struct iw_request_info *i + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR( useAdapter ); + if( !pHddStaCtx ) + { +- buf = snprintf(extra + len, WE_MAX_STR_LEN - len, ++ buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n pHddStaCtx is NULL"); + len += buf; + break; +@@ -4455,7 +4455,7 @@ static int iw_get_char_setnone(struct net_device *dev, struct iw_request_info *i + + tlState = smeGetTLSTAState(hHal, pHddStaCtx->conn_info.staId[0]); + +- buf = snprintf(extra + len, WE_MAX_STR_LEN - len, ++ buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n HDD Conn State - %s " + "\n \n SME State:" + "\n Neighbour Roam State - %s" +@@ -4478,7 +4478,7 @@ static int iw_get_char_setnone(struct net_device *dev, struct iw_request_info *i + } + + /* Printing Lim State starting with global lim states */ +- buf = snprintf(extra + len, WE_MAX_STR_LEN - len, ++ buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n \n LIM STATES:-" + "\n Global Sme State - %s "\ + "\n Global mlm State - %s "\ +@@ -4493,7 +4493,7 @@ static int iw_get_char_setnone(struct net_device *dev, struct iw_request_info *i + { + if ( pMac->lim.gpSession[count].valid ) + { +- buf = snprintf(extra + len, WE_MAX_STR_LEN - len, ++ buf = scnprintf(extra + len, WE_MAX_STR_LEN - len, + "\n Lim Valid Session %d:-" + "\n PE Sme State - %s " + "\n PE Mlm State - %s " +@@ -4574,6 +4574,7 @@ static int iw_get_char_setnone(struct net_device *dev, struct iw_request_info *i + VOS_STATUS status; + v_U8_t i, len; + char* buf ; ++ + tChannelListInfo channel_list; + + status = iw_softap_get_channel_list(dev, info, wrqu, (char *)&channel_list); +@@ -4585,20 +4586,23 @@ static int iw_get_char_setnone(struct net_device *dev, struct iw_request_info *i + buf = extra; + + /** +- * Maximum channels = WNI_CFG_VALID_CHANNEL_LIST_LEN. Maximum buffer +- * needed = 5 * number of channels. Check if sufficient buffer is available and +- * then proceed to fill the buffer. +- */ ++ * Maximum channels = WNI_CFG_VALID_CHANNEL_LIST_LEN. Maximum buffer ++ * needed = 5 * number of channels. Check if sufficient buffer is available and ++ * then proceed to fill the buffer. ++ */ + if(WE_MAX_STR_LEN < (5 * WNI_CFG_VALID_CHANNEL_LIST_LEN)) + { +- hddLog(VOS_TRACE_LEVEL_ERROR, "%s Insufficient Buffer to populate channel list\n",__func__); ++ hddLog(VOS_TRACE_LEVEL_ERROR, ++ "%s Insufficient Buffer to populate channel list\n", ++ __func__); + return -EINVAL; + } +- len = snprintf(buf, 5, "%u ", channel_list.num_channels); ++ len = scnprintf(buf, WE_MAX_STR_LEN, "%u ", ++ channel_list.num_channels); + buf += len; + for(i = 0 ; i < channel_list.num_channels; i++) + { +- len = snprintf(buf, 5, ++ len = scnprintf(buf, WE_MAX_STR_LEN, + "%u ", channel_list.channels[i]); + buf += len; + } +@@ -4632,6 +4636,36 @@ static int iw_get_char_setnone(struct net_device *dev, struct iw_request_info *i + break; + } + #endif ++#ifdef FEATURE_CESIUM_PROPRIETARY ++ case WE_GET_IBSS_STA_INFO: ++ { ++ hdd_station_ctx_t *pHddStaCtx = ++ WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); ++ int idx = 0; ++ int length = 0; ++ ++ for (idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++) ++ { ++ if (0 != pHddStaCtx->conn_info.staId[ idx ]) ++ { ++ length += scnprintf ++ ( ++ (extra + length), WE_MAX_STR_LEN - length, ++ "%d .%02x:%02x:%02x:%02x:%02x:%02x\n", ++ pHddStaCtx->conn_info.staId[ idx ], ++ pHddStaCtx->conn_info.peerMacAddress[idx].bytes[0], ++ pHddStaCtx->conn_info.peerMacAddress[idx].bytes[1], ++ pHddStaCtx->conn_info.peerMacAddress[idx].bytes[2], ++ pHddStaCtx->conn_info.peerMacAddress[idx].bytes[3], ++ pHddStaCtx->conn_info.peerMacAddress[idx].bytes[4], ++ pHddStaCtx->conn_info.peerMacAddress[idx].bytes[5] ++ ); ++ } ++ } ++ wrqu->data.length = strlen(extra)+1; ++ break; ++ } ++#endif + default: + { + hddLog(LOGE, "Invalid IOCTL command %d \n", sub_cmd ); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9902.patch b/patches/3.10/CVE-2014-9902.patch new file mode 100644 index 0000000..36eb161 --- /dev/null +++ b/patches/3.10/CVE-2014-9902.patch @@ -0,0 +1,60 @@ +From 3b1c44a3a7129dc25abe2c23543f6f66c59e8f50 Mon Sep 17 00:00:00 2001 +From: Kiran Kumar Lokere +Date: Thu, 7 Nov 2013 19:01:17 -0800 +Subject: Fix the buffer overflow issue observed in static code analysis. + +Fix the possible buffer overflow in IE parsing. + +Change-Id: I1a386ac09dbe30562fbd84739eb8d61c6a09b001 +CRs-Fixed: 553937, 553941 +--- + CORE/MAC/src/include/dot11f.h | 2 +- + CORE/SYS/legacy/src/utils/src/dot11f.c | 6 +++--- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/CORE/MAC/src/include/dot11f.h b/CORE/MAC/src/include/dot11f.h +index 3a82e65..cc89258 100644 +--- a/CORE/MAC/src/include/dot11f.h ++++ b/CORE/MAC/src/include/dot11f.h +@@ -52,7 +52,7 @@ + * + * + * This file was automatically generated by 'framesc' +- * Tue Jul 2 15:39:44 2013 from the following file(s): ++ * Thu Nov 7 16:38:38 2013 from the following file(s): + * + * dot11f.frms + * +diff --git a/CORE/SYS/legacy/src/utils/src/dot11f.c b/CORE/SYS/legacy/src/utils/src/dot11f.c +index 411f593..1b89baa 100644 +--- a/CORE/SYS/legacy/src/utils/src/dot11f.c ++++ b/CORE/SYS/legacy/src/utils/src/dot11f.c +@@ -29,7 +29,7 @@ + * + * + * This file was automatically generated by 'framesc' +- * Tue Jul 2 15:39:44 2013 from the following file(s): ++ * Thu Nov 7 16:38:38 2013 from the following file(s): + * + * dot11f.frms + * +@@ -2976,7 +2976,7 @@ tANI_U32 dot11fUnpackIeCountry(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen + else + { + pDst->num_triplets = (tANI_U8)( ielen / 3 ); +- if (ielen / 3 > 84){ ++ if (ielen > 84 * 3){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } +@@ -4650,7 +4650,7 @@ tANI_U32 dot11fUnpackIeSuppChannels(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + pDst->num_bands = (tANI_U8)( ielen / 2 ); +- if (ielen / 2 > 48){ ++ if (ielen > 48 * 2){ + pDst->present = 0; + return DOT11F_SKIPPED_BAD_IE; + } +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2014-9904.patch b/patches/3.10/CVE-2014-9904.patch new file mode 100644 index 0000000..f7c4d33 --- /dev/null +++ b/patches/3.10/CVE-2014-9904.patch @@ -0,0 +1,35 @@ +From 6217e5ede23285ddfee10d2e4ba0cc2d4c046205 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Wed, 16 Jul 2014 09:37:04 +0300 +Subject: ALSA: compress: fix an integer overflow check + +I previously added an integer overflow check here but looking at it now, +it's still buggy. + +The bug happens in snd_compr_allocate_buffer(). We multiply +".fragments" and ".fragment_size" and that doesn't overflow but then we +save it in an unsigned int so it truncates the high bits away and we +allocate a smaller than expected size. + +Fixes: b35cc8225845 ('ALSA: compress_core: integer overflow in snd_compr_allocate_buffer()') +Signed-off-by: Dan Carpenter +Signed-off-by: Takashi Iwai +--- + sound/core/compress_offload.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c +index 7403f34..89028fa 100644 +--- a/sound/core/compress_offload.c ++++ b/sound/core/compress_offload.c +@@ -491,7 +491,7 @@ static int snd_compress_check_input(struct snd_compr_params *params) + { + /* first let's check the buffer parameter's */ + if (params->buffer.fragment_size == 0 || +- params->buffer.fragments > SIZE_MAX / params->buffer.fragment_size) ++ params->buffer.fragments > INT_MAX / params->buffer.fragment_size) + return -EINVAL; + + /* now codec parameters */ +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2015-8938.patch b/patches/3.10/CVE-2015-8938.patch new file mode 100644 index 0000000..13ca7e1 --- /dev/null +++ b/patches/3.10/CVE-2015-8938.patch @@ -0,0 +1,254 @@ +From 51c39420e3a49d1a7f05a77c64369b7623088238 Mon Sep 17 00:00:00 2001 +From: Sreesudhan Ramakrish Ramkumar +Date: Fri, 12 Dec 2014 04:20:59 -0800 +Subject: msm: camera: isp: Validate input parameter for vfe_write and vfe_read + +Validate input parameters for read and write operations in vfe to +ensure operations are performed within vfe register boundary and +within structure limits passed by caller. + +Change-Id: If3719de65b32773c2b6ff904da76a951dbfb11eb +Signed-off-by: Sreesudhan Ramakrish Ramkumar +--- + .../platform/msm/camera_v2/isp/msm_isp_util.c | 126 +++++++++++++-------- + .../msm/camera_v2/sensor/io/msm_camera_io_util.c | 11 ++ + .../msm/camera_v2/sensor/io/msm_camera_io_util.h | 2 + + 3 files changed, 89 insertions(+), 50 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +index c598555..ff213fc 100644 +--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c ++++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +@@ -917,7 +917,8 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, + /* Validate input parameters */ + switch (reg_cfg_cmd->cmd_type) { + case VFE_WRITE: +- case VFE_READ: { ++ case VFE_READ: ++ case VFE_WRITE_MB: { + if ((reg_cfg_cmd->u.rw_info.reg_offset > + (UINT_MAX - reg_cfg_cmd->u.rw_info.len)) || + ((reg_cfg_cmd->u.rw_info.reg_offset + +@@ -943,6 +944,58 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, + } + break; + } ++ ++ case VFE_WRITE_DMI_16BIT: ++ case VFE_WRITE_DMI_32BIT: ++ case VFE_WRITE_DMI_64BIT: ++ case VFE_READ_DMI_16BIT: ++ case VFE_READ_DMI_32BIT: ++ case VFE_READ_DMI_64BIT: { ++ if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) { ++ if ((reg_cfg_cmd->u.dmi_info.hi_tbl_offset <= ++ reg_cfg_cmd->u.dmi_info.lo_tbl_offset) || ++ (reg_cfg_cmd->u.dmi_info.hi_tbl_offset - ++ reg_cfg_cmd->u.dmi_info.lo_tbl_offset != ++ (sizeof(uint32_t)))) { ++ pr_err("%s:%d hi %d lo %d\n", ++ __func__, __LINE__, ++ reg_cfg_cmd->u.dmi_info.hi_tbl_offset, ++ reg_cfg_cmd->u.dmi_info.hi_tbl_offset); ++ return -EINVAL; ++ } ++ if (reg_cfg_cmd->u.dmi_info.len <= sizeof(uint32_t)) { ++ pr_err("%s:%d len %d\n", ++ __func__, __LINE__, ++ reg_cfg_cmd->u.dmi_info.len); ++ return -EINVAL; ++ } ++ if (((UINT_MAX - ++ reg_cfg_cmd->u.dmi_info.hi_tbl_offset) < ++ (reg_cfg_cmd->u.dmi_info.len - ++ sizeof(uint32_t))) || ++ ((reg_cfg_cmd->u.dmi_info.hi_tbl_offset + ++ reg_cfg_cmd->u.dmi_info.len - ++ sizeof(uint32_t)) > cmd_len)) { ++ pr_err("%s:%d hi_tbl_offset %d len %d cmd %d\n", ++ __func__, __LINE__, ++ reg_cfg_cmd->u.dmi_info.hi_tbl_offset, ++ reg_cfg_cmd->u.dmi_info.len, cmd_len); ++ return -EINVAL; ++ } ++ } ++ if ((reg_cfg_cmd->u.dmi_info.lo_tbl_offset > ++ (UINT_MAX - reg_cfg_cmd->u.dmi_info.len)) || ++ ((reg_cfg_cmd->u.dmi_info.lo_tbl_offset + ++ reg_cfg_cmd->u.dmi_info.len) > cmd_len)) { ++ pr_err("%s:%d lo_tbl_offset %d len %d cmd_len %d\n", ++ __func__, __LINE__, ++ reg_cfg_cmd->u.dmi_info.lo_tbl_offset, ++ reg_cfg_cmd->u.dmi_info.len, cmd_len); ++ return -EINVAL; ++ } ++ break; ++ } ++ + default: + break; + } +@@ -956,39 +1009,27 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, + break; + } + case VFE_WRITE_MB: { +- uint32_t *data_ptr = cfg_data + +- reg_cfg_cmd->u.rw_info.cmd_data_offset/4; +- +- if ((UINT_MAX - sizeof(*data_ptr) < +- reg_cfg_cmd->u.rw_info.reg_offset) || +- (resource_size(vfe_dev->vfe_mem) < +- reg_cfg_cmd->u.rw_info.reg_offset + +- sizeof(*data_ptr))) { +- pr_err("%s: VFE_WRITE_MB: Invalid length\n", __func__); +- return -EINVAL; +- } +- msm_camera_io_w_mb(*data_ptr, vfe_dev->vfe_base + +- reg_cfg_cmd->u.rw_info.reg_offset); ++ msm_camera_io_memcpy_mb(vfe_dev->vfe_base + ++ reg_cfg_cmd->u.rw_info.reg_offset, ++ cfg_data + reg_cfg_cmd->u.rw_info.cmd_data_offset/4, ++ reg_cfg_cmd->u.rw_info.len); + break; + } + case VFE_CFG_MASK: { + uint32_t temp; +- if (resource_size(vfe_dev->vfe_mem) < +- reg_cfg_cmd->u.mask_info.reg_offset) +- return -EINVAL; +- temp = msm_camera_io_r(vfe_dev->vfe_base + +- reg_cfg_cmd->u.mask_info.reg_offset); +- +- temp &= ~reg_cfg_cmd->u.mask_info.mask; +- temp |= reg_cfg_cmd->u.mask_info.val; + if ((UINT_MAX - sizeof(temp) < +- reg_cfg_cmd->u.mask_info.reg_offset) || ++ reg_cfg_cmd->u.mask_info.reg_offset) || + (resource_size(vfe_dev->vfe_mem) < + reg_cfg_cmd->u.mask_info.reg_offset + + sizeof(temp))) { + pr_err("%s: VFE_CFG_MASK: Invalid length\n", __func__); + return -EINVAL; + } ++ temp = msm_camera_io_r(vfe_dev->vfe_base + ++ reg_cfg_cmd->u.mask_info.reg_offset); ++ ++ temp &= ~reg_cfg_cmd->u.mask_info.mask; ++ temp |= reg_cfg_cmd->u.mask_info.val; + msm_camera_io_w(temp, vfe_dev->vfe_base + + reg_cfg_cmd->u.mask_info.reg_offset); + break; +@@ -1000,24 +1041,9 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, + uint32_t *hi_tbl_ptr = NULL, *lo_tbl_ptr = NULL; + uint32_t hi_val, lo_val, lo_val1; + if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) { +- if ((UINT_MAX - reg_cfg_cmd->u.dmi_info.hi_tbl_offset < +- reg_cfg_cmd->u.dmi_info.len - +- sizeof(uint32_t)) || +- (reg_cfg_cmd->u.dmi_info.hi_tbl_offset + +- reg_cfg_cmd->u.dmi_info.len - +- sizeof(uint32_t) > cmd_len)) { +- pr_err("Invalid Hi Table out of bounds\n"); +- return -EINVAL; +- } + hi_tbl_ptr = cfg_data + + reg_cfg_cmd->u.dmi_info.hi_tbl_offset/4; + } +- +- if (reg_cfg_cmd->u.dmi_info.lo_tbl_offset + +- reg_cfg_cmd->u.dmi_info.len > cmd_len) { +- pr_err("Invalid Lo Table out of bounds\n"); +- return -EINVAL; +- } + lo_tbl_ptr = cfg_data + + reg_cfg_cmd->u.dmi_info.lo_tbl_offset/4; + if (reg_cfg_cmd->cmd_type == VFE_WRITE_DMI_64BIT) +@@ -1050,24 +1076,17 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, + uint32_t *hi_tbl_ptr = NULL, *lo_tbl_ptr = NULL; + uint32_t hi_val, lo_val, lo_val1; + if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_64BIT) { +- if (reg_cfg_cmd->u.dmi_info.hi_tbl_offset + +- reg_cfg_cmd->u.dmi_info.len - +- sizeof(uint32_t) > cmd_len) { +- pr_err("Invalid Hi Table out of bounds\n"); +- return -EINVAL; +- } + hi_tbl_ptr = cfg_data + + reg_cfg_cmd->u.dmi_info.hi_tbl_offset/4; + } + +- if (reg_cfg_cmd->u.dmi_info.lo_tbl_offset + +- reg_cfg_cmd->u.dmi_info.len > cmd_len) { +- pr_err("Invalid Lo Table out of bounds\n"); +- return -EINVAL; +- } + lo_tbl_ptr = cfg_data + + reg_cfg_cmd->u.dmi_info.lo_tbl_offset/4; + ++ if (reg_cfg_cmd->cmd_type == VFE_READ_DMI_64BIT) ++ reg_cfg_cmd->u.dmi_info.len = ++ reg_cfg_cmd->u.dmi_info.len / 2; ++ + for (i = 0; i < reg_cfg_cmd->u.dmi_info.len/4; i++) { + lo_val = msm_camera_io_r(vfe_dev->vfe_base + + vfe_dev->hw_info->dmi_reg_offset + 0x4); +@@ -1121,7 +1140,7 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, + if ((data_ptr < cfg_data) || + (UINT_MAX / sizeof(*data_ptr) < + (data_ptr - cfg_data)) || +- (sizeof(*data_ptr) * (data_ptr - cfg_data) > ++ (sizeof(*data_ptr) * (data_ptr - cfg_data) >= + cmd_len)) + return -EINVAL; + *data_ptr++ = msm_camera_io_r(vfe_dev->vfe_base + +@@ -1187,6 +1206,13 @@ static int msm_isp_send_hw_cmd(struct vfe_device *vfe_dev, + case SET_WM_UB_SIZE: + break; + case SET_UB_POLICY: { ++ ++ if (cmd_len < sizeof(vfe_dev->vfe_ub_policy)) { ++ pr_err("%s:%d failed: invalid cmd len %u exp %zu\n", ++ __func__, __LINE__, cmd_len, ++ sizeof(vfe_dev->vfe_ub_policy)); ++ return -EINVAL; ++ } + vfe_dev->vfe_ub_policy = *cfg_data; + break; + } +diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c +index 78b9148..41c784a 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c ++++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.c +@@ -102,6 +102,17 @@ void msm_camera_io_memcpy(void __iomem *dest_addr, + msm_camera_io_dump(dest_addr, len); + } + ++void msm_camera_io_memcpy_mb(void __iomem *dest_addr, ++ void __iomem *src_addr, u32 len) ++{ ++ int i; ++ u32 *d = (u32 *) dest_addr; ++ u32 *s = (u32 *) src_addr; ++ ++ for (i = 0; i < (len / 4); i++) ++ msm_camera_io_w_mb(*s++, d++); ++} ++ + int msm_cam_clk_sel_src(struct device *dev, struct msm_cam_clk_info *clk_info, + struct msm_cam_clk_info *clk_src_info, int num_clk) + { +diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h +index fa9a283..2a0e21c 100644 +--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h ++++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_io_util.h +@@ -38,6 +38,8 @@ u32 msm_camera_io_r_mb(void __iomem *addr); + void msm_camera_io_dump(void __iomem *addr, int size); + void msm_camera_io_memcpy(void __iomem *dest_addr, + void __iomem *src_addr, u32 len); ++void msm_camera_io_memcpy_mb(void __iomem *dest_addr, ++ void __iomem *src_addr, u32 len); + int msm_cam_clk_sel_src(struct device *dev, struct msm_cam_clk_info *clk_info, + struct msm_cam_clk_info *clk_src_info, int num_clk); + int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info, +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2015-8939.patch b/patches/3.10/CVE-2015-8939.patch new file mode 100644 index 0000000..981abc0 --- /dev/null +++ b/patches/3.10/CVE-2015-8939.patch @@ -0,0 +1,66 @@ +From 884cff808385788fa620833c7e2160a4b98a21da Mon Sep 17 00:00:00 2001 +From: raghavendra ambadas +Date: Mon, 16 Mar 2015 18:10:35 +0530 +Subject: msm_fb: display: validate input args of mdp4_argc_process_write_req + +A bounds check has to be done for r/g/b stages variables +to avoid undetermined behaviour. + +Change-Id: Ibdc96e79b36cf188d4b5c42d8e2d9ece8e9ace8a +Signed-off-by: Raghavendra Ambadas +--- + drivers/video/msm/mdp4_util.c | 29 ++++++++++++++++++++++++++--- + 1 file changed, 26 insertions(+), 3 deletions(-) + +diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c +index f8b7f2f..cfcccdb 100644 +--- a/drivers/video/msm/mdp4_util.c ++++ b/drivers/video/msm/mdp4_util.c +@@ -2739,19 +2739,42 @@ static int mdp4_argc_process_write_req(uint32_t *offset, + struct mdp_ar_gc_lut_data r[MDP_AR_GC_MAX_STAGES]; + struct mdp_ar_gc_lut_data g[MDP_AR_GC_MAX_STAGES]; + struct mdp_ar_gc_lut_data b[MDP_AR_GC_MAX_STAGES]; ++ uint8_t num_r_stages; ++ uint8_t num_g_stages; ++ uint8_t num_b_stages; ++ ++ if (get_user(num_r_stages, &pgc_ptr->num_r_stages)) { ++ pr_err("%s failed: num_r_stages : Invalid arg\n", __func__); ++ return -EFAULT; ++ } ++ ++ if (get_user(num_g_stages, &pgc_ptr->num_g_stages)) { ++ pr_err("%s failed: num_g_stages : Invalid arg\n", __func__); ++ return -EFAULT; ++ } ++ ++ if (get_user(num_b_stages, &pgc_ptr->num_b_stages)) { ++ pr_err("%s failed: num_b_stages : Invalid arg\n", __func__); ++ return -EFAULT; ++ } ++ ++ if ((!num_r_stages || num_r_stages > MDP_AR_GC_MAX_STAGES) || ++ (!num_g_stages || num_g_stages > MDP_AR_GC_MAX_STAGES) || ++ (!num_b_stages || num_b_stages > MDP_AR_GC_MAX_STAGES)) ++ return -EINVAL; + + ret = copy_from_user(&r[0], pgc_ptr->r_data, +- pgc_ptr->num_r_stages * sizeof(struct mdp_ar_gc_lut_data)); ++ num_r_stages * sizeof(struct mdp_ar_gc_lut_data)); + + if (!ret) { + ret = copy_from_user(&g[0], + pgc_ptr->g_data, +- pgc_ptr->num_g_stages ++ num_g_stages + * sizeof(struct mdp_ar_gc_lut_data)); + if (!ret) + ret = copy_from_user(&b[0], + pgc_ptr->b_data, +- pgc_ptr->num_b_stages ++ num_b_stages + * sizeof(struct mdp_ar_gc_lut_data)); + } + +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2015-8940.patch b/patches/3.10/CVE-2015-8940.patch new file mode 100644 index 0000000..2a6b575 --- /dev/null +++ b/patches/3.10/CVE-2015-8940.patch @@ -0,0 +1,47 @@ +From e13ebd727d161db7003be6756e61283dce85fa3b Mon Sep 17 00:00:00 2001 +From: Bhalchandra Gajare +Date: Tue, 10 Feb 2015 14:44:36 -0800 +Subject: ASoC: q6lsm: Add check for integer overflow + +During sound model registration, the total memory size needed by the +sound model data is the sum of sound model length, number of zero +padding bytes and the calibration size. It is possible this sum +can result into integer overflow causing difficult to debug issues. +Add check for integer overflow to avoid such possible issues. + +CRs-fixed: 792367 +Change-Id: I9f451aa308214a4eac42b82e2abf1375c858ff30 +Signed-off-by: Bhalchandra Gajare +--- + sound/soc/msm/qdsp6v2/q6lsm.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/sound/soc/msm/qdsp6v2/q6lsm.c b/sound/soc/msm/qdsp6v2/q6lsm.c +index db29115..67be542 100644 +--- a/sound/soc/msm/qdsp6v2/q6lsm.c ++++ b/sound/soc/msm/qdsp6v2/q6lsm.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (c) 2013-2014, Linux Foundation. All rights reserved. ++ * Copyright (c) 2013-2015, Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and +@@ -1055,6 +1055,15 @@ int q6lsm_snd_model_buf_alloc(struct lsm_client *client, size_t len) + client->sound_model.size = len; + pad_zero = (LSM_ALIGN_BOUNDARY - + (len % LSM_ALIGN_BOUNDARY)); ++ if ((len > SIZE_MAX - pad_zero) || ++ (len + pad_zero > ++ SIZE_MAX - cal_block->cal_data.size)) { ++ pr_err("%s: invalid allocation size, len = %zd, pad_zero =%zd, cal_size = %zd\n", ++ __func__, len, pad_zero, ++ cal_block->cal_data.size); ++ rc = -EINVAL; ++ goto fail; ++ } + + total_mem = PAGE_ALIGN(pad_zero + len + + cal_block->cal_data.size); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2015-8941.patch b/patches/3.10/CVE-2015-8941.patch new file mode 100644 index 0000000..33f32b4 --- /dev/null +++ b/patches/3.10/CVE-2015-8941.patch @@ -0,0 +1,158 @@ +From d4d4d1dd626b21e68e78395bab3382c1eb04877f Mon Sep 17 00:00:00 2001 +From: Petar Sivenov +Date: Tue, 10 Feb 2015 13:46:18 +0200 +Subject: msm:camera:isp: fix array index bound checks + +This change fixes several incorrect or missing array index bound checks. + +Change-Id: Icd96555c01330ec11e94c6173d8df1973fe39c33 +Signed-off-by: Petar Sivenov +--- + .../platform/msm/camera_v2/isp/msm_isp_axi_util.c | 56 ++++++++++++++-------- + 1 file changed, 36 insertions(+), 20 deletions(-) + +diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +index e3be614..bc993cd 100644 +--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c ++++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +@@ -368,8 +368,8 @@ int msm_isp_axi_check_stream_state( + return -EINVAL; + + for (i = 0; i < stream_cfg_cmd->num_streams; i++) { +- if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]) +- > MAX_NUM_STREAM) { ++ if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]) >= ++ MAX_NUM_STREAM) { + return -EINVAL; + } + stream_info = &axi_data->stream_info[ +@@ -676,8 +676,10 @@ int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg) + &vfe_dev->axi_data, stream_cfg_cmd); + if (rc) { + pr_err("%s: Request validation failed\n", __func__); +- msm_isp_axi_destroy_stream(&vfe_dev->axi_data, +- HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)); ++ if (HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle) < ++ MAX_NUM_STREAM) ++ msm_isp_axi_destroy_stream(&vfe_dev->axi_data, ++ HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)); + return rc; + } + stream_info = &vfe_dev->axi_data. +@@ -748,11 +750,17 @@ int msm_isp_release_axi_stream(struct vfe_device *vfe_dev, void *arg) + int rc = 0, i; + struct msm_vfe_axi_stream_release_cmd *stream_release_cmd = arg; + struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; +- struct msm_vfe_axi_stream *stream_info = +- &axi_data->stream_info[ +- HANDLE_TO_IDX(stream_release_cmd->stream_handle)]; ++ struct msm_vfe_axi_stream *stream_info; + struct msm_vfe_axi_stream_cfg_cmd stream_cfg; + ++ ++ if (HANDLE_TO_IDX(stream_release_cmd->stream_handle) >= ++ MAX_NUM_STREAM) { ++ pr_err("%s: Invalid stream handle\n", __func__); ++ return -EINVAL; ++ } ++ stream_info = &axi_data->stream_info[ ++ HANDLE_TO_IDX(stream_release_cmd->stream_handle)]; + if (stream_info->state == AVALIABLE) { + pr_err("%s: Stream already released\n", __func__); + return -EINVAL; +@@ -1069,6 +1077,11 @@ static void msm_isp_process_done_buf(struct vfe_device *vfe_dev, + uint8_t drop_frame = 0; + memset(&buf_event, 0, sizeof(buf_event)); + ++ if (stream_idx >= MAX_NUM_STREAM) { ++ pr_err("%s: Invalid stream_idx", __func__); ++ return; ++ } ++ + frame_id = vfe_dev->axi_data. + src_info[SRC_TO_INTF(stream_info->stream_src)].frame_id; + +@@ -1235,8 +1248,8 @@ static void msm_isp_update_camif_output_count( + return; + + for (i = 0; i < stream_cfg_cmd->num_streams; i++) { +- if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]) +- > MAX_NUM_STREAM) { ++ if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]) >= ++ MAX_NUM_STREAM) { + return; + } + stream_info = +@@ -1535,8 +1548,8 @@ static int msm_isp_axi_update_cgc_override(struct vfe_device *vfe_dev, + return -EINVAL; + + for (i = 0; i < stream_cfg_cmd->num_streams; i++) { +- if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]) +- > MAX_NUM_STREAM) { ++ if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]) >= ++ MAX_NUM_STREAM) { + return -EINVAL; + } + stream_info = &axi_data->stream_info[ +@@ -1567,8 +1580,8 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev, + return -EINVAL; + + for (i = 0; i < stream_cfg_cmd->num_streams; i++) { +- if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]) +- > MAX_NUM_STREAM) { ++ if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]) >= ++ MAX_NUM_STREAM) { + return -EINVAL; + } + stream_info = &axi_data->stream_info[ +@@ -1651,8 +1664,8 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev, + return -EINVAL; + + for (i = 0; i < stream_cfg_cmd->num_streams; i++) { +- if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]) +- > MAX_NUM_STREAM) { ++ if (HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]) >= ++ MAX_NUM_STREAM) { + return -EINVAL; + } + stream_info = &axi_data->stream_info[ +@@ -1916,8 +1929,8 @@ int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg) + for (i = 0; i < update_cmd->num_streams; i++) { + update_info = &update_cmd->update_info[i]; + /*check array reference bounds*/ +- if (HANDLE_TO_IDX(update_info->stream_handle) +- > MAX_NUM_STREAM) { ++ if (HANDLE_TO_IDX(update_info->stream_handle) >= ++ MAX_NUM_STREAM) { + return -EINVAL; + } + stream_info = &axi_data->stream_info[ +@@ -2082,7 +2095,9 @@ void msm_isp_process_axi_irq(struct vfe_device *vfe_dev, + comp_info = &axi_data->composite_info[i]; + wm_mask &= ~(comp_info->stream_composite_mask); + if (comp_mask & (1 << i)) { +- if (!comp_info->stream_handle) { ++ stream_idx = HANDLE_TO_IDX(comp_info->stream_handle); ++ if ((!comp_info->stream_handle) || ++ (stream_idx >= MAX_NUM_STREAM)) { + pr_err("%s: Invalid handle for composite irq\n", + __func__); + continue; +@@ -2118,12 +2133,13 @@ void msm_isp_process_axi_irq(struct vfe_device *vfe_dev, + + for (i = 0; i < axi_data->hw_info->num_wm; i++) { + if (wm_mask & (1 << i)) { +- if (!axi_data->free_wm[i]) { ++ stream_idx = HANDLE_TO_IDX(axi_data->free_wm[i]); ++ if ((!axi_data->free_wm[i]) || ++ (stream_idx >= MAX_NUM_STREAM)) { + pr_err("%s: Invalid handle for wm irq\n", + __func__); + continue; + } +- stream_idx = HANDLE_TO_IDX(axi_data->free_wm[i]); + stream_info = &axi_data->stream_info[stream_idx]; + ISP_DBG("%s: stream id %x frame id: 0x%x\n", __func__, + stream_info->stream_id, stream_info->frame_id); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2015-8943.patch b/patches/3.10/CVE-2015-8943.patch new file mode 100644 index 0000000..177829f --- /dev/null +++ b/patches/3.10/CVE-2015-8943.patch @@ -0,0 +1,61 @@ +From ad376e4053b87bd58f62f45b6df2c5544bc21aee Mon Sep 17 00:00:00 2001 +From: Jayant Shekhar +Date: Tue, 20 Jan 2015 16:12:43 +0530 +Subject: msm: mdss: Unmap only when buffer was mapped + +Currently buffer is unmapped if iommu is attached. +This can lead to potential unmap issues if wrong +addresses are sent and are tried to unmap without +mapping. Hence ensure unmap is done only when +buffer is mapped. + +Change-Id: I6d7f1eb1e951cd314a4c3c35551c87930af5118e +Signed-off-by: Jayant Shekhar +--- + drivers/video/msm/mdss/mdss_mdp.h | 1 + + drivers/video/msm/mdss/mdss_mdp_util.c | 4 +++- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h +index f5f5770..99ea0cd 100644 +--- a/drivers/video/msm/mdss/mdss_mdp.h ++++ b/drivers/video/msm/mdss/mdss_mdp.h +@@ -279,6 +279,7 @@ struct mdss_mdp_img_data { + u32 len; + u32 flags; + int p_need; ++ bool mapped; + struct file *srcp_file; + struct ion_handle *srcp_ihdl; + }; +diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c +index 01745fd..dd93dce 100644 +--- a/drivers/video/msm/mdss/mdss_mdp_util.c ++++ b/drivers/video/msm/mdss/mdss_mdp_util.c +@@ -502,7 +502,7 @@ int mdss_mdp_put_img(struct mdss_mdp_img_data *data) + pr_err("invalid ion client\n"); + return -ENOMEM; + } else { +- if (is_mdss_iommu_attached()) { ++ if (data->mapped) { + int domain; + if (data->flags & MDP_SECURE_OVERLAY_SESSION) + domain = MDSS_IOMMU_DOMAIN_SECURE; +@@ -515,6 +515,7 @@ int mdss_mdp_put_img(struct mdss_mdp_img_data *data) + msm_ion_unsecure_buffer(iclient, + data->srcp_ihdl); + } ++ data->mapped = false; + } + ion_free(iclient, data->srcp_ihdl); + data->srcp_ihdl = NULL; +@@ -593,6 +594,7 @@ int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data) + if (ret && (domain == MDSS_IOMMU_DOMAIN_SECURE)) + msm_ion_unsecure_buffer(iclient, + data->srcp_ihdl); ++ data->mapped = true; + } else { + ret = ion_phys(iclient, data->srcp_ihdl, start, + (size_t *) len); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2016-2185.patch b/patches/3.10/CVE-2016-2185.patch new file mode 100644 index 0000000..4418e3b --- /dev/null +++ b/patches/3.10/CVE-2016-2185.patch @@ -0,0 +1,108 @@ +From 950336ba3e4a1ffd2ca60d29f6ef386dd2c7351d Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Wed, 23 Mar 2016 11:53:46 -0700 +Subject: Input: ati_remote2 - fix crashes on detecting device with invalid + descriptor + +The ati_remote2 driver expects at least two interfaces with one +endpoint each. If given malicious descriptor that specify one +interface or no endpoints, it will crash in the probe function. +Ensure there is at least two interfaces and one endpoint for each +interface before using it. + +The full disclosure: http://seclists.org/bugtraq/2016/Mar/90 + +Reported-by: Ralf Spenneberg +Signed-off-by: Vladis Dronov +Cc: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +--- + drivers/input/misc/ati_remote2.c | 36 ++++++++++++++++++++++++++++++------ + 1 file changed, 30 insertions(+), 6 deletions(-) + +diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c +index cfd58e8..1c5914c 100644 +--- a/drivers/input/misc/ati_remote2.c ++++ b/drivers/input/misc/ati_remote2.c +@@ -817,26 +817,49 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d + + ar2->udev = udev; + ++ /* Sanity check, first interface must have an endpoint */ ++ if (alt->desc.bNumEndpoints < 1 || !alt->endpoint) { ++ dev_err(&interface->dev, ++ "%s(): interface 0 must have an endpoint\n", __func__); ++ r = -ENODEV; ++ goto fail1; ++ } + ar2->intf[0] = interface; + ar2->ep[0] = &alt->endpoint[0].desc; + ++ /* Sanity check, the device must have two interfaces */ + ar2->intf[1] = usb_ifnum_to_if(udev, 1); ++ if ((udev->actconfig->desc.bNumInterfaces < 2) || !ar2->intf[1]) { ++ dev_err(&interface->dev, "%s(): need 2 interfaces, found %d\n", ++ __func__, udev->actconfig->desc.bNumInterfaces); ++ r = -ENODEV; ++ goto fail1; ++ } ++ + r = usb_driver_claim_interface(&ati_remote2_driver, ar2->intf[1], ar2); + if (r) + goto fail1; ++ ++ /* Sanity check, second interface must have an endpoint */ + alt = ar2->intf[1]->cur_altsetting; ++ if (alt->desc.bNumEndpoints < 1 || !alt->endpoint) { ++ dev_err(&interface->dev, ++ "%s(): interface 1 must have an endpoint\n", __func__); ++ r = -ENODEV; ++ goto fail2; ++ } + ar2->ep[1] = &alt->endpoint[0].desc; + + r = ati_remote2_urb_init(ar2); + if (r) +- goto fail2; ++ goto fail3; + + ar2->channel_mask = channel_mask; + ar2->mode_mask = mode_mask; + + r = ati_remote2_setup(ar2, ar2->channel_mask); + if (r) +- goto fail2; ++ goto fail3; + + usb_make_path(udev, ar2->phys, sizeof(ar2->phys)); + strlcat(ar2->phys, "/input0", sizeof(ar2->phys)); +@@ -845,11 +868,11 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d + + r = sysfs_create_group(&udev->dev.kobj, &ati_remote2_attr_group); + if (r) +- goto fail2; ++ goto fail3; + + r = ati_remote2_input_init(ar2); + if (r) +- goto fail3; ++ goto fail4; + + usb_set_intfdata(interface, ar2); + +@@ -857,10 +880,11 @@ static int ati_remote2_probe(struct usb_interface *interface, const struct usb_d + + return 0; + +- fail3: ++ fail4: + sysfs_remove_group(&udev->dev.kobj, &ati_remote2_attr_group); +- fail2: ++ fail3: + ati_remote2_urb_cleanup(ar2); ++ fail2: + usb_driver_release_interface(&ati_remote2_driver, ar2->intf[1]); + fail1: + kfree(ar2); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2016-2186.patch b/patches/3.10/CVE-2016-2186.patch new file mode 100644 index 0000000..6ea57db --- /dev/null +++ b/patches/3.10/CVE-2016-2186.patch @@ -0,0 +1,37 @@ +From 9c6ba456711687b794dcf285856fc14e2c76074f Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Mon, 14 Mar 2016 09:33:40 -0700 +Subject: Input: powermate - fix oops with malicious USB descriptors + +The powermate driver expects at least one valid USB endpoint in its +probe function. If given malicious descriptors that specify 0 for +the number of endpoints, it will crash. Validate the number of +endpoints on the interface before using them. + +The full report for this issue can be found here: +http://seclists.org/bugtraq/2016/Mar/85 + +Reported-by: Ralf Spenneberg +Cc: stable +Signed-off-by: Josh Boyer +Signed-off-by: Dmitry Torokhov +--- + drivers/input/misc/powermate.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c +index 63b539d..84909a1 100644 +--- a/drivers/input/misc/powermate.c ++++ b/drivers/input/misc/powermate.c +@@ -307,6 +307,9 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i + int error = -ENOMEM; + + interface = intf->cur_altsetting; ++ if (interface->desc.bNumEndpoints < 1) ++ return -EINVAL; ++ + endpoint = &interface->endpoint[0].desc; + if (!usb_endpoint_is_int_in(endpoint)) + return -EIO; +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2016-2187.patch b/patches/3.10/CVE-2016-2187.patch new file mode 100644 index 0000000..26faa9f --- /dev/null +++ b/patches/3.10/CVE-2016-2187.patch @@ -0,0 +1,55 @@ +From 162f98dea487206d9ab79fc12ed64700667a894d Mon Sep 17 00:00:00 2001 +From: Vladis Dronov +Date: Thu, 31 Mar 2016 10:53:42 -0700 +Subject: Input: gtco - fix crash on detecting device without endpoints + +The gtco driver expects at least one valid endpoint. If given malicious +descriptors that specify 0 for the number of endpoints, it will crash in +the probe function. Ensure there is at least one endpoint on the interface +before using it. + +Also let's fix a minor coding style issue. + +The full correct report of this issue can be found in the public +Red Hat Bugzilla: + +https://bugzilla.redhat.com/show_bug.cgi?id=1283385 + +Reported-by: Ralf Spenneberg +Signed-off-by: Vladis Dronov +Cc: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +--- + drivers/input/tablet/gtco.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c +index 3a7f3a4..7c18249 100644 +--- a/drivers/input/tablet/gtco.c ++++ b/drivers/input/tablet/gtco.c +@@ -858,6 +858,14 @@ static int gtco_probe(struct usb_interface *usbinterface, + goto err_free_buf; + } + ++ /* Sanity check that a device has an endpoint */ ++ if (usbinterface->altsetting[0].desc.bNumEndpoints < 1) { ++ dev_err(&usbinterface->dev, ++ "Invalid number of endpoints\n"); ++ error = -EINVAL; ++ goto err_free_urb; ++ } ++ + /* + * The endpoint is always altsetting 0, we know this since we know + * this device only has one interrupt endpoint +@@ -879,7 +887,7 @@ static int gtco_probe(struct usb_interface *usbinterface, + * HID report descriptor + */ + if (usb_get_extra_descriptor(usbinterface->cur_altsetting, +- HID_DEVICE_TYPE, &hid_desc) != 0){ ++ HID_DEVICE_TYPE, &hid_desc) != 0) { + dev_err(&usbinterface->dev, + "Can't retrieve exta USB descriptor to get hid report descriptor length\n"); + error = -EIO; +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2016-2188.patch b/patches/3.10/CVE-2016-2188.patch new file mode 100644 index 0000000..a068f43 --- /dev/null +++ b/patches/3.10/CVE-2016-2188.patch @@ -0,0 +1,40 @@ +From 4ec0ef3a82125efc36173062a50624550a900ae0 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Mon, 14 Mar 2016 10:42:38 -0400 +Subject: USB: iowarrior: fix oops with malicious USB descriptors + +The iowarrior driver expects at least one valid endpoint. If given +malicious descriptors that specify 0 for the number of endpoints, +it will crash in the probe function. Ensure there is at least +one endpoint on the interface before using it. + +The full report of this issue can be found here: +http://seclists.org/bugtraq/2016/Mar/87 + +Reported-by: Ralf Spenneberg +Cc: stable +Signed-off-by: Josh Boyer +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/misc/iowarrior.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c +index c6bfd13..1950e87 100644 +--- a/drivers/usb/misc/iowarrior.c ++++ b/drivers/usb/misc/iowarrior.c +@@ -787,6 +787,12 @@ static int iowarrior_probe(struct usb_interface *interface, + iface_desc = interface->cur_altsetting; + dev->product_id = le16_to_cpu(udev->descriptor.idProduct); + ++ if (iface_desc->desc.bNumEndpoints < 1) { ++ dev_err(&interface->dev, "Invalid number of endpoints\n"); ++ retval = -EINVAL; ++ goto error; ++ } ++ + /* set up the endpoint information */ + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2016-3136.patch b/patches/3.10/CVE-2016-3136.patch new file mode 100644 index 0000000..3a3e5f7 --- /dev/null +++ b/patches/3.10/CVE-2016-3136.patch @@ -0,0 +1,48 @@ +From 4e9a0b05257f29cf4b75f3209243ed71614d062e Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 31 Mar 2016 12:04:24 -0400 +Subject: USB: mct_u232: add sanity checking in probe + +An attack using the lack of sanity checking in probe is known. This +patch checks for the existence of a second port. + +CVE-2016-3136 + +Signed-off-by: Oliver Neukum +CC: stable@vger.kernel.org +[johan: add error message ] +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/serial/mct_u232.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c +index 4446b8d..8856553 100644 +--- a/drivers/usb/serial/mct_u232.c ++++ b/drivers/usb/serial/mct_u232.c +@@ -376,14 +376,21 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port, + + static int mct_u232_port_probe(struct usb_serial_port *port) + { ++ struct usb_serial *serial = port->serial; + struct mct_u232_private *priv; + ++ /* check first to simplify error handling */ ++ if (!serial->port[1] || !serial->port[1]->interrupt_in_urb) { ++ dev_err(&port->dev, "expected endpoint missing\n"); ++ return -ENODEV; ++ } ++ + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + /* Use second interrupt-in endpoint for reading. */ +- priv->read_urb = port->serial->port[1]->interrupt_in_urb; ++ priv->read_urb = serial->port[1]->interrupt_in_urb; + priv->read_urb->context = port; + + spin_lock_init(&priv->lock); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2016-3140.patch b/patches/3.10/CVE-2016-3140.patch new file mode 100644 index 0000000..3c10f92 --- /dev/null +++ b/patches/3.10/CVE-2016-3140.patch @@ -0,0 +1,53 @@ +From 5a07975ad0a36708c6b0a5b9fea1ff811d0b0c1f Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 31 Mar 2016 12:04:26 -0400 +Subject: USB: digi_acceleport: do sanity checking for the number of ports + +The driver can be crashed with devices that expose crafted descriptors +with too few endpoints. + +See: http://seclists.org/bugtraq/2016/Mar/61 + +Signed-off-by: Oliver Neukum +[johan: fix OOB endpoint check and add error messages ] +Cc: stable +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/serial/digi_acceleport.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c +index 010a42a..16e8e37 100644 +--- a/drivers/usb/serial/digi_acceleport.c ++++ b/drivers/usb/serial/digi_acceleport.c +@@ -1251,8 +1251,27 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num) + + static int digi_startup(struct usb_serial *serial) + { ++ struct device *dev = &serial->interface->dev; + struct digi_serial *serial_priv; + int ret; ++ int i; ++ ++ /* check whether the device has the expected number of endpoints */ ++ if (serial->num_port_pointers < serial->type->num_ports + 1) { ++ dev_err(dev, "OOB endpoints missing\n"); ++ return -ENODEV; ++ } ++ ++ for (i = 0; i < serial->type->num_ports + 1 ; i++) { ++ if (!serial->port[i]->read_urb) { ++ dev_err(dev, "bulk-in endpoint missing\n"); ++ return -ENODEV; ++ } ++ if (!serial->port[i]->write_urb) { ++ dev_err(dev, "bulk-out endpoint missing\n"); ++ return -ENODEV; ++ } ++ } + + serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL); + if (!serial_priv) +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2016-3689.patch b/patches/3.10/CVE-2016-3689.patch new file mode 100644 index 0000000..fd4b556 --- /dev/null +++ b/patches/3.10/CVE-2016-3689.patch @@ -0,0 +1,39 @@ +From a0ad220c96692eda76b2e3fd7279f3dcd1d8a8ff Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Thu, 17 Mar 2016 14:00:17 -0700 +Subject: Input: ims-pcu - sanity check against missing interfaces + +A malicious device missing interface can make the driver oops. +Add sanity checking. + +Signed-off-by: Oliver Neukum +CC: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +--- + drivers/input/misc/ims-pcu.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c +index ac1fa5f..9c0ea36 100644 +--- a/drivers/input/misc/ims-pcu.c ++++ b/drivers/input/misc/ims-pcu.c +@@ -1663,6 +1663,8 @@ static int ims_pcu_parse_cdc_data(struct usb_interface *intf, struct ims_pcu *pc + + pcu->ctrl_intf = usb_ifnum_to_if(pcu->udev, + union_desc->bMasterInterface0); ++ if (!pcu->ctrl_intf) ++ return -EINVAL; + + alt = pcu->ctrl_intf->cur_altsetting; + pcu->ep_ctrl = &alt->endpoint[0].desc; +@@ -1670,6 +1672,8 @@ static int ims_pcu_parse_cdc_data(struct usb_interface *intf, struct ims_pcu *pc + + pcu->data_intf = usb_ifnum_to_if(pcu->udev, + union_desc->bSlaveInterface0); ++ if (!pcu->data_intf) ++ return -EINVAL; + + alt = pcu->data_intf->cur_altsetting; + if (alt->desc.bNumEndpoints != 2) { +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2016-3857.patch b/patches/3.10/CVE-2016-3857.patch new file mode 100644 index 0000000..9adf98b --- /dev/null +++ b/patches/3.10/CVE-2016-3857.patch @@ -0,0 +1,51 @@ +From d948109df11c8485e972b4cc0eb4820d4b754615 Mon Sep 17 00:00:00 2001 +From: Dave Weinstein +Date: Thu, 28 Jul 2016 11:55:41 -0700 +Subject: arm: oabi compat: add missing access checks + +commit 7de249964f5578e67b99699c5f0b405738d820a2 upstream. + +Add access checks to sys_oabi_epoll_wait() and sys_oabi_semtimedop(). +This fixes CVE-2016-3857, a local privilege escalation under +CONFIG_OABI_COMPAT. + +Cc: stable@vger.kernel.org +Reported-by: Chiachih Wu +Reviewed-by: Kees Cook +Reviewed-by: Nicolas Pitre +Signed-off-by: Dave Weinstein +Signed-off-by: Linus Torvalds +Signed-off-by: Willy Tarreau +--- + arch/arm/kernel/sys_oabi-compat.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c +index 3e94811..a0aee80 100644 +--- a/arch/arm/kernel/sys_oabi-compat.c ++++ b/arch/arm/kernel/sys_oabi-compat.c +@@ -275,8 +275,12 @@ asmlinkage long sys_oabi_epoll_wait(int epfd, + mm_segment_t fs; + long ret, err, i; + +- if (maxevents <= 0 || maxevents > (INT_MAX/sizeof(struct epoll_event))) ++ if (maxevents <= 0 || ++ maxevents > (INT_MAX/sizeof(*kbuf)) || ++ maxevents > (INT_MAX/sizeof(*events))) + return -EINVAL; ++ if (!access_ok(VERIFY_WRITE, events, sizeof(*events) * maxevents)) ++ return -EFAULT; + kbuf = kmalloc(sizeof(*kbuf) * maxevents, GFP_KERNEL); + if (!kbuf) + return -ENOMEM; +@@ -313,6 +317,8 @@ asmlinkage long sys_oabi_semtimedop(int semid, + + if (nsops < 1 || nsops > SEMOPM) + return -EINVAL; ++ if (!access_ok(VERIFY_READ, tsops, sizeof(*tsops) * nsops)) ++ return -EFAULT; + sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL); + if (!sops) + return -ENOMEM; +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2016-5340.patch b/patches/3.10/CVE-2016-5340.patch new file mode 100644 index 0000000..2a23d8b --- /dev/null +++ b/patches/3.10/CVE-2016-5340.patch @@ -0,0 +1,81 @@ +From 06e51489061e5473b4e2035c79dcf7c27a6f75a6 Mon Sep 17 00:00:00 2001 +From: Sunil Khatri +Date: Wed, 22 Jun 2016 14:45:31 +0530 +Subject: ashmem: Validate ashmem memory with fops pointer + +Validate the ashmem memory entry against f_op pointer +rather then comparing its name with path of the dentry. + +This is to avoid any invalid access to ashmem area in cases +where some one deliberately set the dentry name to /ashmem. + +Change-Id: I74e50cd244f68cb13009cf2355e528485f4de34b +Signed-off-by: Sunil Khatri +--- + drivers/staging/android/ashmem.c | 42 +++++++++++++++++++--------------------- + 1 file changed, 20 insertions(+), 22 deletions(-) + +diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c +index 808acd4..ee79ac8 100644 +--- a/drivers/staging/android/ashmem.c ++++ b/drivers/staging/android/ashmem.c +@@ -766,11 +766,28 @@ static long compat_ashmem_ioctl(struct file *file, unsigned int cmd, unsigned lo + } + #endif + ++static const struct file_operations ashmem_fops = { ++ .owner = THIS_MODULE, ++ .open = ashmem_open, ++ .release = ashmem_release, ++ .read = ashmem_read, ++ .llseek = ashmem_llseek, ++ .mmap = ashmem_mmap, ++ .unlocked_ioctl = ashmem_ioctl, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = compat_ashmem_ioctl, ++#endif ++}; ++ ++static struct miscdevice ashmem_misc = { ++ .minor = MISC_DYNAMIC_MINOR, ++ .name = "ashmem", ++ .fops = &ashmem_fops, ++}; ++ + static int is_ashmem_file(struct file *file) + { +- char fname[256], *name; +- name = dentry_path(file->f_dentry, fname, 256); +- return strcmp(name, "/ashmem") ? 0 : 1; ++ return (file->f_op == &ashmem_fops); + } + + int get_ashmem_file(int fd, struct file **filp, struct file **vm_file, +@@ -819,25 +836,6 @@ void put_ashmem_file(struct file *file) + } + EXPORT_SYMBOL(put_ashmem_file); + +-static const struct file_operations ashmem_fops = { +- .owner = THIS_MODULE, +- .open = ashmem_open, +- .release = ashmem_release, +- .read = ashmem_read, +- .llseek = ashmem_llseek, +- .mmap = ashmem_mmap, +- .unlocked_ioctl = ashmem_ioctl, +-#ifdef CONFIG_COMPAT +- .compat_ioctl = compat_ashmem_ioctl, +-#endif +-}; +- +-static struct miscdevice ashmem_misc = { +- .minor = MISC_DYNAMIC_MINOR, +- .name = "ashmem", +- .fops = &ashmem_fops, +-}; +- + static int __init ashmem_init(void) + { + int ret; +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2016-8453.patch b/patches/3.10/CVE-2016-8453.patch new file mode 100644 index 0000000..d12a6d3 --- /dev/null +++ b/patches/3.10/CVE-2016-8453.patch @@ -0,0 +1,46 @@ +From 15a311f8810581867d31022ec6b2a2ba343302a2 Mon Sep 17 00:00:00 2001 +From: Mekala Natarajan +Date: Tue, 13 Oct 2015 11:17:30 -0700 +Subject: [PATCH] ASoC: msm-cpe-lsm: move slimbus channel open to LAB thread + +Opening Slimbus channels before starting the lab thread can +lead to issues, when CPE LAB thread stop is called after opening +Slimbus master/slave ports, but before scheduling LAB thread. +In this case, error will be returned when trying to stop the +LAB thread and if not closed cleanly, Slimbus channel open for +next CPE session will fail. This will result in failure for all +subsequent CPE LAB sessions. +Move Slimbus channel open inside LAB thread so that the channels +are opened only after creating and scheduling the LAB thread. + +Bug: 24774316 +Bug: 24872437 +Change-Id: I014fe6aed34dcaa896e1aa7a45a898485e783dd8 +Signed-off-by: Banajit Goswami +Signed-off-by: Mekala Natarajan +--- + sound/soc/msm/msm-cpe-lsm.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c +index 8cc10f7bc8283..8673f80207061 100644 +--- a/sound/soc/msm/msm-cpe-lsm.c ++++ b/sound/soc/msm/msm-cpe-lsm.c +@@ -396,6 +396,8 @@ static int msm_cpe_lab_thread(void *data) + } + + if (!kthread_should_stop()) { ++ lsm_ops->lsm_lab_data_channel_open(cpe->core_handle, session); ++ + rc = lsm_ops->lsm_lab_data_channel_read(core, lab->lsm_s, + lab->pcm_buf[0].phys, + lab->pcm_buf[0].mem, +@@ -1320,8 +1322,6 @@ static int msm_cpe_lsm_lab_start(struct snd_pcm_substream *substream, + atomic_set(&lab_sess->abort_read, 0); + pr_debug("%s: KW detected,\n" + "scheduling LAB thread\n", __func__); +- lsm_ops->lsm_lab_data_channel_open( +- cpe->core_handle, session); + + /* + * Even though thread might be only scheduled and \ No newline at end of file diff --git a/patches/3.10/CVE-2016-8454.patch b/patches/3.10/CVE-2016-8454.patch new file mode 100644 index 0000000..32954bb --- /dev/null +++ b/patches/3.10/CVE-2016-8454.patch @@ -0,0 +1,264 @@ +From 39bd1fc23040a441628884588b19bc4d199b59c2 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Tue, 8 Nov 2016 11:19:43 -0800 +Subject: [PATCH] net: wireless: bcmdhd: fix overrun in dhd_pno_set_cfg_gscan + +1. added limit check for GSCAN-PNO max channel bucket +2. added length check in each NL TLV parsing and error handling + +Bug: 32174590 + +Signed-off-by: Insun Song +Change-Id: Ic946bfa3b3ab6b2b201043371c27ee7dbedb7e75 +--- + drivers/net/wireless/bcmdhd/wl_cfgvendor.c | 210 +++++++++++++++++++---------- + 1 file changed, 142 insertions(+), 68 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +index 3239bf53a5f1d..b536de31010a9 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +@@ -510,23 +510,113 @@ static int wl_cfgvendor_enable_full_scan_result(struct wiphy *wiphy, + return err; + } + +-static int wl_cfgvendor_set_scan_cfg(struct wiphy *wiphy, +- struct wireless_dev *wdev, const void *data, int len) ++static int ++wl_cfgvendor_set_scan_cfg_bucket(const struct nlattr *prev, ++ gscan_scan_params_t *scan_param, int num) ++{ ++ struct dhd_pno_gscan_channel_bucket *ch_bucket; ++ int k = 0; ++ int type, err = 0, rem; ++ const struct nlattr *cur, *next; ++ ++ nla_for_each_nested(cur, prev, rem) { ++ type = nla_type(cur); ++ ch_bucket = scan_param->channel_bucket; ++ switch (type) { ++ case GSCAN_ATTRIBUTE_BUCKET_ID: ++ break; ++ case GSCAN_ATTRIBUTE_BUCKET_PERIOD: ++ if (nla_len(cur) != sizeof(uint32)) { ++ err = -EINVAL; ++ goto exit; ++ } ++ ++ ch_bucket[num].bucket_freq_multiple = ++ nla_get_u32(cur) / MSEC_PER_SEC; ++ break; ++ case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS: ++ if (nla_len(cur) != sizeof(uint32)) { ++ err = -EINVAL; ++ goto exit; ++ } ++ ch_bucket[num].num_channels = nla_get_u32(cur); ++ if (ch_bucket[num].num_channels > ++ GSCAN_MAX_CHANNELS_IN_BUCKET) { ++ WL_ERR(("channel range:%d,bucket:%d\n", ++ ch_bucket[num].num_channels, ++ num)); ++ err = -EINVAL; ++ goto exit; ++ } ++ break; ++ case GSCAN_ATTRIBUTE_BUCKET_CHANNELS: ++ nla_for_each_nested(next, cur, rem) { ++ if (k >= GSCAN_MAX_CHANNELS_IN_BUCKET) ++ break; ++ if (nla_len(next) != sizeof(uint32)) { ++ err = -EINVAL; ++ goto exit; ++ } ++ ch_bucket[num].chan_list[k] = nla_get_u32(next); ++ k++; ++ } ++ break; ++ case GSCAN_ATTRIBUTE_BUCKETS_BAND: ++ if (nla_len(cur) != sizeof(uint32)) { ++ err = -EINVAL; ++ goto exit; ++ } ++ ch_bucket[num].band = (uint16)nla_get_u32(cur); ++ break; ++ case GSCAN_ATTRIBUTE_REPORT_EVENTS: ++ if (nla_len(cur) != sizeof(uint32)) { ++ err = -EINVAL; ++ goto exit; ++ } ++ ch_bucket[num].report_flag = (uint8)nla_get_u32(cur); ++ break; ++ case GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT: ++ if (nla_len(cur) != sizeof(uint32)) { ++ err = -EINVAL; ++ goto exit; ++ } ++ ch_bucket[num].repeat = (uint16)nla_get_u32(cur); ++ break; ++ case GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD: ++ if (nla_len(cur) != sizeof(uint32)) { ++ err = -EINVAL; ++ goto exit; ++ } ++ ch_bucket[num].bucket_max_multiple = ++ nla_get_u32(cur) / MSEC_PER_SEC; ++ break; ++ default: ++ WL_ERR(("unknown attr type:%d\n", type)); ++ err = -EINVAL; ++ goto exit; ++ } ++ } ++ ++exit: ++ return err; ++} ++ ++static int ++wl_cfgvendor_set_scan_cfg(struct wiphy *wiphy, struct wireless_dev *wdev, ++ const void *data, int len) + { + int err = 0; + struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); + gscan_scan_params_t *scan_param; + int j = 0; +- int type, tmp, tmp1, tmp2, k = 0; +- const struct nlattr *iter, *iter1, *iter2; +- struct dhd_pno_gscan_channel_bucket *ch_bucket; ++ int type, tmp; ++ const struct nlattr *iter; + + scan_param = kzalloc(sizeof(gscan_scan_params_t), GFP_KERNEL); + if (!scan_param) { + WL_ERR(("Could not set GSCAN scan cfg, mem alloc failure\n")); + err = -EINVAL; + return err; +- + } + + scan_param->scan_fr = PNO_SCAN_MIN_FW_SEC; +@@ -537,77 +627,61 @@ static int wl_cfgvendor_set_scan_cfg(struct wiphy *wiphy, + break; + + switch (type) { +- case GSCAN_ATTRIBUTE_BASE_PERIOD: +- scan_param->scan_fr = nla_get_u32(iter)/1000; +- break; +- case GSCAN_ATTRIBUTE_NUM_BUCKETS: +- scan_param->nchannel_buckets = nla_get_u32(iter); +- break; +- case GSCAN_ATTRIBUTE_CH_BUCKET_1: +- case GSCAN_ATTRIBUTE_CH_BUCKET_2: +- case GSCAN_ATTRIBUTE_CH_BUCKET_3: +- case GSCAN_ATTRIBUTE_CH_BUCKET_4: +- case GSCAN_ATTRIBUTE_CH_BUCKET_5: +- case GSCAN_ATTRIBUTE_CH_BUCKET_6: +- case GSCAN_ATTRIBUTE_CH_BUCKET_7: +- nla_for_each_nested(iter1, iter, tmp1) { +- type = nla_type(iter1); +- ch_bucket = +- scan_param->channel_bucket; ++ case GSCAN_ATTRIBUTE_BASE_PERIOD: ++ if (nla_len(iter) != sizeof(uint32)) { ++ err = -EINVAL; ++ goto exit; ++ } ++ scan_param->scan_fr = nla_get_u32(iter) / MSEC_PER_SEC; ++ break; ++ case GSCAN_ATTRIBUTE_NUM_BUCKETS: ++ if (nla_len(iter) != sizeof(uint32)) { ++ err = -EINVAL; ++ goto exit; ++ } ++ scan_param->nchannel_buckets = nla_get_u32(iter); ++ if (scan_param->nchannel_buckets >= ++ GSCAN_MAX_CH_BUCKETS) { ++ WL_ERR(("ncha_buck out of range %d\n", ++ scan_param->nchannel_buckets)); ++ err = -EINVAL; ++ goto exit; ++ } ++ break; ++ case GSCAN_ATTRIBUTE_CH_BUCKET_1: ++ case GSCAN_ATTRIBUTE_CH_BUCKET_2: ++ case GSCAN_ATTRIBUTE_CH_BUCKET_3: ++ case GSCAN_ATTRIBUTE_CH_BUCKET_4: ++ case GSCAN_ATTRIBUTE_CH_BUCKET_5: ++ case GSCAN_ATTRIBUTE_CH_BUCKET_6: ++ case GSCAN_ATTRIBUTE_CH_BUCKET_7: ++ err = wl_cfgvendor_set_scan_cfg_bucket(iter, ++ scan_param, j); ++ if (err < 0) { ++ WL_ERR(("set_scan_cfg_buck error:%d\n", err)); ++ goto exit; ++ } + +- switch (type) { +- case GSCAN_ATTRIBUTE_BUCKET_ID: +- break; +- case GSCAN_ATTRIBUTE_BUCKET_PERIOD: +- ch_bucket[j].bucket_freq_multiple = +- nla_get_u32(iter1)/1000; +- break; +- case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS: +- ch_bucket[j].num_channels = +- nla_get_u32(iter1); +- break; +- case GSCAN_ATTRIBUTE_BUCKET_CHANNELS: +- nla_for_each_nested(iter2, iter1, tmp2) { +- if (k >= GSCAN_MAX_CHANNELS_IN_BUCKET) +- break; +- ch_bucket[j].chan_list[k] = +- nla_get_u32(iter2); +- k++; +- } +- k = 0; +- break; +- case GSCAN_ATTRIBUTE_BUCKETS_BAND: +- ch_bucket[j].band = (uint16) +- nla_get_u32(iter1); +- break; +- case GSCAN_ATTRIBUTE_REPORT_EVENTS: +- ch_bucket[j].report_flag = (uint8) +- nla_get_u32(iter1); +- break; +- case GSCAN_ATTRIBUTE_BUCKET_STEP_COUNT: +- ch_bucket[j].repeat = (uint16) +- nla_get_u32(iter1); +- break; +- case GSCAN_ATTRIBUTE_BUCKET_MAX_PERIOD: +- ch_bucket[j].bucket_max_multiple = +- nla_get_u32(iter1)/1000; +- break; +- } +- } +- j++; +- break; ++ j++; ++ break; ++ default: ++ WL_ERR(("Unknown attr type %d\n", type)); ++ err = -EINVAL; ++ goto exit; + } + } + +- if (dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg), +- DHD_PNO_SCAN_CFG_ID, scan_param, FALSE) < 0) { +- WL_ERR(("Could not set GSCAN scan cfg\n")); ++ err = dhd_dev_pno_set_cfg_gscan(bcmcfg_to_prmry_ndev(cfg), ++ DHD_PNO_SCAN_CFG_ID, scan_param, FALSE); ++ ++ if (err < 0) { ++ WL_ERR(("Could not set GSCAN scan cfg error %d\n", err)); + err = -EINVAL; + } + ++exit: + kfree(scan_param); + return err; +- + } + + static int wl_cfgvendor_hotlist_cfg(struct wiphy *wiphy, \ No newline at end of file diff --git a/patches/3.10/CVE-2016-8455.patch b/patches/3.10/CVE-2016-8455.patch new file mode 100644 index 0000000..92de27d --- /dev/null +++ b/patches/3.10/CVE-2016-8455.patch @@ -0,0 +1,120 @@ +From 068427b76963929b220a4be40cdf77856374df55 Mon Sep 17 00:00:00 2001 +From: Sudhir Kohalli +Date: Fri, 4 Nov 2016 12:09:19 -0700 +Subject: [PATCH] net: wireless: bcmdhd: Security V: memory overflow in wifi + driver function __dhd_apf_add_filter + +In order to fix the memory overflow added a check +for APF program_len to verify if the program_len is +more than the MAX program length. If the APF program_len +is more than the MAX APF program_len then parse an error. +This check will avoid memory oveflow issue happening +in __dhd_apf_add_filter API. APF referes to Android Packet +filter. + +Bug: 32219121 + +Change-Id: Ibe468dcb51ec4f35c64da4bdc7296130bf145f13 +Signed-off-by: Sudhir Kohalli +--- + drivers/net/wireless/bcmdhd/dhd_linux.c | 13 ++++++++++- + drivers/net/wireless/bcmdhd/include/wlioctl.h | 2 ++ + drivers/net/wireless/bcmdhd/wl_cfgvendor.c | 31 +++++++++++++++++++++++++-- + 3 files changed, 43 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c +index 4ce5a2f4663d3..2fd2934a7e851 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_linux.c ++++ b/drivers/net/wireless/bcmdhd/dhd_linux.c +@@ -9039,13 +9039,24 @@ __dhd_apf_add_filter(struct net_device *ndev, uint32 filter_id, + } + + cmd_len = sizeof(cmd); ++ ++ /* Check if the program_len is more than the expected len ++ * and if program is initialized to NULL return here. ++ */ ++ if ((program_len > WL_APF_PROGRAM_MAX_SIZE) || ++ (program == NULL)) { ++ DHD_ERROR(("%s Invalid program_len: %d, program: %pK\n", ++ __func__, program_len, program)); ++ return -EINVAL; ++ } + buf_len = cmd_len + WL_PKT_FILTER_FIXED_LEN + + WL_APF_PROGRAM_FIXED_LEN + program_len; + + kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; + buf = kzalloc(buf_len, kflags); + if (unlikely(!buf)) { +- DHD_ERROR(("%s: MALLOC failure, %d bytes\n", __FUNCTION__, buf_len)); ++ DHD_ERROR(("%s: MALLOC failure, %d bytes\n", __func__, ++ buf_len)); + return -ENOMEM; + } + +diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h +index 50de89bc5a9c6..808a0bfc3e108 100644 +--- a/drivers/net/wireless/bcmdhd/include/wlioctl.h ++++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h +@@ -3291,6 +3291,8 @@ typedef struct wl_tcp_keep_set { + OFFSETOF(wl_pkt_filter_pattern_listel_t, mask_and_data) + + #define WL_APF_INTERNAL_VERSION 1 ++/* This will be MAX allowable APF program size */ ++#define WL_APF_PROGRAM_MAX_SIZE (2 * 1024) + #define WL_APF_PROGRAM_FIXED_LEN OFFSETOF(wl_apf_program_t, instrs) + #define WL_APF_PROGRAM_LEN(apf_program) \ + (apf_program->instr_len * sizeof(apf_program->instrs[0])) +diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +index d578026885619..5be16a72aa43f 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +@@ -2722,12 +2722,33 @@ wl_cfgvendor_apf_set_filter(struct wiphy *wiphy, + int ret, tmp, type; + gfp_t kflags; + +- /* assumption: length attribute must come first */ ++ if (len <= 0) { ++ WL_ERR((" Invalid len : %d\n", len)); ++ ret = -EINVAL; ++ goto exit; ++ } + nla_for_each_attr(iter, data, len, tmp) { + type = nla_type(iter); + switch (type) { + case APF_ATTRIBUTE_PROGRAM_LEN: +- program_len = nla_get_u32(iter); ++ /* check if the iter is valid and program ++ * length is not already initialized. ++ */ ++ if (nla_len(iter) == sizeof(uint32) && ++ !program_len) { ++ program_len = nla_get_u32(iter); ++ } else { ++ ret = -EINVAL; ++ goto exit; ++ } ++ ++ if (program_len > ++ WL_APF_PROGRAM_MAX_SIZE) { ++ WL_ERR(("program len is more ")); ++ WL_ERR(("than expected len\n")); ++ ret = -EINVAL; ++ goto exit; ++ } + if (unlikely(!program_len)) { + WL_ERR(("zero program length\n")); + ret = -EINVAL; +@@ -2740,6 +2761,12 @@ wl_cfgvendor_apf_set_filter(struct wiphy *wiphy, + ret = -EINVAL; + goto exit; + } ++ if (nla_len(iter) != program_len) { ++ WL_ERR(("program_len is not same\n")); ++ ret = -EINVAL; ++ goto exit; ++ } ++ + kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; + program = kzalloc(program_len, kflags); + if (unlikely(!program)) { \ No newline at end of file diff --git a/patches/3.10/CVE-2016-8456.patch b/patches/3.10/CVE-2016-8456.patch new file mode 100644 index 0000000..a5c597c --- /dev/null +++ b/patches/3.10/CVE-2016-8456.patch @@ -0,0 +1,143 @@ +From c2f9a396f1236a5a5e7bd1c90e32fbcf2ef35367 Mon Sep 17 00:00:00 2001 +From: Sudhir Kohalli +Date: Mon, 31 Oct 2016 14:49:11 -0700 +Subject: [PATCH] net: wireless: bcmdhd: Fix up the BRCM wifi DHD code + +Security Vulnerability fix for memory overflow wifi driver +function wl_cfgvendor_rtt_set_config. In the current fix added +check to validate if the target_cnt is valid or not if it is not valid +then parse error. Since target_cnt can be controlled by user netlink +input which needs to validated at the DHD level. + +Signed-off-by: Sudhir Kohalli +Bug: 32219255 +Change-Id: I5cf771c60a6ae8019e5e36571197e2849c572b40 +--- + drivers/net/wireless/bcmdhd/wl_cfgvendor.c | 62 ++++++++++++++++++++++-------- + 1 file changed, 46 insertions(+), 16 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +index b536de31010a9..eb83c8339e471 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +@@ -1537,13 +1537,18 @@ wl_cfgvendor_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, + } + + memset(&rtt_param, 0, sizeof(rtt_param)); ++ if (len <= 0) { ++ err = BCME_ERROR; ++ goto exit; ++ } + nla_for_each_attr(iter, data, len, rem) { + type = nla_type(iter); + switch (type) { + case RTT_ATTRIBUTE_TARGET_CNT: + target_cnt = nla_get_u8(iter); +- if (rtt_param.rtt_target_cnt > RTT_MAX_TARGET_CNT) { +- WL_ERR(("exceed max target count : %d\n", ++ if ((target_cnt <= 0) || ++ (target_cnt > RTT_MAX_TARGET_CNT)) { ++ WL_ERR(("target_cnt is not valid: %d", + target_cnt)); + err = BCME_RANGE; + goto exit; +@@ -1557,6 +1562,13 @@ wl_cfgvendor_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, + } + break; + case RTT_ATTRIBUTE_TARGET_INFO: ++ /* Added this variable for safe check to avoid crash ++ * incase the caller did not respect the order ++ */ ++ if (!rtt_param.target_info) { ++ err = BCME_NOMEM; ++ goto exit; ++ } + rtt_target = rtt_param.target_info; + nla_for_each_nested(iter1, iter, rem1) { + nla_for_each_nested(iter2, iter1, rem2) { +@@ -1677,6 +1689,7 @@ wl_cfgvendor_rtt_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, + exit: + /* free the target info list */ + kfree(rtt_param.target_info); ++ rtt_param.target_info = NULL; + return err; + } + +@@ -1685,46 +1698,63 @@ wl_cfgvendor_rtt_cancel_config(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int len) + { + int err = 0, rem, type, target_cnt = 0; +- int target_cnt_chk = 0; ++ int target_idx = 0; + const struct nlattr *iter; +- struct ether_addr *mac_list = NULL, *mac_addr = NULL; ++ struct ether_addr *mac_list = NULL; + struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); + ++ if (len <= 0) { ++ err = -EINVAL; ++ goto exit; ++ } + nla_for_each_attr(iter, data, len, rem) { + type = nla_type(iter); + switch (type) { + case RTT_ATTRIBUTE_TARGET_CNT: + if (mac_list != NULL) { + WL_ERR(("mac_list is not NULL\n")); ++ err = -EINVAL; + goto exit; + } + target_cnt = nla_get_u8(iter); +- if (target_cnt > 0) { ++ if ((target_cnt > 0) && ++ (target_cnt < RTT_MAX_TARGET_CNT)) { + mac_list = (struct ether_addr *)kzalloc(target_cnt * ETHER_ADDR_LEN, + GFP_KERNEL); + if (mac_list == NULL) { + WL_ERR(("failed to allocate mem for mac list\n")); ++ err = -EINVAL; + goto exit; + } +- mac_addr = &mac_list[0]; + } else { + /* cancel the current whole RTT process */ + goto cancel; + } + break; + case RTT_ATTRIBUTE_TARGET_MAC: +- if (mac_addr) { +- memcpy(mac_addr++, nla_data(iter), ETHER_ADDR_LEN); +- target_cnt_chk++; +- if (target_cnt_chk > target_cnt) { +- WL_ERR(("over target count\n")); +- goto exit; +- } +- break; +- } else { +- WL_ERR(("mac_list is NULL\n")); ++ if (!mac_list) { ++ err = -EINVAL; + goto exit; + } ++ ++ if (target_idx >= target_cnt) { ++ err = -EINVAL; ++ goto exit; ++ } ++ ++ if (nla_len(iter) != ETHER_ADDR_LEN) { ++ err = -EINVAL; ++ goto exit; ++ } ++ ++ memcpy(&mac_list[target_idx], nla_data(iter), ++ ETHER_ADDR_LEN); ++ target_idx++; ++ break; ++ ++ default: ++ err = -EINVAL; ++ goto exit; + } + } + cancel: \ No newline at end of file diff --git a/patches/3.10/CVE-2016-8457.patch b/patches/3.10/CVE-2016-8457.patch new file mode 100644 index 0000000..c6624aa --- /dev/null +++ b/patches/3.10/CVE-2016-8457.patch @@ -0,0 +1,348 @@ +From e5c1b001a822e8b38680655c400e7b3f67cc3323 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Thu, 10 Nov 2016 15:01:31 -0800 +Subject: [PATCH] net: wireless: bcmdhd: fix buffer overrun in anqpo config + +1. memory leak fix when input packet content corrupted. +2. reduced unnecessary debug messages + +Signed-off-by: Insun Song +Bug: 32219453 +Change-Id: I0f79310c97571cd46afff29f58f66b17a2471927 +--- + drivers/net/wireless/bcmdhd/dhd_linux.c | 2 + + drivers/net/wireless/bcmdhd/dhd_pno.c | 3 +- + drivers/net/wireless/bcmdhd/dhd_pno.h | 17 ++-- + drivers/net/wireless/bcmdhd/wl_cfg80211.c | 14 +++ + drivers/net/wireless/bcmdhd/wl_cfgvendor.c | 141 ++++++++++++++++++++--------- + 5 files changed, 127 insertions(+), 50 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c +index 2fd2934a7e851..00201de5de5b8 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_linux.c ++++ b/drivers/net/wireless/bcmdhd/dhd_linux.c +@@ -8621,6 +8621,7 @@ int dhd_dev_set_whitelist_ssid(struct net_device *dev, wl_ssid_whitelist_t *ssid + return err; + } + ++#ifdef DHD_ANQPO_SUPPORT + void * dhd_dev_process_anqpo_result(struct net_device *dev, + const void *data, uint32 event, int *send_evt_bytes) + { +@@ -8628,6 +8629,7 @@ void * dhd_dev_process_anqpo_result(struct net_device *dev, + + return (dhd_pno_process_anqpo_result(&dhd->pub, data, event, send_evt_bytes)); + } ++#endif /* DHD_ANQPO_SUPPORT */ + #endif /* GSCAN_SUPPORT */ + + int dhd_dev_set_rssi_monitor_cfg(struct net_device *dev, int start, +diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.c b/drivers/net/wireless/bcmdhd/dhd_pno.c +index 8d6d234cd11b3..a88d1e2e41320 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_pno.c ++++ b/drivers/net/wireless/bcmdhd/dhd_pno.c +@@ -3798,6 +3798,7 @@ dhd_pno_process_epno_result(dhd_pub_t *dhd, const void *data, uint32 event, int + return results; + } + ++#ifdef DHD_ANQPO_SUPPORT + void * + dhd_pno_process_anqpo_result(dhd_pub_t *dhd, const void *data, uint32 event, int *size) + { +@@ -3849,7 +3850,7 @@ dhd_pno_process_anqpo_result(dhd_pub_t *dhd, const void *data, uint32 event, int + + return result; + } +- ++#endif /* DHD_ANQPO_SUPPORT */ + + void *dhd_handle_hotlist_scan_evt(dhd_pub_t *dhd, const void *event_data, int *send_evt_bytes, + hotlist_type_t type) +diff --git a/drivers/net/wireless/bcmdhd/dhd_pno.h b/drivers/net/wireless/bcmdhd/dhd_pno.h +index b61d0fd866364..a0edf54049acf 100644 +--- a/drivers/net/wireless/bcmdhd/dhd_pno.h ++++ b/drivers/net/wireless/bcmdhd/dhd_pno.h +@@ -98,8 +98,9 @@ + + #define CHANNEL_BUCKET_EMPTY_INDEX 0xFFFF + #define GSCAN_RETRY_THRESHOLD 3 +-#define MAX_EPNO_SSID_NUM 64 +- ++#define MAX_EPNO_SSID_NUM 64 ++#define GSCAN_ANQPO_MAX_HS_LIST_SIZE 16 ++#define ANQPO_MAX_HS_NAI_REALM_SIZE 256 + #endif /* GSCAN_SUPPORT */ + + enum scan_status { +@@ -351,10 +352,10 @@ typedef struct gscan_results_cache { + } gscan_results_cache_t; + + typedef struct { +- int id; /* identifier of this network block, report this in event */ +- char realm[256]; /* null terminated UTF8 encoded realm, 0 if unspecified */ +- int64_t roamingConsortiumIds[16]; /* roaming consortium ids to match, 0s if unspecified */ +- uint8 plmn[3]; /* mcc/mnc combination as per rules, 0s if unspecified */ ++ int id; ++ char realm[ANQPO_MAX_HS_NAI_REALM_SIZE]; ++ int64_t roamingConsortiumIds[ANQPO_MAX_PFN_HS]; ++ uint8 plmn[ANQPO_MCC_LENGTH]; + } wifi_passpoint_network; + + typedef struct dhd_pno_gscan_capabilities { +@@ -517,8 +518,10 @@ extern void dhd_dev_gscan_hotlist_cache_cleanup(struct net_device *dev, hotlist_ + extern int dhd_dev_wait_batch_results_complete(struct net_device *dev); + extern void * dhd_dev_process_epno_result(struct net_device *dev, + const void *data, uint32 event, int *send_evt_bytes); ++#ifdef DHD_ANQPO_SUPPORT + extern void * dhd_dev_process_anqpo_result(struct net_device *dev, + const void *data, uint32 event, int *send_evt_bytes); ++#endif /* DHD_ANQPO_SUPPORT */ + extern int dhd_dev_set_epno(struct net_device *dev); + extern int dhd_dev_flush_fw_epno(struct net_device *dev); + #endif /* GSCAN_SUPPORT */ +@@ -567,7 +570,9 @@ extern void dhd_gscan_hotlist_cache_cleanup(dhd_pub_t *dhd, hotlist_type_t type) + extern int dhd_wait_batch_results_complete(dhd_pub_t *dhd); + extern void * dhd_pno_process_epno_result(dhd_pub_t *dhd, const void *data, + uint32 event, int *size); ++#ifdef DHD_ANQPO_SUPPORT + extern void * dhd_pno_process_anqpo_result(dhd_pub_t *dhd, const void *data, uint32 event, int *size); ++#endif /* DHD_ANQPO_SUPPORT */ + extern void dhd_pno_translate_epno_fw_flags(uint32 *flags); + extern int dhd_pno_set_epno(dhd_pub_t *dhd); + extern int dhd_pno_flush_fw_epno(dhd_pub_t *dhd); +diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +index a56ba6b82e197..3d70a82adfa5e 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c +@@ -9423,6 +9423,16 @@ wl_notify_gscan_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, + } else + err = -ENOMEM; + break; ++ case WLC_E_PFN_SSID_EXT: ++ ptr = dhd_dev_process_epno_result(ndev, data, event, &send_evt_bytes); ++ if (ptr) { ++ wl_cfgvendor_send_async_event(wiphy, ndev, ++ GOOGLE_SCAN_EPNO_EVENT, ptr, send_evt_bytes); ++ kfree(ptr); ++ } else ++ err = -ENOMEM; ++ break; ++#ifdef DHD_ANQPO_SUPPORT + case WLC_E_PFN_NET_FOUND: + ptr = dhd_dev_process_anqpo_result(ndev, data, event, &len); + if (ptr) { +@@ -9432,6 +9442,7 @@ wl_notify_gscan_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev, + } else + err = -ENOMEM; + break; ++#endif /* DHD_ANQPO_SUPPORT */ + default: + WL_ERR(("Unknown event %d\n", event)); + break; +@@ -10035,7 +10046,10 @@ static void wl_init_event_handler(struct bcm_cfg80211 *cfg) + cfg->evt_handler[WLC_E_PFN_SWC] = wl_notify_gscan_event; + cfg->evt_handler[WLC_E_PFN_BSSID_NET_FOUND] = wl_notify_gscan_event; + cfg->evt_handler[WLC_E_PFN_BSSID_NET_LOST] = wl_notify_gscan_event; ++ cfg->evt_handler[WLC_E_PFN_SSID_EXT] = wl_notify_gscan_event; ++#ifdef DHD_ANQPO_SUPPORT + cfg->evt_handler[WLC_E_GAS_FRAGMENT_RX] = wl_notify_gscan_event; ++#endif /* DHD_ANQPO_SUPPORT */ + cfg->evt_handler[WLC_E_ROAM_EXP_EVENT] = wl_handle_roam_exp_event; + #endif /* GSCAN_SUPPORT */ + cfg->evt_handler[WLC_E_RSSI_LQM] = wl_handle_rssi_monitor_event; +diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +index 5be16a72aa43f..b156660ed053a 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +@@ -939,10 +939,13 @@ static int wl_cfgvendor_epno_cfg(struct wiphy *wiphy, + return err; + } + ++#ifdef DHD_ANQPO_SUPPORT + static int wl_cfgvendor_gscan_anqpo_config(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int len) + { +- int err = BCME_ERROR, rem, type, hs_list_size = 0, malloc_size, i = 0, j, k, num_oi, oi_len; ++ int err = BCME_ERROR, rem, type, malloc_size, i = 0; ++ uint32 hs_list_size = 0; ++ int j, k, num_oi, oi_len; + wifi_passpoint_network *hs_list = NULL, *src_hs; + wl_anqpo_pfn_hs_list_t *anqpo_hs_list; + wl_anqpo_pfn_hs_t *dst_hs; +@@ -953,52 +956,100 @@ static int wl_cfgvendor_gscan_anqpo_config(struct wiphy *wiphy, + char *rcid; + + nla_for_each_attr(iter, data, len, rem) { +- type = nla_type(iter); +- switch (type) { +- case GSCAN_ATTRIBUTE_ANQPO_HS_LIST: +- if (hs_list_size > 0) { +- hs_list = kmalloc(hs_list_size*sizeof(wifi_passpoint_network), GFP_KERNEL); +- if (hs_list == NULL) { +- WL_ERR(("failed to allocate hs_list\n")); +- return -ENOMEM; +- } +- } +- nla_for_each_nested(outer, iter, tmp) { +- nla_for_each_nested(inner, outer, tmp1) { +- type = nla_type(inner); ++ type = nla_type(iter); ++ switch (type) { ++ case GSCAN_ATTRIBUTE_ANQPO_HS_LIST: ++ if (hs_list) { ++ err = -EINVAL; ++ goto exit; ++ } ++ if (hs_list_size > GSCAN_ANQPO_MAX_HS_LIST_SIZE) { ++ err = -EINVAL; ++ goto exit; ++ } ++ if (hs_list_size > 0) { ++ hs_list = kzalloc(hs_list_size * ++ sizeof(wifi_passpoint_network), GFP_KERNEL); ++ if (!hs_list) { ++ WL_ERR(("failed to allocate hs_list\n")); ++ return -ENOMEM; ++ } ++ } ++ nla_for_each_nested(outer, iter, tmp) { ++ if (i == hs_list_size) ++ break; ++ nla_for_each_nested(inner, outer, tmp1) { ++ type = nla_type(inner); + +- switch (type) { +- case GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID: +- hs_list[i].id = nla_get_u32(inner); +- WL_ERR(("%s: net id: %d\n", __func__, hs_list[i].id)); +- break; +- case GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM: +- memcpy(hs_list[i].realm, +- nla_data(inner), 256); +- WL_ERR(("%s: realm: %s\n", __func__, hs_list[i].realm)); +- break; +- case GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID: +- memcpy(hs_list[i].roamingConsortiumIds, +- nla_data(inner), 128); +- break; +- case GSCAN_ATTRIBUTE_ANQPO_HS_PLMN: +- memcpy(hs_list[i].plmn, +- nla_data(inner), 3); +- WL_ERR(("%s: plmn: %c %c %c\n", __func__, hs_list[i].plmn[0], hs_list[i].plmn[1], hs_list[i].plmn[2])); +- break; +- } +- } +- i++; ++ switch (type) { ++ case GSCAN_ATTRIBUTE_ANQPO_HS_NETWORK_ID: ++ if (nla_len(inner) != sizeof(hs_list[i].id)) { ++ err = -EINVAL; ++ goto exit; + } ++ hs_list[i].id = nla_get_u32(inner); ++ WL_DBG(("%s: net id: %d\n", ++ __func__, hs_list[i].id)); + break; +- case GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE: +- hs_list_size = nla_get_u32(iter); +- WL_ERR(("%s: ANQPO: %d\n", __func__, hs_list_size)); ++ case GSCAN_ATTRIBUTE_ANQPO_HS_NAI_REALM: ++ if (nla_len(inner) != ++ sizeof(hs_list[i].realm)) { ++ err = -EINVAL; ++ goto exit; ++ } ++ memcpy(hs_list[i].realm, nla_data(inner), ++ sizeof(hs_list[i].realm)); ++ WL_DBG(("%s: realm: %s\n", ++ __func__, hs_list[i].realm)); + break; +- default: +- WL_ERR(("Unknown type: %d\n", type)); +- return err; ++ case GSCAN_ATTRIBUTE_ANQPO_HS_ROAM_CONSORTIUM_ID: ++ if (nla_len(inner) != sizeof(hs_list[i]. ++ roamingConsortiumIds)) { ++ err = -EINVAL; ++ goto exit; ++ } ++ memcpy(hs_list[i].roamingConsortiumIds, ++ nla_data(inner), ++ sizeof(hs_list[i].roamingConsortiumIds)); ++ break; ++ case GSCAN_ATTRIBUTE_ANQPO_HS_PLMN: ++ if (nla_len(inner) != sizeof(hs_list[i].plmn)) { ++ err = -EINVAL; ++ goto exit; ++ } ++ memcpy(hs_list[i].plmn, ++ nla_data(inner), ++ sizeof(hs_list[i].plmn)); ++ WL_DBG(("%s: plmn: %c %c %c\n", ++ __func__, hs_list[i].plmn[0], ++ hs_list[i].plmn[1], ++ hs_list[i].plmn[2])); ++ break; ++ } ++ } ++ i++; + } ++ break; ++ case GSCAN_ATTRIBUTE_ANQPO_HS_LIST_SIZE: ++ if (nla_len(iter) != sizeof(hs_list_size)) { ++ err = -EINVAL; ++ goto exit; ++ } ++ hs_list_size = nla_get_u32(iter); ++ if ((hs_list_size == 0) || ++ (hs_list_size > GSCAN_ANQPO_MAX_HS_LIST_SIZE)) { ++ WL_ERR(("%s: ANQPO: %d\n", __func__, hs_list_size)); ++ err = -EINVAL; ++ goto exit; ++ } ++ WL_DBG(("%s: ANQPO: %d\n", __func__, hs_list_size)); ++ break; ++ default: ++ WL_ERR(("Unknown type: %d\n", type)); ++ err = -EINVAL; ++ goto exit; ++ } ++ + } + + malloc_size = OFFSETOF(wl_anqpo_pfn_hs_list_t, hs) + +@@ -1046,7 +1097,7 @@ static int wl_cfgvendor_gscan_anqpo_config(struct wiphy *wiphy, + kfree(hs_list); + return err; + } +- ++#endif /* DHD_ANQPO_SUPPORT */ + static int wl_cfgvendor_set_batch_scan_cfg(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int len) + { +@@ -3065,6 +3116,7 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wl_cfgvendor_set_bssid_blacklist + }, ++#ifdef DHD_ANQPO_SUPPORT + { + { + .vendor_id = OUI_GOOGLE, +@@ -3073,6 +3125,7 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = { + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = wl_cfgvendor_gscan_anqpo_config + }, ++#endif /* DHD_ANQPO_SUPPORT */ + #endif /* GSCAN_SUPPORT */ + { + { +@@ -3233,7 +3286,9 @@ static const struct nl80211_vendor_cmd_info wl_vendor_events [] = { + { OUI_GOOGLE, GOOGLE_SCAN_EPNO_EVENT }, + { OUI_GOOGLE, GOOGLE_DEBUG_RING_EVENT }, + { OUI_GOOGLE, GOOGLE_FW_DUMP_EVENT }, ++#ifdef DHD_ANQPO_SUPPORT + { OUI_GOOGLE, GOOGLE_PNO_HOTSPOT_FOUND_EVENT }, ++#endif /* DHD_ANQPO_SUPPORT */ + { OUI_GOOGLE, GOOGLE_RSSI_MONITOR_EVENT }, + { OUI_GOOGLE, GOOGLE_MKEEP_ALIVE_EVENT } + }; \ No newline at end of file diff --git a/patches/3.10/CVE-2016-8458.patch b/patches/3.10/CVE-2016-8458.patch new file mode 100644 index 0000000..7438d7e --- /dev/null +++ b/patches/3.10/CVE-2016-8458.patch @@ -0,0 +1,394 @@ +From d567c744898f67e1c54db5339f41815d02f3d59e Mon Sep 17 00:00:00 2001 +From: Andrew Chant +Date: Sun, 13 Nov 2016 14:29:08 -0800 +Subject: [PATCH] input: synaptics_dsx: add update bounds checks. + +Firmware updates contain offsets that are parsed +by the kernel driver. Ensure all offsets are within +the bounds of the firmware update. + +TESTED: +successfully parsed update firmware on device boot. + +Bug: 31525965 +Bug: 31968442 +Change-Id: If66dd1a837d0606250db6f1c75c89747d106541c +Signed-off-by: Andrew Chant +--- + .../synaptics_dsx25/synaptics_dsx_fw_update.c | 172 +++++++++++++++++---- + 1 file changed, 144 insertions(+), 28 deletions(-) + +diff --git a/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c +index ff82a4f3a55e8..323f65891b458 100755 +--- a/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c ++++ b/drivers/input/touchscreen/synaptics_dsx25/synaptics_dsx_fw_update.c +@@ -691,6 +691,22 @@ static int __init early_parse_tp_panel_cmdline(char *arg) + } + early_param("mdss_mdp.panel", early_parse_tp_panel_cmdline); + ++/* Check offset + size <= bound. 1 if in bounds, 0 otherwise. */ ++static int in_bounds(unsigned long offset, ++ unsigned long size, ++ unsigned long bound) ++{ ++ if (offset > bound || size > bound) { ++ pr_err("%s: %lu or %lu > %lu\n", __func__, offset, size, bound); ++ return 0; ++ } ++ if (offset > (bound - size)) { ++ pr_err("%s: %lu > %lu - %lu\n", __func__, offset, size, bound); ++ return 0; ++ } ++ return 1; ++} ++ + static unsigned int le_to_uint(const unsigned char *ptr) + { + return (unsigned int)ptr[0] + +@@ -770,8 +786,10 @@ static void fwu_compare_partition_tables(void) + return; + } + +-static void fwu_parse_partition_table(const unsigned char *partition_table, +- struct block_count *blkcount, struct physical_address *phyaddr) ++static int fwu_parse_partition_table(const unsigned char *partition_table, ++ unsigned long len, ++ struct block_count *blkcount, ++ struct physical_address *phyaddr) + { + unsigned char ii; + unsigned char index; +@@ -784,6 +802,11 @@ static void fwu_parse_partition_table(const unsigned char *partition_table, + tp_log_debug("%s: in!\n",__func__); + for (ii = 0; ii < fwu->partitions; ii++) { + index = ii * 8 + 2; ++ if (!in_bounds(index, sizeof(*ptable), len)) { ++ pr_err("%s: %d/%d not in bounds\n", __func__, ii, ++ fwu->partitions); ++ return -EINVAL; ++ } + ptable = (struct partition_table *)&partition_table[index]; + partition_length = ptable->partition_length_15_8 << 8 | + ptable->partition_length_7_0; +@@ -792,7 +815,7 @@ static void fwu_parse_partition_table(const unsigned char *partition_table, + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: Partition entry %d:\n", + __func__, ii); +- for (offset = 0; offset < 8; offset++) { ++ for (offset = 0; offset < sizeof(*ptable); offset++) { + dev_dbg(rmi4_data->pdev->dev.parent, + "%s: 0x%02x\n", + __func__, +@@ -854,28 +877,36 @@ static void fwu_parse_partition_table(const unsigned char *partition_table, + }; + } + +- return; ++ return 0; + } + +-static void fwu_parse_image_header_10_bl_container(const unsigned char *image) ++static int fwu_parse_image_header_10_bl_container(const unsigned char *image) + { + unsigned char ii; + unsigned char num_of_containers; + unsigned int addr; + unsigned int container_id; ++ unsigned int content_offset; + unsigned int length; + const unsigned char *content; + struct container_descriptor *descriptor; + ++ if (fwu->img.bootloader.size < 4) ++ return -ENOENT; + num_of_containers = (fwu->img.bootloader.size - 4) / 4; + + for (ii = 1; ii <= num_of_containers; ii++) { + addr = le_to_uint(fwu->img.bootloader.data + (ii * 4)); ++ if (!in_bounds(addr, sizeof(*descriptor), fwu->image_size)) ++ return -EINVAL; + descriptor = (struct container_descriptor *)(image + addr); + container_id = descriptor->container_id[0] | + descriptor->container_id[1] << 8; +- content = image + le_to_uint(descriptor->content_address); ++ content_offset = le_to_uint(descriptor->content_address); + length = le_to_uint(descriptor->content_length); ++ if (!in_bounds(content_offset, length, fwu->image_size)) ++ return -EINVAL; ++ content = image + content_offset; + switch (container_id) { + case BL_CONFIG_CONTAINER: + case GLOBAL_PARAMETERS_CONTAINER: +@@ -892,10 +923,10 @@ static void fwu_parse_image_header_10_bl_container(const unsigned char *image) + }; + } + +- return; ++ return 0; + } + +-static void fwu_parse_image_header_10(void) ++static int fwu_parse_image_header_10(void) + { + unsigned char ii; + unsigned char num_of_containers; +@@ -903,6 +934,7 @@ static void fwu_parse_image_header_10(void) + unsigned int offset; + unsigned int container_id; + unsigned int length; ++ unsigned int content_offset; + const unsigned char *image; + const unsigned char *content; + struct container_descriptor *descriptor; +@@ -911,25 +943,35 @@ static void fwu_parse_image_header_10(void) + tp_log_debug("%s: in!\n",__func__); + image = fwu->image; + header = (struct image_header_10 *)image; +- ++ if (fwu->image_size < sizeof(*header)) ++ return -EINVAL; + fwu->img.checksum = le_to_uint(header->checksum); + + /* address of top level container */ + offset = le_to_uint(header->top_level_container_start_addr); + descriptor = (struct container_descriptor *)(image + offset); ++ if (!in_bounds(offset, sizeof(*descriptor), fwu->image_size)) ++ return -EINVAL; + + /* address of top level container content */ + offset = le_to_uint(descriptor->content_address); + num_of_containers = le_to_uint(descriptor->content_length) / 4; + + for (ii = 0; ii < num_of_containers; ii++) { ++ if (!in_bounds(offset, 4, fwu->image_size)) ++ return -EINVAL; + addr = le_to_uint(image + offset); + offset += 4; ++ if (!in_bounds(addr, sizeof(*descriptor), fwu->image_size)) ++ return -EINVAL; + descriptor = (struct container_descriptor *)(image + addr); + container_id = descriptor->container_id[0] | + descriptor->container_id[1] << 8; +- content = image + le_to_uint(descriptor->content_address); ++ content_offset = le_to_uint(descriptor->content_address); + length = le_to_uint(descriptor->content_length); ++ if (!in_bounds(content_offset, length, fwu->image_size)) ++ return -EINVAL; ++ content = image + content_offset; + switch (container_id) { + case UI_CONTAINER: + case CORE_CODE_CONTAINER: +@@ -945,7 +987,8 @@ static void fwu_parse_image_header_10(void) + fwu->img.bl_version = *content; + fwu->img.bootloader.data = content; + fwu->img.bootloader.size = length; +- fwu_parse_image_header_10_bl_container(image); ++ if (fwu_parse_image_header_10_bl_container(image)) ++ return -EINVAL; + break; + case GUEST_CODE_CONTAINER: + fwu->img.contains_guest_code = true; +@@ -964,6 +1007,8 @@ static void fwu_parse_image_header_10(void) + break; + case GENERAL_INFORMATION_CONTAINER: + fwu->img.contains_firmware_id = true; ++ if (length < 4 + 4) ++ return -EINVAL; + fwu->img.firmware_id = le_to_uint(content + 4); + break; + default: +@@ -971,10 +1016,10 @@ static void fwu_parse_image_header_10(void) + } + } + +- return; ++ return 0; + } + +-static void fwu_parse_image_header_05_06(void) ++static int fwu_parse_image_header_05_06(void) + { + int retval; + const unsigned char *image; +@@ -983,6 +1028,8 @@ static void fwu_parse_image_header_05_06(void) + + tp_log_debug("%s: in!\n",__func__); + image = fwu->image; ++ if (fwu->image_size < sizeof(*header)) ++ return -EINVAL; + header = (struct image_header_05_06 *)image; + + fwu->img.checksum = le_to_uint(header->checksum); +@@ -995,18 +1042,51 @@ static void fwu_parse_image_header_05_06(void) + + fwu->img.ui_firmware.size = le_to_uint(header->firmware_size); + if (fwu->img.ui_firmware.size) { +- fwu->img.ui_firmware.data = image + IMAGE_AREA_OFFSET; +- if (fwu->img.contains_bootloader) +- fwu->img.ui_firmware.data += fwu->img.bootloader_size; ++ unsigned int ui_firmware_offset = IMAGE_AREA_OFFSET; ++ ++ if (fwu->img.contains_bootloader) { ++ if (!in_bounds(ui_firmware_offset, ++ fwu->img.bootloader_size, ++ fwu->image_size)) { ++ return -EINVAL; ++ } ++ ui_firmware_offset += fwu->img.bootloader_size; ++ } ++ if (!in_bounds(ui_firmware_offset, ++ fwu->img.ui_firmware.size, ++ fwu->image_size)) { ++ return -EINVAL; ++ } ++ fwu->img.ui_firmware.data = image + ui_firmware_offset; + } + +- if ((fwu->img.bl_version == BL_V6) && header->options_tddi) ++ if ((fwu->img.bl_version == BL_V6) && header->options_tddi) { ++ if (!in_bounds(IMAGE_AREA_OFFSET, ++ fwu->img.ui_firmware.size, ++ fwu->image_size)) { ++ return -EINVAL; ++ } + fwu->img.ui_firmware.data = image + IMAGE_AREA_OFFSET; ++ } + + fwu->img.ui_config.size = le_to_uint(header->config_size); + if (fwu->img.ui_config.size) { +- fwu->img.ui_config.data = fwu->img.ui_firmware.data + ++ unsigned int ui_firmware_end; ++ ++ if (fwu->img.ui_firmware.data < image) ++ return -EINVAL; ++ if (!in_bounds(fwu->img.ui_firmware.data - image, ++ fwu->img.ui_firmware.size, ++ fwu->image_size)) { ++ return -EINVAL; ++ } ++ ui_firmware_end = fwu->img.ui_firmware.data - image + + fwu->img.ui_firmware.size; ++ if (!in_bounds(ui_firmware_end, fwu->img.ui_config.size, ++ fwu->image_size)) { ++ return -EINVAL; ++ } ++ fwu->img.ui_config.data = image + ui_firmware_end; + } + + if ((fwu->img.bl_version == BL_V5 && fwu->img.contains_bootloader) || +@@ -1018,6 +1098,11 @@ static void fwu_parse_image_header_05_06(void) + if (fwu->img.contains_disp_config) { + fwu->img.disp_config_offset = le_to_uint(header->dsp_cfg_addr); + fwu->img.dp_config.size = le_to_uint(header->dsp_cfg_size); ++ if (!in_bounds(fwu->img.disp_config_offset, ++ fwu->img.dp_config.size, ++ fwu->image_size)) { ++ return -EINVAL; ++ } + fwu->img.dp_config.data = image + fwu->img.disp_config_offset; + } else { + retval = secure_memcpy(fwu->img.cstmr_product_id, +@@ -1050,28 +1135,52 @@ static void fwu_parse_image_header_05_06(void) + fwu->img.product_id[PRODUCT_ID_SIZE] = 0; + + fwu->img.lockdown.size = LOCKDOWN_SIZE; ++ if (LOCKDOWN_SIZE > IMAGE_AREA_OFFSET) ++ return -EINVAL; ++ if (fwu->image_size < IMAGE_AREA_OFFSET) ++ return -EINVAL; + fwu->img.lockdown.data = image + IMAGE_AREA_OFFSET - LOCKDOWN_SIZE; + +- return; ++ return 0; + } + + static int fwu_parse_image_info(void) + { + struct image_header_10 *header; + struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data; ++ unsigned int image_size = 0; + +- tp_log_debug("%s: in!\n",__func__); ++ tp_log_debug("%s: in!\n", __func__); + header = (struct image_header_10 *)fwu->image; ++ if (!header) { ++ tp_log_debug("%s: Invalid header\n", __func__); ++ return -EINVAL; ++ } + ++ image_size = fwu->image_size; ++ if (image_size < sizeof(struct image_header_05_06) && ++ image_size < sizeof(struct image_header_10)) { ++ tp_log_debug("header too small: %u < (%lu, %lu)", ++ image_size, sizeof(struct image_header_05_06), ++ sizeof(struct image_header_10)); ++ return -EINVAL; ++ } ++ /* This is clearing img, not image. */ + memset(&fwu->img, 0x00, sizeof(fwu->img)); + + switch (header->major_header_version) { + case IMAGE_HEADER_VERSION_10: +- fwu_parse_image_header_10(); ++ if (fwu_parse_image_header_10()) { ++ tp_log_debug("%s:error parsing v10 header\n", __func__); ++ return -EINVAL; ++ } + break; + case IMAGE_HEADER_VERSION_05: + case IMAGE_HEADER_VERSION_06: +- fwu_parse_image_header_05_06(); ++ if (fwu_parse_image_header_05_06()) { ++ tp_log_debug("%s:error parsing v56 header\n", __func__); ++ return -EINVAL; ++ } + break; + default: + dev_err(rmi4_data->pdev->dev.parent, +@@ -1088,9 +1197,13 @@ static int fwu_parse_image_info(void) + return -EINVAL; + } + +- fwu_parse_partition_table(fwu->img.fl_config.data, +- &fwu->img.blkcount, &fwu->img.phyaddr); +- ++ if (fwu_parse_partition_table(fwu->img.fl_config.data, ++ fwu->img.fl_config.size, ++ &fwu->img.blkcount, ++ &fwu->img.phyaddr)) { ++ tp_log_debug("%s:Error parsing ptable\n", __func__); ++ return -EINVAL; ++ } + fwu_compare_partition_tables(); + } else { + fwu->new_partition_table = false; +@@ -1669,7 +1782,9 @@ static int fwu_read_f34_v7_queries(void) + return retval; + } + +- fwu_parse_partition_table(ptable, &fwu->blkcount, &fwu->phyaddr); ++ if (fwu_parse_partition_table(ptable, fwu->partition_table_bytes, ++ &fwu->blkcount, &fwu->phyaddr)) ++ return -EINVAL; + + return 0; + } +@@ -3330,6 +3445,7 @@ static int fwu_start_reflash(void) + __func__, fw_entry->size); + + fwu->image = fw_entry->data; ++ fwu->image_size = fw_entry->size; + } + + retval = fwu_parse_image_info(); +@@ -4203,8 +4319,8 @@ static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data) + &fwu->fwu_work); + #endif + +- retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj, +- &dev_attr_data); ++ retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj, ++ &dev_attr_data); + if (retval < 0) { + dev_err(rmi4_data->pdev->dev.parent, + "%s: Failed to create sysfs bin file\n", \ No newline at end of file diff --git a/patches/3.10/CVE-2016-8463.patch b/patches/3.10/CVE-2016-8463.patch new file mode 100644 index 0000000..84f991e --- /dev/null +++ b/patches/3.10/CVE-2016-8463.patch @@ -0,0 +1,34 @@ +From cd0fa86de6ca1d40c0a93d86d1c0f7846e8a9a10 Mon Sep 17 00:00:00 2001 +From: Laura Abbott +Date: Fri, 3 Jan 2014 10:47:00 -0800 +Subject: fs: fuse: Add replacment for CMA pages into the LRU cache + +CMA pages are currently replaced in the FUSE file system since +FUSE may hold on to CMA pages for a long time, preventing migration. +The replacement page is added to the file cache but not the LRU +cache. This may prevent the page from being properly aged and dropped, +creating poor performance under tight memory condition. Fix this by +adding the new page to the LRU cache after creation. + +Change-Id: Ib349abf1024d48386b835335f3fbacae040b6241 +CRs-Fixed: 586855 +Signed-off-by: Laura Abbott +--- + fs/fuse/file.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/fuse/file.c b/fs/fuse/file.c +index e231a7f..3411ed8 100644 +--- a/fs/fuse/file.c ++++ b/fs/fuse/file.c +@@ -822,6 +822,8 @@ static int fuse_readpages_fill(void *_data, struct page *page) + lock_page(newpage); + put_page(newpage); + ++ lru_cache_add_file(newpage); ++ + /* finally release the old page and swap pointers */ + unlock_page(oldpage); + page_cache_release(oldpage); +-- +cgit v1.1 diff --git a/patches/3.10/CVE-2016-8464.patch b/patches/3.10/CVE-2016-8464.patch new file mode 100644 index 0000000..013d23c --- /dev/null +++ b/patches/3.10/CVE-2016-8464.patch @@ -0,0 +1,146 @@ +From cbf66a616bb08cc6c932e4122f3271df83e253bb Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Tue, 25 Oct 2016 13:33:18 -0700 +Subject: [PATCH] net: wireless: bcmdhd: fix buffer overrun in private command + path + +buffer overrun case found when length parameter manipulated. + +1. if input parameter buffer length is less than 4k, +then allocate 4k by default. It help to get enough margin +for output string overwritten. + +2. added additional length check not to override user space +allocated buffer size. + +bug=29000183 +Change-Id: I0c15d764c1648920f0214ec47ada689ca44ebfba +Signed-off-by: Insun Song +--- + drivers/net/wireless/bcmdhd/wl_android.c | 58 ++++++++++++++++++++------------ + 1 file changed, 37 insertions(+), 21 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c +index c8cae82af2f46..86c56e28f532c 100644 +--- a/drivers/net/wireless/bcmdhd/wl_android.c ++++ b/drivers/net/wireless/bcmdhd/wl_android.c +@@ -246,17 +246,22 @@ static int wl_android_get_rssi(struct net_device *net, char *command, int total_ + return -1; + if ((ssid.SSID_len == 0) || (ssid.SSID_len > DOT11_MAX_SSID_LEN)) { + DHD_ERROR(("%s: wldev_get_ssid failed\n", __FUNCTION__)); +- } else if (total_len <= ssid.SSID_len) { +- return -ENOMEM; + } else { +- memcpy(command, ssid.SSID, ssid.SSID_len); +- bytes_written = ssid.SSID_len; ++ if (total_len > ssid.SSID_len) { ++ memcpy(command, ssid.SSID, ssid.SSID_len); ++ bytes_written = ssid.SSID_len; ++ } else { ++ return BCME_ERROR; ++ } ++ } ++ ++ if ((total_len - bytes_written) >= (strlen(" rssi -XXX") + 1)) { ++ bytes_written += snprintf(&command[bytes_written], total_len - bytes_written, ++ " rssi %d", rssi); ++ command[bytes_written] = '\0'; ++ } else { ++ return BCME_ERROR; + } +- if ((total_len - bytes_written) < (strlen(" rssi -XXX") + 1)) +- return -ENOMEM; +- bytes_written += scnprintf(&command[bytes_written], +- total_len - bytes_written, " rssi %d", rssi); +- command[bytes_written] = '\0'; + + DHD_INFO(("%s: command result is %s (%d)\n", __FUNCTION__, command, bytes_written)); + return bytes_written; +@@ -1332,13 +1337,17 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) + } + + if ((priv_cmd.total_len > PRIVATE_COMMAND_MAX_LEN) || (priv_cmd.total_len < 0)) { +- DHD_ERROR(("%s: buf length invalid:%d\n", __FUNCTION__, +- priv_cmd.total_len)); ++ DHD_ERROR(("%s: buf length invalid:%d \n", __FUNCTION__, priv_cmd.total_len)); + ret = -EINVAL; + goto exit; + } + +- buf_size = max(priv_cmd.total_len, PRIVATE_COMMAND_DEF_LEN); ++ if (priv_cmd.total_len < PRIVATE_COMMAND_DEF_LEN) { ++ buf_size = PRIVATE_COMMAND_DEF_LEN; ++ } else { ++ buf_size = priv_cmd.total_len; ++ } ++ + command = kmalloc((buf_size + 1), GFP_KERNEL); + + if (!command) +@@ -1355,20 +1364,22 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) + + DHD_INFO(("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name)); + +- bytes_written = wl_handle_private_cmd(net, command, priv_cmd.total_len); ++ bytes_written = wl_handle_private_cmd(net, command, buf_size); + if (bytes_written >= 0) { +- if ((bytes_written == 0) && (priv_cmd.total_len > 0)) ++ if ((bytes_written == 0) && (priv_cmd.total_len > 0)) { + command[0] = '\0'; ++ } + if (bytes_written >= priv_cmd.total_len) { +- DHD_ERROR(("%s: err. b_w:%d >= tot:%d\n", __FUNCTION__, +- bytes_written, priv_cmd.total_len)); ++ DHD_ERROR(("%s: not enough for output. bytes_written:%d >= total_len:%d \n", ++ __FUNCTION__, bytes_written, priv_cmd.total_len)); + ret = BCME_BUFTOOSHORT; + goto exit; ++ } else { ++ bytes_written++; + } +- bytes_written++; + priv_cmd.used_len = bytes_written; + if (copy_to_user(priv_cmd.buf, command, bytes_written)) { +- DHD_ERROR(("%s: failed copy to user\n", __FUNCTION__)); ++ DHD_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__)); + ret = -EFAULT; + } + } else { +@@ -1377,13 +1388,17 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) + + exit: + net_os_wake_unlock(net); +- kfree(command); ++ if (command) { ++ kfree(command); ++ } ++ + return ret; + } + + int + wl_handle_private_cmd(struct net_device *net, char *command, u32 buf_size) + { ++ + int bytes_written = 0; + android_wifi_priv_cmd priv_cmd; + +@@ -1400,7 +1415,7 @@ wl_handle_private_cmd(struct net_device *net, char *command, u32 buf_size) + + if (!g_wifi_on) { + DHD_ERROR(("%s: Ignore private cmd \"%s\" - iface is down\n", +- __FUNCTION__, command)); ++ __FUNCTION__, command)); + return 0; + } + +@@ -1558,7 +1573,8 @@ wl_handle_private_cmd(struct net_device *net, char *command, u32 buf_size) + } + else { + DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command)); +- bytes_written = scnprintf(command, sizeof("FAIL"), "FAIL"); ++ snprintf(command, 5, "FAIL"); ++ bytes_written = strlen("FAIL"); + } + + return bytes_written; \ No newline at end of file diff --git a/patches/3.10/CVE-2016-8465.patch b/patches/3.10/CVE-2016-8465.patch new file mode 100644 index 0000000..bbf3a1b --- /dev/null +++ b/patches/3.10/CVE-2016-8465.patch @@ -0,0 +1,155 @@ +From 8f1621cd0d0ca0bc494a926a1331f582b27b913e Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Thu, 3 Nov 2016 10:53:51 -0700 +Subject: [PATCH] net: wireless: bcmdhd: fix buffer overrun in + wl_cfgvendor_hotlist_cfg + +fix buffer overrun found where user manipulated input parameters + +1. allocate local buffer with max length than input sized. +2. length check added in each tlv parsing and added error handling. +3. limit max hotlist count to PFN_SW_MAX_NUM_APS(16). + +bug=32474971 + +Signed-off-by: Insun Song +Change-Id: I60d513a30875f6a8ee8cfdc557bdec1436416fe7 +--- + drivers/net/wireless/bcmdhd/wl_cfgvendor.c | 107 +++++++++++++++++++++-------- + 1 file changed, 78 insertions(+), 29 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +index eb83c8339e471..d578026885619 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +@@ -691,14 +691,22 @@ static int wl_cfgvendor_hotlist_cfg(struct wiphy *wiphy, + struct bcm_cfg80211 *cfg = wiphy_priv(wiphy); + gscan_hotlist_scan_params_t *hotlist_params; + int tmp, tmp1, tmp2, type, j = 0, dummy; +- const struct nlattr *outer, *inner, *iter; +- bool flush = FALSE; ++ const struct nlattr *outer, *inner = NULL, *iter; ++ uint8 flush = 0; + struct bssid_t *pbssid; + +- hotlist_params = (gscan_hotlist_scan_params_t *)kzalloc(len, GFP_KERNEL); ++ if (len < sizeof(*hotlist_params) || len >= WLC_IOCTL_MAXLEN) { ++ WL_ERR(("buffer length :%d wrong - bail out.\n", len)); ++ return -EINVAL; ++ } ++ ++ hotlist_params = kzalloc(sizeof(*hotlist_params) ++ + (sizeof(struct bssid_t) * (PFN_SWC_MAX_NUM_APS - 1)), ++ GFP_KERNEL); ++ + if (!hotlist_params) { + WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes \n", len)); +- return -1; ++ return -ENOMEM; + } + + hotlist_params->lost_ap_window = GSCAN_LOST_AP_WINDOW_DEFAULT; +@@ -706,37 +714,78 @@ static int wl_cfgvendor_hotlist_cfg(struct wiphy *wiphy, + nla_for_each_attr(iter, data, len, tmp2) { + type = nla_type(iter); + switch (type) { +- case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS: +- pbssid = hotlist_params->bssid; +- nla_for_each_nested(outer, iter, tmp) { +- nla_for_each_nested(inner, outer, tmp1) { +- type = nla_type(inner); ++ case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS: ++ pbssid = hotlist_params->bssid; ++ nla_for_each_nested(outer, iter, tmp) { ++ nla_for_each_nested(inner, outer, tmp1) { ++ type = nla_type(inner); + +- switch (type) { +- case GSCAN_ATTRIBUTE_BSSID: +- memcpy(&(pbssid[j].macaddr), +- nla_data(inner), ETHER_ADDR_LEN); +- break; +- case GSCAN_ATTRIBUTE_RSSI_LOW: +- pbssid[j].rssi_reporting_threshold = +- (int8) nla_get_u8(inner); +- break; +- case GSCAN_ATTRIBUTE_RSSI_HIGH: +- dummy = (int8) nla_get_u8(inner); +- break; ++ switch (type) { ++ case GSCAN_ATTRIBUTE_BSSID: ++ if (nla_len(inner) != sizeof(pbssid[j].macaddr)) { ++ WL_DBG(("type:%d length:%d not matching.\n", ++ type, nla_len(inner))); ++ err = -EINVAL; ++ goto exit; + } ++ memcpy( ++ &pbssid[j].macaddr, ++ nla_data(inner), ++ sizeof(pbssid[j].macaddr)); ++ break; ++ case GSCAN_ATTRIBUTE_RSSI_LOW: ++ if (nla_len(inner) != sizeof(uint8)) { ++ WL_DBG(("type:%d length:%d not matching.\n", ++ type, nla_len(inner))); ++ err = -EINVAL; ++ goto exit; ++ } ++ pbssid[j].rssi_reporting_threshold = ++ (int8)nla_get_u8(inner); ++ break; ++ case GSCAN_ATTRIBUTE_RSSI_HIGH: ++ if (nla_len(inner) != sizeof(uint8)) { ++ WL_DBG(("type:%d length:%d not matching.\n", ++ type, nla_len(inner))); ++ err = -EINVAL; ++ goto exit; ++ } ++ dummy = (int8)nla_get_u8(inner); ++ break; + } +- j++; ++ } ++ if (++j > PFN_SWC_MAX_NUM_APS) { ++ WL_DBG(("nbssid:%d exeed limit.\n", ++ hotlist_params->nbssid)); ++ err = -EINVAL; ++ goto exit; + } + hotlist_params->nbssid = j; +- break; +- case GSCAN_ATTRIBUTE_HOTLIST_FLUSH: +- flush = (bool) nla_get_u8(iter); +- break; +- case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE: +- hotlist_params->lost_ap_window = nla_get_u32(iter); +- break; + } ++ break; ++ case GSCAN_ATTRIBUTE_HOTLIST_FLUSH: ++ if (nla_len(iter) != sizeof(uint8)) { ++ WL_DBG(("type:%d length:%d not matching.\n", ++ type, nla_len(inner))); ++ err = -EINVAL; ++ goto exit; ++ } ++ flush = nla_get_u8(iter); ++ break; ++ case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE: ++ if (nla_len(iter) != sizeof(uint32)) { ++ WL_DBG(("type:%d length:%d not matching.\n", ++ type, nla_len(inner))); ++ err = -EINVAL; ++ goto exit; ++ } ++ hotlist_params->lost_ap_window = (uint16)nla_get_u32(iter); ++ break; ++ default: ++ WL_DBG(("Unknown type %d\n", type)); ++ err = -EINVAL; ++ goto exit; ++ } + + } + \ No newline at end of file diff --git a/patches/3.10/CVE-2016-8466.patch b/patches/3.10/CVE-2016-8466.patch new file mode 100644 index 0000000..7142c05 --- /dev/null +++ b/patches/3.10/CVE-2016-8466.patch @@ -0,0 +1,101 @@ +From 50ba575e9cd28ab9537f0961bbc051a6a727da74 Mon Sep 17 00:00:00 2001 +From: Insun Song +Date: Wed, 30 Nov 2016 12:00:17 -0800 +Subject: [PATCH] net: wireless: bcmdhd: fix hotlist index in + wl_cfgvendor_hotlist_cfg + +add bssid count element to exactly refer in NL-TLV parsing. + +This change need to sync with +/hardware/broadcom/wlan/bcmdhd/wifi_hal/gscan.cpp +where GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT supposed to be called. + +Bug: 32474971 + +Signed-off-by: Insun Song +Change-Id: Id2b019bb43fb99b3843fe1b32f59e58c7af7cdad +--- + drivers/net/wireless/bcmdhd/wl_cfgvendor.c | 39 ++++++++++++++++++++++++------ + drivers/net/wireless/bcmdhd/wl_cfgvendor.h | 1 + + 2 files changed, 32 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +index b156660ed053a..9a73de20f1298 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.c ++++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.c +@@ -705,7 +705,7 @@ static int wl_cfgvendor_hotlist_cfg(struct wiphy *wiphy, + GFP_KERNEL); + + if (!hotlist_params) { +- WL_ERR(("Cannot Malloc mem to parse config commands size - %d bytes \n", len)); ++ WL_ERR(("Cannot Malloc mem.\n")); + return -ENOMEM; + } + +@@ -714,10 +714,33 @@ static int wl_cfgvendor_hotlist_cfg(struct wiphy *wiphy, + nla_for_each_attr(iter, data, len, tmp2) { + type = nla_type(iter); + switch (type) { ++ case GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT: ++ if (nla_len(iter) != sizeof(uint32)) { ++ WL_DBG(("type:%d length:%d not matching.\n", ++ type, nla_len(inner))); ++ err = -EINVAL; ++ goto exit; ++ } ++ hotlist_params->nbssid = (uint16)nla_get_u32(iter); ++ if ((hotlist_params->nbssid == 0) || ++ (hotlist_params->nbssid > PFN_SWC_MAX_NUM_APS)) { ++ WL_ERR(("nbssid:%d exceed limit.\n", ++ hotlist_params->nbssid)); ++ err = -EINVAL; ++ goto exit; ++ } ++ break; + case GSCAN_ATTRIBUTE_HOTLIST_BSSIDS: ++ if (hotlist_params->nbssid == 0) { ++ WL_ERR(("nbssid not retrieved.\n")); ++ err = -EINVAL; ++ goto exit; ++ } + pbssid = hotlist_params->bssid; + nla_for_each_nested(outer, iter, tmp) { + nla_for_each_nested(inner, outer, tmp1) { ++ if (j >= hotlist_params->nbssid) ++ break; + type = nla_type(inner); + + switch (type) { +@@ -754,13 +777,13 @@ static int wl_cfgvendor_hotlist_cfg(struct wiphy *wiphy, + break; + } + } +- if (++j > PFN_SWC_MAX_NUM_APS) { +- WL_DBG(("nbssid:%d exeed limit.\n", +- hotlist_params->nbssid)); +- err = -EINVAL; +- goto exit; +- } +- hotlist_params->nbssid = j; ++ j++; ++ } ++ if (j != hotlist_params->nbssid) { ++ WL_ERR(("bssid_cnt:%d != nbssid:%d.\n", j, ++ hotlist_params->nbssid)); ++ err = -EINVAL; ++ goto exit; + } + break; + case GSCAN_ATTRIBUTE_HOTLIST_FLUSH: +diff --git a/drivers/net/wireless/bcmdhd/wl_cfgvendor.h b/drivers/net/wireless/bcmdhd/wl_cfgvendor.h +index e6cb53a1de087..e15666f720e50 100644 +--- a/drivers/net/wireless/bcmdhd/wl_cfgvendor.h ++++ b/drivers/net/wireless/bcmdhd/wl_cfgvendor.h +@@ -203,6 +203,7 @@ enum gscan_attributes { + GSCAN_ATTRIBUTE_RSSI_HIGH, + GSCAN_ATTRIBUTE_HOSTLIST_BSSID_ELEM, + GSCAN_ATTRIBUTE_HOTLIST_FLUSH, ++ GSCAN_ATTRIBUTE_HOTLIST_BSSID_COUNT, + + /* remaining reserved for additional attributes */ + GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60, \ No newline at end of file diff --git a/patches/3.10/CVE-2016-8473.patch b/patches/3.10/CVE-2016-8473.patch new file mode 100644 index 0000000..361a77f --- /dev/null +++ b/patches/3.10/CVE-2016-8473.patch @@ -0,0 +1,46 @@ +From 900b8b72c57cefebb39c150dfddfdd493a1cea79 Mon Sep 17 00:00:00 2001 +From: Steve Pfetsch +Date: Mon, 7 Nov 2016 16:20:11 -0800 +Subject: [PATCH] input: ldaf: Initialize buffers before use. + +Prevent writing uninitialized stack data to calibration files by +zeroing out buffers upon creation. + +Bug: 31799972 +Bug: 31795790 +Change-Id: Ic848d4d1e181818f461e4b61ad73ada28a474bd1 +--- + drivers/input/misc/vl6180/stmvl6180_module.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/input/misc/vl6180/stmvl6180_module.c b/drivers/input/misc/vl6180/stmvl6180_module.c +index c61cc0f063424..78bc7f6844c33 100755 +--- a/drivers/input/misc/vl6180/stmvl6180_module.c ++++ b/drivers/input/misc/vl6180/stmvl6180_module.c +@@ -107,7 +107,7 @@ static int stmvl6180_stop(struct stmvl6180_data *data); + static void stmvl6180_read_calibration_file(void) + { + struct file *f; +- char buf[8]; ++ char buf[8] = {0}; + mm_segment_t fs; + int i, is_sign = 0; + +@@ -184,7 +184,7 @@ static void stmvl6180_read_calibration_file(void) + static void stmvl6180_write_offset_calibration_file(void) + { + struct file *f = NULL; +- char buf[8]; ++ char buf[8] = {0}; + mm_segment_t fs; + + f = filp_open(CAL_FILE_OFFSET, O_CREAT | O_TRUNC | O_RDWR, +@@ -207,7 +207,7 @@ static void stmvl6180_write_offset_calibration_file(void) + static void stmvl6180_write_xtalk_calibration_file(void) + { + struct file *f = NULL; +- char buf[8]; ++ char buf[8] = {0}; + mm_segment_t fs; + + f = filp_open(CAL_FILE_XTALK, O_CREAT | O_TRUNC | O_RDWR, \ No newline at end of file diff --git a/patches/3.10/CVE-2016-8474.patch b/patches/3.10/CVE-2016-8474.patch new file mode 100644 index 0000000..361a77f --- /dev/null +++ b/patches/3.10/CVE-2016-8474.patch @@ -0,0 +1,46 @@ +From 900b8b72c57cefebb39c150dfddfdd493a1cea79 Mon Sep 17 00:00:00 2001 +From: Steve Pfetsch +Date: Mon, 7 Nov 2016 16:20:11 -0800 +Subject: [PATCH] input: ldaf: Initialize buffers before use. + +Prevent writing uninitialized stack data to calibration files by +zeroing out buffers upon creation. + +Bug: 31799972 +Bug: 31795790 +Change-Id: Ic848d4d1e181818f461e4b61ad73ada28a474bd1 +--- + drivers/input/misc/vl6180/stmvl6180_module.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/input/misc/vl6180/stmvl6180_module.c b/drivers/input/misc/vl6180/stmvl6180_module.c +index c61cc0f063424..78bc7f6844c33 100755 +--- a/drivers/input/misc/vl6180/stmvl6180_module.c ++++ b/drivers/input/misc/vl6180/stmvl6180_module.c +@@ -107,7 +107,7 @@ static int stmvl6180_stop(struct stmvl6180_data *data); + static void stmvl6180_read_calibration_file(void) + { + struct file *f; +- char buf[8]; ++ char buf[8] = {0}; + mm_segment_t fs; + int i, is_sign = 0; + +@@ -184,7 +184,7 @@ static void stmvl6180_read_calibration_file(void) + static void stmvl6180_write_offset_calibration_file(void) + { + struct file *f = NULL; +- char buf[8]; ++ char buf[8] = {0}; + mm_segment_t fs; + + f = filp_open(CAL_FILE_OFFSET, O_CREAT | O_TRUNC | O_RDWR, +@@ -207,7 +207,7 @@ static void stmvl6180_write_offset_calibration_file(void) + static void stmvl6180_write_xtalk_calibration_file(void) + { + struct file *f = NULL; +- char buf[8]; ++ char buf[8] = {0}; + mm_segment_t fs; + + f = filp_open(CAL_FILE_XTALK, O_CREAT | O_TRUNC | O_RDWR, \ No newline at end of file diff --git a/patches/3.10/CVE-2016-9555.patch b/patches/3.10/CVE-2016-9555.patch new file mode 100644 index 0000000..69cef52 --- /dev/null +++ b/patches/3.10/CVE-2016-9555.patch @@ -0,0 +1,54 @@ +From bf911e985d6bbaa328c20c3e05f4eb03de11fdd6 Mon Sep 17 00:00:00 2001 +From: Marcelo Ricardo Leitner +Date: Tue, 25 Oct 2016 14:27:39 -0200 +Subject: [PATCH] sctp: validate chunk len before actually using it + +Andrey Konovalov reported that KASAN detected that SCTP was using a slab +beyond the boundaries. It was caused because when handling out of the +blue packets in function sctp_sf_ootb() it was checking the chunk len +only after already processing the first chunk, validating only for the +2nd and subsequent ones. + +The fix is to just move the check upwards so it's also validated for the +1st chunk. + +Reported-by: Andrey Konovalov +Tested-by: Andrey Konovalov +Signed-off-by: Marcelo Ricardo Leitner +Reviewed-by: Xin Long +Acked-by: Neil Horman +Signed-off-by: David S. Miller +--- + net/sctp/sm_statefuns.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c +index 026e3bca4a94b..8ec20a64a3f80 100644 +--- a/net/sctp/sm_statefuns.c ++++ b/net/sctp/sm_statefuns.c +@@ -3422,6 +3422,12 @@ sctp_disposition_t sctp_sf_ootb(struct net *net, + return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, + commands); + ++ /* Report violation if chunk len overflows */ ++ ch_end = ((__u8 *)ch) + SCTP_PAD4(ntohs(ch->length)); ++ if (ch_end > skb_tail_pointer(skb)) ++ return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, ++ commands); ++ + /* Now that we know we at least have a chunk header, + * do things that are type appropriate. + */ +@@ -3453,12 +3459,6 @@ sctp_disposition_t sctp_sf_ootb(struct net *net, + } + } + +- /* Report violation if chunk len overflows */ +- ch_end = ((__u8 *)ch) + SCTP_PAD4(ntohs(ch->length)); +- if (ch_end > skb_tail_pointer(skb)) +- return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, +- commands); +- + ch = (sctp_chunkhdr_t *) ch_end; + } while (ch_end < skb_tail_pointer(skb)); + \ No newline at end of file diff --git a/patches/3.10/CVE-2017-0510.patch b/patches/3.10/CVE-2017-0510.patch new file mode 100644 index 0000000..2214c43 --- /dev/null +++ b/patches/3.10/CVE-2017-0510.patch @@ -0,0 +1,205 @@ +From d4dfd82835bb6f92de3bfb8a1cbf6beaf892ad08 Mon Sep 17 00:00:00 2001 +From: Mark Salyzyn +Date: Tue, 20 Dec 2016 15:59:19 -0800 +Subject: android: fiq_debugger: restrict access to critical commands. + +Sysrq must be enabled via /proc/sys/kernel/sysrq as a security +measure to enable various critical fiq debugger commands that +either leak information or can be used as a system attack. + +Default disabled, this will leave the reboot, reset, irqs, sleep, +nosleep, console and ps commands. Reboot and reset commands +will be restricted from taking any parameters. We will also +switch to showing the limited command set in this mode. + +Signed-off-by: Mark Salyzyn +Bug: 32402555 +Change-Id: I3f74b1ff5e4971d619bcb37a911fed68fbb538d5 +[d-cagle@codeaurora.org: Resolve merge conflict] +Git-repo: https://android.googlesource.com/kernel/msm +Git-commit: 1031836c0895f1f5a05c25efec83bfa11aa08ca9 +Signed-off-by: Dennis Cagle +--- + .../staging/android/fiq_debugger/fiq_debugger.c | 86 ++++++++++++++-------- + drivers/tty/sysrq.c | 3 +- + include/linux/sysrq.h | 1 + + 3 files changed, 57 insertions(+), 33 deletions(-) + +diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger.c b/drivers/staging/android/fiq_debugger/fiq_debugger.c +index 7d6b4ae..ceb45bc9e 100644 +--- a/drivers/staging/android/fiq_debugger/fiq_debugger.c ++++ b/drivers/staging/android/fiq_debugger/fiq_debugger.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -395,7 +396,7 @@ static void fiq_debugger_work(struct work_struct *work) + cmd += 6; + while (*cmd == ' ') + cmd++; +- if (cmd != '\0') ++ if ((cmd != '\0') && sysrq_on()) + kernel_restart(cmd); + else + kernel_restart(NULL); +@@ -425,29 +426,39 @@ static void fiq_debugger_irq_exec(struct fiq_debugger_state *state, char *cmd) + static void fiq_debugger_help(struct fiq_debugger_state *state) + { + fiq_debugger_printf(&state->output, +- "FIQ Debugger commands:\n" +- " pc PC status\n" +- " regs Register dump\n" +- " allregs Extended Register dump\n" +- " bt Stack trace\n" +- " reboot [] Reboot with command \n" +- " reset [] Hard reset with command \n" +- " irqs Interupt status\n" +- " kmsg Kernel log\n" +- " version Kernel version\n"); +- fiq_debugger_printf(&state->output, +- " sleep Allow sleep while in FIQ\n" +- " nosleep Disable sleep while in FIQ\n" +- " console Switch terminal to console\n" +- " cpu Current CPU\n" +- " cpu Switch to CPU\n"); ++ "FIQ Debugger commands:\n"); ++ if (sysrq_on()) { ++ fiq_debugger_printf(&state->output, ++ " pc PC status\n" ++ " regs Register dump\n" ++ " allregs Extended Register dump\n" ++ " bt Stack trace\n"); ++ fiq_debugger_printf(&state->output, ++ " reboot [] Reboot with command \n" ++ " reset [] Hard reset with command \n" ++ " irqs Interrupt status\n" ++ " kmsg Kernel log\n" ++ " version Kernel version\n"); ++ fiq_debugger_printf(&state->output, ++ " cpu Current CPU\n" ++ " cpu Switch to CPU\n" ++ " sysrq sysrq options\n" ++ " sysrq Execute sysrq with \n"); ++ } else { ++ fiq_debugger_printf(&state->output, ++ " reboot Reboot\n" ++ " reset Hard reset\n" ++ " irqs Interrupt status\n"); ++ } + fiq_debugger_printf(&state->output, +- " ps Process list\n" +- " sysrq sysrq options\n" +- " sysrq Execute sysrq with \n"); ++ " sleep Allow sleep while in FIQ\n" ++ " nosleep Disable sleep while in FIQ\n" ++ " console Switch terminal to console\n" ++ " ps Process list\n"); + #ifdef CONFIG_KGDB +- fiq_debugger_printf(&state->output, +- " kgdb Enter kernel debugger\n"); ++ if (fiq_kgdb_enable) { ++ fiq_debugger_printf(&state->output, ++ " kgdb Enter kernel debugger\n"); + #endif + } + +@@ -479,18 +490,23 @@ static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state, + if (!strcmp(cmd, "help") || !strcmp(cmd, "?")) { + fiq_debugger_help(state); + } else if (!strcmp(cmd, "pc")) { +- fiq_debugger_dump_pc(&state->output, regs); ++ if (sysrq_on()) ++ fiq_debugger_dump_pc(&state->output, regs); + } else if (!strcmp(cmd, "regs")) { +- fiq_debugger_dump_regs(&state->output, regs); ++ if (sysrq_on()) ++ fiq_debugger_dump_regs(&state->output, regs); + } else if (!strcmp(cmd, "allregs")) { +- fiq_debugger_dump_allregs(&state->output, regs); ++ if (sysrq_on()) ++ fiq_debugger_dump_allregs(&state->output, regs); + } else if (!strcmp(cmd, "bt")) { +- fiq_debugger_dump_stacktrace(&state->output, regs, 100, svc_sp); ++ if (sysrq_on()) ++ fiq_debugger_dump_stacktrace(&state->output, regs, ++ 100, svc_sp); + } else if (!strncmp(cmd, "reset", 5)) { + cmd += 5; + while (*cmd == ' ') + cmd++; +- if (*cmd) { ++ if (*cmd && sysrq_on()) { + char tmp_cmd[32]; + strlcpy(tmp_cmd, cmd, sizeof(tmp_cmd)); + machine_restart(tmp_cmd); +@@ -500,9 +516,12 @@ static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state, + } else if (!strcmp(cmd, "irqs")) { + fiq_debugger_dump_irqs(state); + } else if (!strcmp(cmd, "kmsg")) { +- fiq_debugger_dump_kernel_log(state); ++ if (sysrq_on()) ++ fiq_debugger_dump_kernel_log(state); + } else if (!strcmp(cmd, "version")) { +- fiq_debugger_printf(&state->output, "%s\n", linux_banner); ++ if (sysrq_on()) ++ fiq_debugger_printf(&state->output, "%s\n", ++ linux_banner); + } else if (!strcmp(cmd, "sleep")) { + state->no_sleep = false; + fiq_debugger_printf(&state->output, "enabling sleep\n"); +@@ -514,14 +533,17 @@ static bool fiq_debugger_fiq_exec(struct fiq_debugger_state *state, + fiq_debugger_uart_flush(state); + state->console_enable = true; + } else if (!strcmp(cmd, "cpu")) { +- fiq_debugger_printf(&state->output, "cpu %d\n", state->current_cpu); +- } else if (!strncmp(cmd, "cpu ", 4)) { ++ if (sysrq_on()) ++ fiq_debugger_printf(&state->output, "cpu %d\n", ++ state->current_cpu); ++ } else if (!strncmp(cmd, "cpu ", 4) && sysrq_on()) { + unsigned long cpu = 0; + if (strict_strtoul(cmd + 4, 10, &cpu) == 0) + fiq_debugger_switch_cpu(state, cpu); + else + fiq_debugger_printf(&state->output, "invalid cpu\n"); +- fiq_debugger_printf(&state->output, "cpu %d\n", state->current_cpu); ++ fiq_debugger_printf(&state->output, "cpu %d\n", ++ state->current_cpu); + } else { + if (state->debug_busy) { + fiq_debugger_printf(&state->output, +diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c +index b51c154..08c9406 100644 +--- a/drivers/tty/sysrq.c ++++ b/drivers/tty/sysrq.c +@@ -55,10 +55,11 @@ static bool __read_mostly sysrq_always_enabled; + unsigned short platform_sysrq_reset_seq[] __weak = { KEY_RESERVED }; + int sysrq_reset_downtime_ms __weak; + +-static bool sysrq_on(void) ++bool sysrq_on(void) + { + return sysrq_enabled || sysrq_always_enabled; + } ++EXPORT_SYMBOL(sysrq_on); + + /* + * A value of 1 means 'all', other nonzero values are an op mask: +diff --git a/include/linux/sysrq.h b/include/linux/sysrq.h +index 7faf933..5a0bd93 100644 +--- a/include/linux/sysrq.h ++++ b/include/linux/sysrq.h +@@ -45,6 +45,7 @@ struct sysrq_key_op { + * are available -- else NULL's). + */ + ++bool sysrq_on(void); + void handle_sysrq(int key); + void __handle_sysrq(int key, bool check_mask); + int register_sysrq_key(int key, struct sysrq_key_op *op); +-- +cgit v1.1